mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
chore: refactor frontend components folder
This commit is contained in:
parent
46f016f661
commit
5a746a946d
106 changed files with 159 additions and 164 deletions
90
apps/web/components/Dashboard/Misc/BreadCrumbs.tsx
Normal file
90
apps/web/components/Dashboard/Misc/BreadCrumbs.tsx
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
'use client';
|
||||
import { useOrg } from '@components/Contexts/OrgContext';
|
||||
import { Backpack, Book, ChevronRight, CreditCard, School, User, Users } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
|
||||
type BreadCrumbsProps = {
|
||||
type: 'courses' | 'user' | 'users' | 'org' | 'orgusers' | 'assignments' | 'payments'
|
||||
last_breadcrumb?: string
|
||||
}
|
||||
|
||||
function BreadCrumbs(props: BreadCrumbsProps) {
|
||||
const org = useOrg() as any
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="h-7"></div>
|
||||
<div className="text-gray-400 tracking-tight font-medium text-sm flex space-x-1">
|
||||
<div className="flex items-center space-x-1">
|
||||
{props.type == 'courses' ? (
|
||||
<div className="flex space-x-2 items-center">
|
||||
{' '}
|
||||
<Book className="text-gray" size={14}></Book>
|
||||
<Link href="/dash/courses">Courses</Link>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{props.type == 'assignments' ? (
|
||||
<div className="flex space-x-2 items-center">
|
||||
{' '}
|
||||
<Backpack className="text-gray" size={14}></Backpack>
|
||||
<Link href="/dash/assignments">Assignments</Link>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{props.type == 'user' ? (
|
||||
<div className="flex space-x-2 items-center">
|
||||
{' '}
|
||||
<User className="text-gray" size={14}></User>
|
||||
<Link href="/dash/user-account/settings/general">
|
||||
Account Settings
|
||||
</Link>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{props.type == 'orgusers' ? (
|
||||
<div className="flex space-x-2 items-center">
|
||||
{' '}
|
||||
<Users className="text-gray" size={14}></Users>
|
||||
<Link href="/dash/users/settings/users">Organization users</Link>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
{props.type == 'org' ? (
|
||||
<div className="flex space-x-2 items-center">
|
||||
{' '}
|
||||
<School className="text-gray" size={14}></School>
|
||||
<Link href="/dash/users">Organization Settings</Link>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{props.type == 'payments' ? (
|
||||
<div className="flex space-x-2 items-center">
|
||||
{' '}
|
||||
<CreditCard className="text-gray" size={14}></CreditCard>
|
||||
<Link href="/dash/payments">Payments</Link>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<div className="flex items-center space-x-1 first-letter:uppercase">
|
||||
{props.last_breadcrumb ? <ChevronRight size={17} /> : ''}
|
||||
<div className="first-letter:uppercase">
|
||||
{' '}
|
||||
{props.last_breadcrumb}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BreadCrumbs
|
||||
66
apps/web/components/Dashboard/Misc/CourseOverviewTop.tsx
Normal file
66
apps/web/components/Dashboard/Misc/CourseOverviewTop.tsx
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { useCourse } from '@components/Contexts/CourseContext'
|
||||
import { useEffect } from 'react'
|
||||
import BreadCrumbs from './BreadCrumbs'
|
||||
import SaveState from './SaveState'
|
||||
import { CourseOverviewParams } from 'app/orgs/[orgslug]/dash/courses/course/[courseuuid]/[subpage]/page'
|
||||
import { getUriWithOrg } from '@services/config/config'
|
||||
import { useOrg } from '@components/Contexts/OrgContext'
|
||||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import EmptyThumbnailImage from '../../../public/empty_thumbnail.png'
|
||||
|
||||
export function CourseOverviewTop({
|
||||
params,
|
||||
}: {
|
||||
params: CourseOverviewParams
|
||||
}) {
|
||||
const course = useCourse() as any
|
||||
const org = useOrg() as any
|
||||
|
||||
useEffect(() => {}, [course, org])
|
||||
|
||||
return (
|
||||
<>
|
||||
<BreadCrumbs
|
||||
type="courses"
|
||||
last_breadcrumb={course.courseStructure.name}
|
||||
></BreadCrumbs>
|
||||
<div className="flex">
|
||||
<div className="flex py-3 grow items-center">
|
||||
<Link
|
||||
href={getUriWithOrg(org?.slug, '') + `/course/${params.courseuuid}`}
|
||||
>
|
||||
{course?.courseStructure?.thumbnail_image ? (
|
||||
<img
|
||||
className="w-[100px] h-[57px] rounded-md drop-shadow-md"
|
||||
src={`${getCourseThumbnailMediaDirectory(
|
||||
org?.org_uuid,
|
||||
'course_' + params.courseuuid,
|
||||
course.courseStructure.thumbnail_image
|
||||
)}`}
|
||||
alt=""
|
||||
/>
|
||||
) : (
|
||||
<Image
|
||||
width={100}
|
||||
className="h-[57px] rounded-md drop-shadow-md"
|
||||
src={EmptyThumbnailImage}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
<div className="flex flex-col course_metadata justify-center pl-5">
|
||||
<div className="text-gray-400 font-semibold text-sm">Course</div>
|
||||
<div className="text-black font-bold text-xl -mt-1 first-letter:uppercase">
|
||||
{course.courseStructure.name}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<SaveState orgslug={params.orgslug} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
131
apps/web/components/Dashboard/Misc/SaveState.tsx
Normal file
131
apps/web/components/Dashboard/Misc/SaveState.tsx
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
'use client'
|
||||
import { getAPIUrl } from '@services/config/config'
|
||||
import { updateCourseOrderStructure } from '@services/courses/chapters'
|
||||
import { revalidateTags } from '@services/utils/ts/requests'
|
||||
import {
|
||||
useCourse,
|
||||
useCourseDispatch,
|
||||
} from '@components/Contexts/CourseContext'
|
||||
import { Check, SaveAllIcon, Timer } from 'lucide-react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import React, { useEffect } from 'react'
|
||||
import { mutate } from 'swr'
|
||||
import { updateCourse } from '@services/courses/courses'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
function SaveState(props: { orgslug: string }) {
|
||||
const course = useCourse() as any
|
||||
const session = useLHSession() as any;
|
||||
const router = useRouter()
|
||||
const saved = course ? course.isSaved : true
|
||||
const dispatchCourse = useCourseDispatch() as any
|
||||
const course_structure = course.courseStructure
|
||||
|
||||
const saveCourseState = async () => {
|
||||
// Course order
|
||||
if (saved) return
|
||||
await changeOrderBackend()
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
// Course metadata
|
||||
await changeMetadataBackend()
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
dispatchCourse({ type: 'setIsSaved' })
|
||||
}
|
||||
|
||||
//
|
||||
// Course Order
|
||||
const changeOrderBackend = async () => {
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
await updateCourseOrderStructure(
|
||||
course.courseStructure.course_uuid,
|
||||
course.courseOrder,
|
||||
session.data?.tokens?.access_token
|
||||
)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
dispatchCourse({ type: 'setIsSaved' })
|
||||
}
|
||||
|
||||
// Course metadata
|
||||
const changeMetadataBackend = async () => {
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
await updateCourse(
|
||||
course.courseStructure.course_uuid,
|
||||
course.courseStructure,
|
||||
session.data?.tokens?.access_token
|
||||
)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
dispatchCourse({ type: 'setIsSaved' })
|
||||
}
|
||||
|
||||
const handleCourseOrder = (course_structure: any) => {
|
||||
const chapters = course_structure.chapters
|
||||
const chapter_order_by_ids = chapters.map((chapter: any) => {
|
||||
return {
|
||||
chapter_id: chapter.id,
|
||||
activities_order_by_ids: chapter.activities.map((activity: any) => {
|
||||
return {
|
||||
activity_id: activity.id,
|
||||
}
|
||||
}),
|
||||
}
|
||||
})
|
||||
dispatchCourse({
|
||||
type: 'setCourseOrder',
|
||||
payload: { chapter_order_by_ids: chapter_order_by_ids },
|
||||
})
|
||||
dispatchCourse({ type: 'setIsNotSaved' })
|
||||
}
|
||||
|
||||
const initOrderPayload = () => {
|
||||
if (course_structure && course_structure.chapters) {
|
||||
handleCourseOrder(course_structure)
|
||||
dispatchCourse({ type: 'setIsSaved' })
|
||||
}
|
||||
}
|
||||
|
||||
const changeOrderPayload = () => {
|
||||
if (course_structure && course_structure.chapters) {
|
||||
handleCourseOrder(course_structure)
|
||||
dispatchCourse({ type: 'setIsNotSaved' })
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (course_structure?.chapters) {
|
||||
initOrderPayload()
|
||||
}
|
||||
if (course_structure?.chapters && !saved) {
|
||||
changeOrderPayload()
|
||||
}
|
||||
}, [course_structure]) // This effect depends on the `course_structure` variable
|
||||
|
||||
return (
|
||||
<div className="flex space-x-4">
|
||||
{saved ? (
|
||||
<></>
|
||||
) : (
|
||||
<div className="text-gray-600 flex space-x-2 items-center antialiased">
|
||||
<Timer size={15} />
|
||||
<div>Unsaved changes</div>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={
|
||||
`px-4 py-2 rounded-lg drop-shadow-md cursor-pointer flex space-x-2 items-center font-bold antialiased transition-all ease-linear ` +
|
||||
(saved
|
||||
? 'bg-gray-600 text-white'
|
||||
: 'bg-black text-white border hover:bg-gray-900 ')
|
||||
}
|
||||
onClick={saveCourseState}
|
||||
>
|
||||
{saved ? <Check size={20} /> : <SaveAllIcon size={20} />}
|
||||
{saved ? <div className="">Saved</div> : <div className="">Save</div>}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SaveState
|
||||
Loading…
Add table
Add a link
Reference in a new issue