mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
chore: merge with dev
This commit is contained in:
parent
b678ac86e8
commit
3430cfdb3a
34 changed files with 3515 additions and 2600 deletions
|
|
@ -74,87 +74,84 @@ const CollectionsPage = async (params: any) => {
|
|||
|
||||
return (
|
||||
<GeneralWrapperStyled>
|
||||
<div className="flex justify-between">
|
||||
<TypeOfContentTitle title="Collections" type="col" />
|
||||
<AuthenticatedClientElement
|
||||
ressourceType="collections"
|
||||
action="create"
|
||||
checkMethod="roles"
|
||||
orgId={org_id}
|
||||
>
|
||||
<Link
|
||||
className="flex justify-center"
|
||||
href={getUriWithOrg(orgslug, '/collections/new')}
|
||||
<div className="flex flex-col space-y-4 mb-8">
|
||||
<div className="flex items-center justify-between">
|
||||
<TypeOfContentTitle title="Collections" type="col" />
|
||||
<AuthenticatedClientElement
|
||||
ressourceType="collections"
|
||||
action="create"
|
||||
checkMethod="roles"
|
||||
orgId={org_id}
|
||||
>
|
||||
<NewCollectionButton />
|
||||
</Link>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
<div className="home_collections flex flex-wrap">
|
||||
{collections.map((collection: any) => (
|
||||
<div
|
||||
className="flex flex-col py-1 px-3"
|
||||
key={collection.collection_uuid}
|
||||
>
|
||||
<CollectionThumbnail
|
||||
collection={collection}
|
||||
orgslug={orgslug}
|
||||
org_id={org_id}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{collections.length == 0 && (
|
||||
<div className="flex mx-auto h-[400px]">
|
||||
<div className="flex flex-col justify-center text-center items-center space-y-5">
|
||||
<div className="mx-auto">
|
||||
<svg
|
||||
width="120"
|
||||
height="120"
|
||||
viewBox="0 0 295 295"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
opacity="0.51"
|
||||
x="10"
|
||||
y="10"
|
||||
width="275"
|
||||
height="275"
|
||||
rx="75"
|
||||
stroke="#4B5564"
|
||||
strokeOpacity="0.15"
|
||||
strokeWidth="20"
|
||||
/>
|
||||
<path
|
||||
d="M135.8 200.8V130L122.2 114.6L135.8 110.4V102.8L122.2 87.4L159.8 76V200.8L174.6 218H121L135.8 200.8Z"
|
||||
fill="#4B5564"
|
||||
fillOpacity="0.08"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="space-y-0">
|
||||
<h1 className="text-3xl font-bold text-gray-600">
|
||||
<Link href={getUriWithOrg(orgslug, '/collections/new')}>
|
||||
<NewCollectionButton />
|
||||
</Link>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{collections.map((collection: any) => (
|
||||
<div key={collection.collection_uuid} className="p-3">
|
||||
<CollectionThumbnail
|
||||
collection={collection}
|
||||
orgslug={orgslug}
|
||||
org_id={org_id}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{collections.length === 0 && (
|
||||
<div className="col-span-full flex justify-center items-center py-8">
|
||||
<div className="text-center">
|
||||
<div className="mb-4">
|
||||
<svg
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 295 295"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mx-auto"
|
||||
>
|
||||
<rect
|
||||
opacity="0.51"
|
||||
x="10"
|
||||
y="10"
|
||||
width="275"
|
||||
height="275"
|
||||
rx="75"
|
||||
stroke="#4B5564"
|
||||
strokeOpacity="0.15"
|
||||
strokeWidth="20"
|
||||
/>
|
||||
<path
|
||||
d="M135.8 200.8V130L122.2 114.6L135.8 110.4V102.8L122.2 87.4L159.8 76V200.8L174.6 218H121L135.8 200.8Z"
|
||||
fill="#4B5564"
|
||||
fillOpacity="0.08"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1 className="text-xl font-bold text-gray-600 mb-2">
|
||||
No collections yet
|
||||
</h1>
|
||||
<p className="text-lg text-gray-400">
|
||||
<p className="text-md text-gray-400">
|
||||
<ContentPlaceHolderIfUserIsNotAdmin
|
||||
text="Create a collection to add content"
|
||||
/>
|
||||
</p>
|
||||
<div className="mt-4">
|
||||
<AuthenticatedClientElement
|
||||
checkMethod="roles"
|
||||
ressourceType="collections"
|
||||
action="create"
|
||||
orgId={org_id}
|
||||
>
|
||||
<Link href={getUriWithOrg(orgslug, '/collections/new')}>
|
||||
<NewCollectionButton />
|
||||
</Link>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
</div>
|
||||
<AuthenticatedClientElement
|
||||
checkMethod="roles"
|
||||
ressourceType="collections"
|
||||
action="create"
|
||||
orgId={org_id}
|
||||
>
|
||||
<Link href={getUriWithOrg(orgslug, '/collections/new')}>
|
||||
<NewCollectionButton />
|
||||
</Link>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</GeneralWrapperStyled>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import AssignmentSubmissionProvider, { useAssignmentSubmission } from '@compone
|
|||
import toast from 'react-hot-toast'
|
||||
import { mutate } from 'swr'
|
||||
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal'
|
||||
import { useMediaQuery } from 'usehooks-ts'
|
||||
|
||||
interface ActivityClientProps {
|
||||
activityid: string
|
||||
|
|
@ -47,6 +48,7 @@ function ActivityClient(props: ActivityClientProps) {
|
|||
const [bgColor, setBgColor] = React.useState('bg-white')
|
||||
const [assignment, setAssignment] = React.useState(null) as any;
|
||||
const [markStatusButtonActive, setMarkStatusButtonActive] = React.useState(false);
|
||||
|
||||
|
||||
function getChapterNameByActivityId(course: any, activity_id: any) {
|
||||
for (let i = 0; i < course.chapters.length; i++) {
|
||||
|
|
@ -223,7 +225,7 @@ export function MarkStatus(props: {
|
|||
}) {
|
||||
const router = useRouter()
|
||||
const session = useLHSession() as any;
|
||||
|
||||
const isMobile = useMediaQuery('(max-width: 768px)')
|
||||
async function markActivityAsCompleteFront() {
|
||||
const trail = await markActivityAsComplete(
|
||||
props.orgslug,
|
||||
|
|
@ -263,7 +265,7 @@ export function MarkStatus(props: {
|
|||
<i>
|
||||
<Check size={17}></Check>
|
||||
</i>{' '}
|
||||
<i className="not-italic text-xs font-bold">Mark as complete</i>
|
||||
{!isMobile && <i className="not-italic text-xs font-bold">Mark as complete</i>}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import UserAvatar from '@components/Objects/UserAvatar'
|
|||
import CourseUpdates from '@components/Objects/CourseUpdates/CourseUpdates'
|
||||
import { CourseProvider } from '@components/Contexts/CourseContext'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { useMediaQuery } from 'usehooks-ts'
|
||||
|
||||
const CourseClient = (props: any) => {
|
||||
const [user, setUser] = useState<any>({})
|
||||
|
|
@ -28,6 +29,7 @@ const CourseClient = (props: any) => {
|
|||
const course = props.course
|
||||
const org = useOrg() as any
|
||||
const router = useRouter()
|
||||
const isMobile = useMediaQuery('(max-width: 768px)')
|
||||
|
||||
function getLearningTags() {
|
||||
// create array of learnings from a string object (comma separated)
|
||||
|
|
@ -72,21 +74,21 @@ const CourseClient = (props: any) => {
|
|||
<PageLoading></PageLoading>
|
||||
) : (
|
||||
<GeneralWrapperStyled>
|
||||
<div className="pb-3 flex justify-between items-center">
|
||||
<div className="pb-3 flex flex-col md:flex-row justify-between items-start md:items-center">
|
||||
<div>
|
||||
<p className="text-md font-bold text-gray-400 pb-2">Course</p>
|
||||
<h1 className="text-3xl -mt-3 font-bold">{course.name}</h1>
|
||||
<h1 className="text-3xl md:text-3xl -mt-3 font-bold">{course.name}</h1>
|
||||
</div>
|
||||
<div>
|
||||
<CourseProvider courseuuid={course.course_uuid}>
|
||||
<div className="mt-4 md:mt-0">
|
||||
{!isMobile && <CourseProvider courseuuid={course.course_uuid}>
|
||||
<CourseUpdates />
|
||||
</CourseProvider>
|
||||
</CourseProvider>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{props.course?.thumbnail_image && org ? (
|
||||
<div
|
||||
className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-auto h-[400px] bg-cover bg-center mb-4"
|
||||
className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-auto h-[200px] md:h-[400px] bg-cover bg-center mb-4"
|
||||
style={{
|
||||
backgroundImage: `url(${getCourseThumbnailMediaDirectory(
|
||||
org?.org_uuid,
|
||||
|
|
@ -111,7 +113,7 @@ const CourseClient = (props: any) => {
|
|||
course={course}
|
||||
/>
|
||||
|
||||
<div className="flex flex-row pt-10">
|
||||
<div className="flex flex-col md:flex-row pt-10">
|
||||
<div className="course_metadata_left grow space-y-2">
|
||||
<h2 className="py-3 text-2xl font-bold">Description</h2>
|
||||
<div className="bg-white shadow-md shadow-gray-300/25 outline outline-1 outline-neutral-200/40 rounded-lg overflow-hidden">
|
||||
|
|
@ -141,7 +143,7 @@ const CourseClient = (props: any) => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<h2 className="py-3 text-2xl font-bold">Course Lessons</h2>
|
||||
<h2 className="py-3 text-xl md:text-2xl font-bold">Course Lessons</h2>
|
||||
<div className="bg-white shadow-md shadow-gray-300/25 outline outline-1 outline-neutral-200/40 rounded-lg overflow-hidden">
|
||||
{course.chapters.map((chapter: any) => {
|
||||
return (
|
||||
|
|
@ -303,20 +305,20 @@ const CourseClient = (props: any) => {
|
|||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="course_metadata_right space-y-3 w-72 antialiased flex flex-col ml-10 h-fit p-3 py-5 bg-white shadow-md shadow-gray-300/25 outline outline-1 outline-neutral-200/40 rounded-lg overflow-hidden">
|
||||
<div className="course_metadata_right space-y-3 w-full md:w-72 antialiased flex flex-col md:ml-10 h-fit p-3 py-5 bg-white shadow-md shadow-gray-300/25 outline outline-1 outline-neutral-200/40 rounded-lg overflow-hidden mt-6 md:mt-0">
|
||||
{user && (
|
||||
<div className="flex flex-col mx-auto space-y-3 px-2 py-2 items-center">
|
||||
<div className="flex flex-row md:flex-col mx-auto space-y-0 md:space-y-3 space-x-4 md:space-x-0 px-2 py-2 items-center">
|
||||
<UserAvatar
|
||||
border="border-8"
|
||||
avatar_url={course.authors[0].avatar_image ? getUserAvatarMediaDirectory(course.authors[0].user_uuid, course.authors[0].avatar_image) : ''}
|
||||
predefined_avatar={course.authors[0].avatar_image ? undefined : 'empty'}
|
||||
width={100}
|
||||
width={isMobile ? 60 : 100}
|
||||
/>
|
||||
<div className="-space-y-2 ">
|
||||
<div className="md:-space-y-2">
|
||||
<div className="text-[12px] text-neutral-400 font-semibold">
|
||||
Author
|
||||
</div>
|
||||
<div className="text-xl font-bold text-neutral-800">
|
||||
<div className="text-lg md:text-xl font-bold text-neutral-800">
|
||||
{course.authors[0].first_name &&
|
||||
course.authors[0].last_name && (
|
||||
<div className="flex space-x-2 items-center">
|
||||
|
|
@ -344,14 +346,14 @@ const CourseClient = (props: any) => {
|
|||
|
||||
{isCourseStarted() ? (
|
||||
<button
|
||||
className="py-2 px-5 mx-auto rounded-xl text-white font-bold h-12 w-[200px] drop-shadow-md bg-red-600 hover:bg-red-700 hover:cursor-pointer"
|
||||
className="py-2 px-5 mx-auto rounded-xl text-white font-bold h-12 w-full md:w-[200px] drop-shadow-md bg-red-600 hover:bg-red-700 hover:cursor-pointer"
|
||||
onClick={quitCourse}
|
||||
>
|
||||
Quit Course
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="py-2 px-5 mx-auto rounded-xl text-white font-bold h-12 w-[200px] drop-shadow-md bg-black hover:bg-gray-900 hover:cursor-pointer"
|
||||
className="py-2 px-5 mx-auto rounded-xl text-white font-bold h-12 w-full md:w-[200px] drop-shadow-md bg-black hover:bg-gray-900 hover:cursor-pointer"
|
||||
onClick={startCourseUI}
|
||||
>
|
||||
Start Course
|
||||
|
|
|
|||
|
|
@ -29,110 +29,102 @@ function Courses(props: CourseProps) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="w-full">
|
||||
<GeneralWrapperStyled>
|
||||
<div className="flex flex-wrap justify-between">
|
||||
<TypeOfContentTitle title="Courses" type="cou" />
|
||||
<AuthenticatedClientElement
|
||||
checkMethod="roles"
|
||||
action="create"
|
||||
ressourceType="courses"
|
||||
orgId={props.org_id}
|
||||
>
|
||||
<Modal
|
||||
isDialogOpen={newCourseModal}
|
||||
onOpenChange={setNewCourseModal}
|
||||
minHeight="md"
|
||||
dialogContent={
|
||||
<CreateCourseModal
|
||||
closeModal={closeNewCourseModal}
|
||||
orgslug={orgslug}
|
||||
></CreateCourseModal>
|
||||
}
|
||||
dialogTitle="Create Course"
|
||||
dialogDescription="Create a new course"
|
||||
dialogTrigger={
|
||||
<button>
|
||||
<NewCourseButton />
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
<div className="flex flex-col space-y-2 mb-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<TypeOfContentTitle title="Courses" type="cou" />
|
||||
<AuthenticatedClientElement
|
||||
checkMethod="roles"
|
||||
action="create"
|
||||
ressourceType="courses"
|
||||
orgId={props.org_id}
|
||||
>
|
||||
<Modal
|
||||
isDialogOpen={newCourseModal}
|
||||
onOpenChange={setNewCourseModal}
|
||||
minHeight="md"
|
||||
dialogContent={
|
||||
<CreateCourseModal
|
||||
closeModal={closeNewCourseModal}
|
||||
orgslug={orgslug}
|
||||
/>
|
||||
}
|
||||
dialogTitle="Create Course"
|
||||
dialogDescription="Create a new course"
|
||||
dialogTrigger={
|
||||
<button>
|
||||
<NewCourseButton />
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap">
|
||||
{courses.map((course: any) => (
|
||||
<div className="px-3" key={course.course_uuid}>
|
||||
<CourseThumbnail course={course} orgslug={orgslug} />
|
||||
</div>
|
||||
))}
|
||||
{courses.length == 0 && (
|
||||
<div className="flex mx-auto h-[400px]">
|
||||
<div className="flex flex-col justify-center text-center items-center space-y-5">
|
||||
<div className="mx-auto">
|
||||
<svg
|
||||
width="120"
|
||||
height="120"
|
||||
viewBox="0 0 295 295"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
opacity="0.51"
|
||||
x="10"
|
||||
y="10"
|
||||
width="275"
|
||||
height="275"
|
||||
rx="75"
|
||||
stroke="#4B5564"
|
||||
strokeOpacity="0.15"
|
||||
strokeWidth="20"
|
||||
/>
|
||||
<path
|
||||
d="M135.8 200.8V130L122.2 114.6L135.8 110.4V102.8L122.2 87.4L159.8 76V200.8L174.6 218H121L135.8 200.8Z"
|
||||
fill="#4B5564"
|
||||
fillOpacity="0.08"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="space-y-0">
|
||||
<h1 className="text-3xl font-bold text-gray-600">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{courses.map((course: any) => (
|
||||
<div key={course.course_uuid} className="p-3">
|
||||
<CourseThumbnail course={course} orgslug={orgslug} />
|
||||
</div>
|
||||
))}
|
||||
{courses.length === 0 && (
|
||||
<div className="col-span-full flex justify-center items-center py-8">
|
||||
<div className="text-center">
|
||||
<div className="mb-4">
|
||||
<svg
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 295 295"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mx-auto"
|
||||
>
|
||||
{/* ... SVG content ... */}
|
||||
</svg>
|
||||
</div>
|
||||
<h1 className="text-xl font-bold text-gray-600 mb-2">
|
||||
No courses yet
|
||||
</h1>
|
||||
{isUserAdmin ? (<p className="text-lg text-gray-400">
|
||||
Create a course to add content
|
||||
</p>) : (<p className="text-lg text-gray-400">
|
||||
No courses available yet
|
||||
</p>)}
|
||||
<p className="text-md text-gray-400">
|
||||
{isUserAdmin ? (
|
||||
"Create a course to add content"
|
||||
) : (
|
||||
"No courses available yet"
|
||||
)}
|
||||
</p>
|
||||
{isUserAdmin && (
|
||||
<div className="mt-4">
|
||||
<AuthenticatedClientElement
|
||||
action="create"
|
||||
ressourceType="courses"
|
||||
checkMethod="roles"
|
||||
orgId={props.org_id}
|
||||
>
|
||||
<Modal
|
||||
isDialogOpen={newCourseModal}
|
||||
onOpenChange={setNewCourseModal}
|
||||
minHeight="md"
|
||||
dialogContent={
|
||||
<CreateCourseModal
|
||||
closeModal={closeNewCourseModal}
|
||||
orgslug={orgslug}
|
||||
/>
|
||||
}
|
||||
dialogTitle="Create Course"
|
||||
dialogDescription="Create a new course"
|
||||
dialogTrigger={
|
||||
<button>
|
||||
<NewCourseButton />
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<AuthenticatedClientElement
|
||||
action="create"
|
||||
ressourceType="courses"
|
||||
checkMethod="roles"
|
||||
orgId={props.org_id}
|
||||
>
|
||||
<Modal
|
||||
isDialogOpen={newCourseModal}
|
||||
onOpenChange={setNewCourseModal}
|
||||
minHeight="md"
|
||||
dialogContent={
|
||||
<CreateCourseModal
|
||||
closeModal={closeNewCourseModal}
|
||||
orgslug={orgslug}
|
||||
></CreateCourseModal>
|
||||
}
|
||||
dialogTitle="Create Course"
|
||||
dialogDescription="Create a new course"
|
||||
dialogTrigger={
|
||||
<button>
|
||||
<NewCourseButton />
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</GeneralWrapperStyled>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -82,48 +82,44 @@ const OrgHomePage = async (params: any) => {
|
|||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="w-full">
|
||||
<GeneralWrapperStyled>
|
||||
{/* Collections */}
|
||||
<div className="flex items-center ">
|
||||
<div className="flex grow">
|
||||
<div className="flex flex-col space-y-4 mb-8">
|
||||
<div className="flex items-center justify-between">
|
||||
<TypeOfContentTitle title="Collections" type="col" />
|
||||
</div>
|
||||
<AuthenticatedClientElement
|
||||
checkMethod="roles"
|
||||
ressourceType="collections"
|
||||
action="create"
|
||||
orgId={org_id}
|
||||
>
|
||||
<Link href={getUriWithOrg(orgslug, '/collections/new')}>
|
||||
<NewCollectionButton />
|
||||
</Link>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
<div className="home_collections flex flex-wrap">
|
||||
{collections.map((collection: any) => (
|
||||
<div
|
||||
className="flex flex-col py-3 px-3"
|
||||
key={collection.collection_id}
|
||||
<AuthenticatedClientElement
|
||||
checkMethod="roles"
|
||||
ressourceType="collections"
|
||||
action="create"
|
||||
orgId={org_id}
|
||||
>
|
||||
<CollectionThumbnail
|
||||
collection={collection}
|
||||
orgslug={orgslug}
|
||||
org_id={org.org_id}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{collections.length == 0 && (
|
||||
<div className="flex mx-auto h-[100px]">
|
||||
<div className="flex flex-col justify-center text-center items-center space-y-3">
|
||||
<div className="flex flex-col space-y-3">
|
||||
<div className="mx-auto">
|
||||
<Link href={getUriWithOrg(orgslug, '/collections/new')}>
|
||||
<NewCollectionButton />
|
||||
</Link>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{collections.map((collection: any) => (
|
||||
<div key={collection.collection_id} className="flex flex-col p-3">
|
||||
<CollectionThumbnail
|
||||
collection={collection}
|
||||
orgslug={orgslug}
|
||||
org_id={org.org_id}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{collections.length === 0 && (
|
||||
<div className="col-span-full flex justify-center items-center py-8">
|
||||
<div className="text-center">
|
||||
<div className="mb-4">
|
||||
<svg
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 295 295"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mx-auto"
|
||||
>
|
||||
<rect
|
||||
opacity="0.51"
|
||||
|
|
@ -143,53 +139,49 @@ const OrgHomePage = async (params: any) => {
|
|||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="space-y-0">
|
||||
<h1 className="text-xl font-bold text-gray-600">
|
||||
No collections yet
|
||||
</h1>
|
||||
<p className="text-md text-gray-400">
|
||||
<ContentPlaceHolderIfUserIsNotAdmin
|
||||
text="Create collections to group courses together"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<h1 className="text-xl font-bold text-gray-600 mb-2">
|
||||
No collections yet
|
||||
</h1>
|
||||
<p className="text-md text-gray-400">
|
||||
<ContentPlaceHolderIfUserIsNotAdmin
|
||||
text="Create collections to group courses together"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Courses */}
|
||||
<div className="h-5"></div>
|
||||
<div className="flex items-center ">
|
||||
<div className="flex grow">
|
||||
<div className="flex flex-col space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<TypeOfContentTitle title="Courses" type="cou" />
|
||||
<AuthenticatedClientElement
|
||||
ressourceType="courses"
|
||||
action="create"
|
||||
checkMethod="roles"
|
||||
orgId={org_id}
|
||||
>
|
||||
<Link href={getUriWithOrg(orgslug, '/courses?new=true')}>
|
||||
<NewCourseButton />
|
||||
</Link>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
<AuthenticatedClientElement
|
||||
ressourceType="courses"
|
||||
action="create"
|
||||
checkMethod="roles"
|
||||
orgId={org_id}
|
||||
>
|
||||
<Link href={getUriWithOrg(orgslug, '/courses?new=true')}>
|
||||
<NewCourseButton />
|
||||
</Link>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
<div className="home_courses flex flex-wrap">
|
||||
{courses.map((course: any) => (
|
||||
<div className="py-3 px-3" key={course.course_uuid}>
|
||||
<CourseThumbnail course={course} orgslug={orgslug} />
|
||||
</div>
|
||||
))}
|
||||
{courses.length == 0 && (
|
||||
<div className="flex mx-auto h-[300px]">
|
||||
<div className="flex flex-col justify-center text-center items-center space-y-3">
|
||||
<div className="flex flex-col space-y-3">
|
||||
<div className="mx-auto">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{courses.map((course: any) => (
|
||||
<div key={course.course_uuid} className="p-3">
|
||||
<CourseThumbnail course={course} orgslug={orgslug} />
|
||||
</div>
|
||||
))}
|
||||
{courses.length === 0 && (
|
||||
<div className="col-span-full flex justify-center items-center py-8">
|
||||
<div className="text-center">
|
||||
<div className="mb-4 ">
|
||||
<svg
|
||||
width="50"
|
||||
height="50"
|
||||
className="mx-auto"
|
||||
viewBox="0 0 295 295"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -212,18 +204,16 @@ const OrgHomePage = async (params: any) => {
|
|||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="space-y-0">
|
||||
<h1 className="text-xl font-bold text-gray-600">
|
||||
No courses yet
|
||||
</h1>
|
||||
<p className="text-md text-gray-400">
|
||||
<ContentPlaceHolderIfUserIsNotAdmin text='Create courses to add content' />
|
||||
</p>
|
||||
</div>
|
||||
<h1 className="text-xl font-bold text-gray-600 mb-2">
|
||||
No courses yet
|
||||
</h1>
|
||||
<p className="text-md text-gray-400">
|
||||
<ContentPlaceHolderIfUserIsNotAdmin text='Create courses to add content' />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</GeneralWrapperStyled>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
'use client';
|
||||
import LeftMenu from '@components/Dashboard/UI/LeftMenu'
|
||||
import DashLeftMenu from '@components/Dashboard/UI/DashLeftMenu'
|
||||
import DashMobileMenu from '@components/Dashboard/UI/DashMobileMenu'
|
||||
import AdminAuthorization from '@components/Security/AdminAuthorization'
|
||||
import { SessionProvider } from 'next-auth/react'
|
||||
import React from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { useMediaQuery } from 'usehooks-ts';
|
||||
|
||||
function ClientAdminLayout({
|
||||
children,
|
||||
|
|
@ -11,11 +13,17 @@ function ClientAdminLayout({
|
|||
children: React.ReactNode
|
||||
params: any
|
||||
}) {
|
||||
const isMobile = useMediaQuery('(max-width: 768px)')
|
||||
|
||||
return (
|
||||
<SessionProvider>
|
||||
<AdminAuthorization authorizationMode="page">
|
||||
<div className="flex">
|
||||
<LeftMenu />
|
||||
<div className="flex flex-col md:flex-row">
|
||||
{isMobile ? (
|
||||
<DashMobileMenu />
|
||||
) : (
|
||||
<DashLeftMenu />
|
||||
)}
|
||||
<div className="flex w-full">{children}</div>
|
||||
</div>
|
||||
</AdminAuthorization>
|
||||
|
|
@ -23,4 +31,4 @@ function ClientAdminLayout({
|
|||
)
|
||||
}
|
||||
|
||||
export default ClientAdminLayout
|
||||
export default ClientAdminLayout
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs'
|
||||
import { BookOpen, BookX, EllipsisVertical, Eye, Layers2, UserRoundPen } from 'lucide-react'
|
||||
import { BookOpen, BookX, EllipsisVertical, Eye, Layers2, Monitor, UserRoundPen } from 'lucide-react'
|
||||
import React, { useEffect } from 'react'
|
||||
import { AssignmentProvider, useAssignments } from '@components/Contexts/Assignments/AssignmentContext';
|
||||
import ToolTip from '@components/StyledElements/Tooltip/Tooltip';
|
||||
|
|
@ -15,12 +15,29 @@ import { updateActivity } from '@services/courses/activities';
|
|||
// Lazy Loading
|
||||
import dynamic from 'next/dynamic';
|
||||
import AssignmentEditorSubPage from './subpages/AssignmentEditorSubPage';
|
||||
import { useMediaQuery } from 'usehooks-ts';
|
||||
const AssignmentSubmissionsSubPage = dynamic(() => import('./subpages/AssignmentSubmissionsSubPage'))
|
||||
|
||||
function AssignmentEdit() {
|
||||
const params = useParams<{ assignmentuuid: string; }>()
|
||||
const searchParams = useSearchParams()
|
||||
const [selectedSubPage, setSelectedSubPage] = React.useState(searchParams.get('subpage') || 'editor')
|
||||
const isMobile = useMediaQuery('(max-width: 767px)')
|
||||
|
||||
if (isMobile) {
|
||||
// TODO: Work on a better mobile experience
|
||||
return (
|
||||
<div className="h-screen w-full bg-[#f8f8f8] flex items-center justify-center p-4">
|
||||
<div className="bg-white p-6 rounded-lg shadow-md text-center">
|
||||
<h2 className="text-xl font-bold mb-4">Desktop Only</h2>
|
||||
<Monitor className='mx-auto my-5' size={60} />
|
||||
<p>This page is only accessible from a desktop device.</p>
|
||||
<p>Please switch to a desktop to view and manage the assignment.</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex w-full flex-col'>
|
||||
<AssignmentProvider assignment_uuid={'assignment_' + params.assignmentuuid}>
|
||||
|
|
|
|||
|
|
@ -46,19 +46,19 @@ function AssignmentsHome() {
|
|||
|
||||
return (
|
||||
<div className='flex w-full'>
|
||||
<div className='pl-10 mr-10 tracking-tighter flex flex-col space-y-5 w-full'>
|
||||
<div className='pl-4 sm:pl-10 mr-4 sm:mr-10 tracking-tighter flex flex-col space-y-5 w-full'>
|
||||
<div className='flex flex-col space-y-2'>
|
||||
<BreadCrumbs type="assignments" />
|
||||
<h1 className="pt-3 flex font-bold text-4xl">Assignments</h1>
|
||||
</div>
|
||||
<div className='flex flex-col space-y-3 w-full'>
|
||||
{courseAssignments.map((assignments: any, index: number) => (
|
||||
<div key={index} className='flex flex-col space-y-2 bg-white nice-shadow p-4 rounded-xl w-full'>
|
||||
<div key={index} className='flex flex-col space-y-2 bg-white nice-shadow p-3 sm:p-4 rounded-xl w-full'>
|
||||
<div>
|
||||
<div className='flex space-x-2 items-center justify-between w-full'>
|
||||
<div className='flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2 items-start sm:items-center justify-between w-full'>
|
||||
<div className='flex space-x-2 items-center'>
|
||||
<MiniThumbnail course={courses[index]} />
|
||||
<div className='flex flex-col font-bold text-lg '>
|
||||
<div className='flex flex-col font-bold text-lg'>
|
||||
<p className='bg-gray-200 text-gray-700 px-2 text-xs py-0.5 rounded-full w-fit'>Course</p>
|
||||
<p>{courses[index].name}</p>
|
||||
</div>
|
||||
|
|
@ -75,10 +75,9 @@ function AssignmentsHome() {
|
|||
</Link>
|
||||
</div>
|
||||
|
||||
|
||||
{assignments && assignments.map((assignment: any) => (
|
||||
<div key={assignment.assignment_uuid} className='flex mt-3 p-3 rounded flex-row space-x-2 w-full light-shadow justify-between bg-gray-50 items-center'>
|
||||
<div className='flex flex-row items-center space-x-2 '>
|
||||
<div key={assignment.assignment_uuid} className='flex mt-3 p-2 sm:p-3 rounded flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2 w-full light-shadow justify-between bg-gray-50 items-start sm:items-center'>
|
||||
<div className='flex flex-col sm:flex-row items-start sm:items-center space-y-1 sm:space-y-0 sm:space-x-2'>
|
||||
<div className='flex text-xs font-bold bg-gray-200 text-gray-700 px-2 py-0.5 rounded-full h-fit'>
|
||||
<p>Assignment</p>
|
||||
</div>
|
||||
|
|
@ -86,7 +85,6 @@ function AssignmentsHome() {
|
|||
<div className='flex font-semibold text-gray-600 px-2 py-0.5 rounded outline outline-gray-200/70'>{assignment.description}</div>
|
||||
</div>
|
||||
<div className='flex space-x-2 font-bold text-sm items-center'>
|
||||
|
||||
<EllipsisVertical className='text-gray-500' size={17} />
|
||||
<Link
|
||||
href={{
|
||||
|
|
@ -103,7 +101,6 @@ function AssignmentsHome() {
|
|||
pathname: getUriWithOrg(org.slug, `/dash/assignments/${removeAssignmentPrefix(assignment.assignment_uuid)}`),
|
||||
query: { subpage: 'submissions' }
|
||||
}}
|
||||
|
||||
prefetch
|
||||
className='bg-white rounded-full flex space-x-2 nice-shadow items-center px-3 py-0.5'>
|
||||
<UserRoundPen size={15} />
|
||||
|
|
@ -124,10 +121,8 @@ function AssignmentsHome() {
|
|||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -172,4 +167,4 @@ const MiniThumbnail = (props: { course: any }) => {
|
|||
}
|
||||
|
||||
|
||||
export default AssignmentsHome
|
||||
export default AssignmentsHome
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
'use client'
|
||||
import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs'
|
||||
import CreateCourseModal from '@components/Objects/Modals/Course/Create/CreateCourse'
|
||||
import CourseThumbnail from '@components/Objects/Thumbnails/CourseThumbnail'
|
||||
import CourseThumbnail, { removeCoursePrefix } from '@components/Objects/Thumbnails/CourseThumbnail'
|
||||
import AuthenticatedClientElement from '@components/Security/AuthenticatedClientElement'
|
||||
import NewCourseButton from '@components/StyledElements/Buttons/NewCourseButton'
|
||||
import Modal from '@components/StyledElements/Modal/Modal'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import React from 'react'
|
||||
import useAdminStatus from '@components/Hooks/useAdminStatus'
|
||||
|
||||
type CourseProps = {
|
||||
orgslug: string
|
||||
|
|
@ -20,114 +21,106 @@ function CoursesHome(params: CourseProps) {
|
|||
const [newCourseModal, setNewCourseModal] = React.useState(isCreatingCourse)
|
||||
const orgslug = params.orgslug
|
||||
const courses = params.courses
|
||||
const isUserAdmin = useAdminStatus() as any
|
||||
|
||||
async function closeNewCourseModal() {
|
||||
setNewCourseModal(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full w-full bg-[#f8f8f8]">
|
||||
<div>
|
||||
<div className="pl-10 mr-10 tracking-tighter">
|
||||
<BreadCrumbs type="courses" />
|
||||
<div className="w-100 flex justify-between">
|
||||
<div className="pt-3 flex font-bold text-4xl">Courses</div>
|
||||
<AuthenticatedClientElement
|
||||
checkMethod="roles"
|
||||
action="create"
|
||||
ressourceType="courses"
|
||||
orgId={params.org_id}
|
||||
>
|
||||
<Modal
|
||||
isDialogOpen={newCourseModal}
|
||||
onOpenChange={setNewCourseModal}
|
||||
minHeight="md"
|
||||
dialogContent={
|
||||
<CreateCourseModal
|
||||
closeModal={closeNewCourseModal}
|
||||
orgslug={orgslug}
|
||||
></CreateCourseModal>
|
||||
}
|
||||
dialogTitle="Create Course"
|
||||
dialogDescription="Create a new course"
|
||||
dialogTrigger={
|
||||
<button>
|
||||
<NewCourseButton />
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
<div className="h-full w-full bg-[#f8f8f8] pl-10 pr-10">
|
||||
<div className="mb-6">
|
||||
<BreadCrumbs type="courses" />
|
||||
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center mt-4">
|
||||
<h1 className="text-3xl font-bold mb-4 sm:mb-0">Courses</h1>
|
||||
<AuthenticatedClientElement
|
||||
checkMethod="roles"
|
||||
action="create"
|
||||
ressourceType="courses"
|
||||
orgId={params.org_id}
|
||||
>
|
||||
<Modal
|
||||
isDialogOpen={newCourseModal}
|
||||
onOpenChange={setNewCourseModal}
|
||||
minHeight="md"
|
||||
dialogContent={
|
||||
<CreateCourseModal
|
||||
closeModal={closeNewCourseModal}
|
||||
orgslug={orgslug}
|
||||
/>
|
||||
}
|
||||
dialogTitle="Create Course"
|
||||
dialogDescription="Create a new course"
|
||||
dialogTrigger={
|
||||
<button>
|
||||
<NewCourseButton />
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-wrap mx-8 mt-7">
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{courses.map((course: any) => (
|
||||
<div className="px-3" key={course.course_uuid}>
|
||||
<CourseThumbnail course={course} orgslug={orgslug} />
|
||||
<div key={course.course_uuid}>
|
||||
<CourseThumbnail customLink={`/dash/courses/course/${removeCoursePrefix(course.course_uuid)}/general`} course={course} orgslug={orgslug} />
|
||||
</div>
|
||||
))}
|
||||
{courses.length == 0 && (
|
||||
<div className="flex mx-auto h-[400px]">
|
||||
<div className="flex flex-col justify-center text-center items-center space-y-5">
|
||||
<div className="mx-auto">
|
||||
{courses.length === 0 && (
|
||||
<div className="col-span-full flex justify-center items-center py-8">
|
||||
<div className="text-center">
|
||||
<div className="mb-4">
|
||||
<svg
|
||||
width="120"
|
||||
height="120"
|
||||
viewBox="0 0 295 295"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mx-auto"
|
||||
>
|
||||
<rect
|
||||
opacity="0.51"
|
||||
x="10"
|
||||
y="10"
|
||||
width="275"
|
||||
height="275"
|
||||
rx="75"
|
||||
stroke="#4B5564"
|
||||
strokeOpacity="0.15"
|
||||
strokeWidth="20"
|
||||
/>
|
||||
<path
|
||||
d="M135.8 200.8V130L122.2 114.6L135.8 110.4V102.8L122.2 87.4L159.8 76V200.8L174.6 218H121L135.8 200.8Z"
|
||||
fill="#4B5564"
|
||||
fillOpacity="0.08"
|
||||
/>
|
||||
{/* ... SVG content ... */}
|
||||
</svg>
|
||||
</div>
|
||||
<div className="space-y-0">
|
||||
<h1 className="text-3xl font-bold text-gray-600">
|
||||
No courses yet
|
||||
</h1>
|
||||
<p className="text-lg text-gray-400">
|
||||
Create a course to add content
|
||||
</p>
|
||||
</div>
|
||||
<AuthenticatedClientElement
|
||||
action="create"
|
||||
ressourceType="courses"
|
||||
checkMethod="roles"
|
||||
orgId={params.org_id}
|
||||
>
|
||||
<Modal
|
||||
isDialogOpen={newCourseModal}
|
||||
onOpenChange={setNewCourseModal}
|
||||
minHeight="md"
|
||||
dialogContent={
|
||||
<CreateCourseModal
|
||||
closeModal={closeNewCourseModal}
|
||||
orgslug={orgslug}
|
||||
></CreateCourseModal>
|
||||
}
|
||||
dialogTitle="Create Course"
|
||||
dialogDescription="Create a new course"
|
||||
dialogTrigger={
|
||||
<button>
|
||||
<NewCourseButton />
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</AuthenticatedClientElement>
|
||||
<h2 className="text-2xl font-bold text-gray-600 mb-2">
|
||||
No courses yet
|
||||
</h2>
|
||||
<p className="text-lg text-gray-400">
|
||||
{isUserAdmin ? (
|
||||
"Create a course to add content"
|
||||
) : (
|
||||
"No courses available yet"
|
||||
)}
|
||||
</p>
|
||||
{isUserAdmin && (
|
||||
<div className="mt-6">
|
||||
<AuthenticatedClientElement
|
||||
action="create"
|
||||
ressourceType="courses"
|
||||
checkMethod="roles"
|
||||
orgId={params.org_id}
|
||||
>
|
||||
<Modal
|
||||
isDialogOpen={newCourseModal}
|
||||
onOpenChange={setNewCourseModal}
|
||||
minHeight="md"
|
||||
dialogContent={
|
||||
<CreateCourseModal
|
||||
closeModal={closeNewCourseModal}
|
||||
orgslug={orgslug}
|
||||
/>
|
||||
}
|
||||
dialogTitle="Create Course"
|
||||
dialogDescription="Create a new course"
|
||||
dialogTrigger={
|
||||
<button>
|
||||
<NewCourseButton />
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</AuthenticatedClientElement>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -7,84 +7,68 @@ import AdminAuthorization from '@components/Security/AdminAuthorization'
|
|||
|
||||
function DashboardHome() {
|
||||
return (
|
||||
<div className="flex items-center justify-center mx-auto min-h-screen flex-col space-x-3">
|
||||
<div className="mx-auto pb-10">
|
||||
<div className="flex items-center justify-center mx-auto min-h-screen flex-col p-4 sm:mb-0 mb-16">
|
||||
<div className="mx-auto pb-6 sm:pb-10">
|
||||
<Image
|
||||
alt="learnhouse logo"
|
||||
width={230}
|
||||
src={learnhousetextlogo}
|
||||
></Image>
|
||||
className="w-48 sm:w-auto"
|
||||
/>
|
||||
</div>
|
||||
<AdminAuthorization authorizationMode="component">
|
||||
<div className="flex space-x-10">
|
||||
<Link
|
||||
href={`/dash/courses`}
|
||||
className="flex bg-white shadow-lg p-[35px] w-[250px] rounded-lg items-center mx-auto hover:scale-105 transition-all ease-linear cursor-pointer"
|
||||
>
|
||||
<div className="flex flex-col mx-auto space-y-2">
|
||||
<BookCopy className="mx-auto text-gray-500" size={50}></BookCopy>
|
||||
<div className="text-center font-bold text-gray-500">Courses</div>
|
||||
<p className="text-center text-sm text-gray-400">
|
||||
Create and manage courses, chapters and ativities{' '}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
<Link
|
||||
href={`/dash/org/settings/general`}
|
||||
className="flex bg-white shadow-lg p-[35px] w-[250px] rounded-lg items-center mx-auto hover:scale-105 transition-all ease-linear cursor-pointer"
|
||||
>
|
||||
<div className="flex flex-col mx-auto space-y-2">
|
||||
<School className="mx-auto text-gray-500" size={50}></School>
|
||||
<div className="text-center font-bold text-gray-500">
|
||||
Organization
|
||||
</div>
|
||||
<p className="text-center text-sm text-gray-400">
|
||||
Configure your Organization general settings{' '}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
<Link
|
||||
href={`/dash/users/settings/users`}
|
||||
className="flex bg-white shadow-lg p-[35px] w-[250px] rounded-lg items-center mx-auto hover:scale-105 transition-all ease-linear cursor-pointer"
|
||||
>
|
||||
<div className="flex flex-col mx-auto space-y-2">
|
||||
<Users className="mx-auto text-gray-500" size={50}></Users>
|
||||
<div className="text-center font-bold text-gray-500">Users</div>
|
||||
<p className="text-center text-sm text-gray-400">
|
||||
Manage your Organization's users, roles{' '}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4 lg:space-x-10">
|
||||
{/* Card components */}
|
||||
<DashboardCard
|
||||
href="/dash/courses"
|
||||
icon={<BookCopy className="mx-auto text-gray-500" size={50} />}
|
||||
title="Courses"
|
||||
description="Create and manage courses, chapters and activities"
|
||||
/>
|
||||
<DashboardCard
|
||||
href="/dash/org/settings/general"
|
||||
icon={<School className="mx-auto text-gray-500" size={50} />}
|
||||
title="Organization"
|
||||
description="Configure your Organization general settings"
|
||||
/>
|
||||
<DashboardCard
|
||||
href="/dash/users/settings/users"
|
||||
icon={<Users className="mx-auto text-gray-500" size={50} />}
|
||||
title="Users"
|
||||
description="Manage your Organization's users, roles"
|
||||
/>
|
||||
</div>
|
||||
</AdminAuthorization>
|
||||
<div className="flex flex-col space-y-10 ">
|
||||
<div className="flex flex-col space-y-6 sm:space-y-10 mt-6 sm:mt-10">
|
||||
<AdminAuthorization authorizationMode="component">
|
||||
<div className="h-1 w-[100px] bg-neutral-200 rounded-full mx-auto"></div>
|
||||
<div className="flex justify-center items-center">
|
||||
<Link
|
||||
href={'https://university.learnhouse.io/'}
|
||||
target='_blank'
|
||||
className="flex mt-[40px] bg-black space-x-2 items-center py-3 px-7 rounded-lg shadow-lg hover:scale-105 transition-all ease-linear cursor-pointer"
|
||||
className="flex mt-4 sm:mt-[40px] bg-black space-x-2 items-center py-3 px-7 rounded-lg shadow-lg hover:scale-105 transition-all ease-linear cursor-pointer"
|
||||
>
|
||||
<University className=" text-gray-100" size={20}></University>
|
||||
<div className=" text-sm font-bold text-gray-100">
|
||||
<University className="text-gray-100" size={20} />
|
||||
<div className="text-sm font-bold text-gray-100">
|
||||
LearnHouse University
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="mx-auto mt-[40px] w-28 h-1 bg-neutral-200 rounded-full"></div>
|
||||
<div className="mx-auto mt-4 sm:mt-[40px] w-28 h-1 bg-neutral-200 rounded-full"></div>
|
||||
</AdminAuthorization>
|
||||
|
||||
<Link
|
||||
href={'/dash/user-account/settings/general'}
|
||||
className="flex bg-white shadow-lg p-[15px] items-center rounded-lg mx-auto hover:scale-105 transition-all ease-linear cursor-pointer"
|
||||
className="flex bg-white shadow-lg p-4 items-center rounded-lg mx-auto hover:scale-105 transition-all ease-linear cursor-pointer max-w-md"
|
||||
>
|
||||
<div className="flex flex-row mx-auto space-x-3 items-center">
|
||||
<Settings className=" text-gray-500" size={20}></Settings>
|
||||
<div className=" font-bold text-gray-500">Account Settings</div>
|
||||
<p className=" text-sm text-gray-400">
|
||||
Configure your personal settings, passwords, email
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row mx-auto space-y-2 sm:space-y-0 sm:space-x-3 items-center text-center sm:text-left">
|
||||
<Settings className="text-gray-500" size={20} />
|
||||
<div>
|
||||
<div className="font-bold text-gray-500">Account Settings</div>
|
||||
<p className="text-sm text-gray-400">
|
||||
Configure your personal settings, passwords, email
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
|
@ -92,4 +76,20 @@ function DashboardHome() {
|
|||
)
|
||||
}
|
||||
|
||||
// New component for dashboard cards
|
||||
function DashboardCard({ href, icon, title, description }: { href: string, icon: React.ReactNode, title: string, description: string }) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="flex bg-white shadow-lg p-6 w-full sm:w-[250px] rounded-lg items-center mx-auto hover:scale-105 transition-all ease-linear cursor-pointer"
|
||||
>
|
||||
<div className="flex flex-col mx-auto space-y-2">
|
||||
{icon}
|
||||
<div className="text-center font-bold text-gray-500">{title}</div>
|
||||
<p className="text-center text-sm text-gray-400">{description}</p>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default DashboardHome
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@
|
|||
import React, { useEffect } from 'react'
|
||||
import { motion } from 'framer-motion'
|
||||
import Link from 'next/link'
|
||||
import { useMediaQuery } from 'usehooks-ts'
|
||||
import { getUriWithOrg } from '@services/config/config'
|
||||
import { ScanEye, SquareUserRound, UserPlus, Users } from 'lucide-react'
|
||||
import { Monitor, ScanEye, SquareUserRound, UserPlus, Users } from 'lucide-react'
|
||||
import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { useOrg } from '@components/Contexts/OrgContext'
|
||||
|
|
@ -22,6 +23,7 @@ function UsersSettingsPage({ params }: { params: SettingsParams }) {
|
|||
const org = useOrg() as any
|
||||
const [H1Label, setH1Label] = React.useState('')
|
||||
const [H2Label, setH2Label] = React.useState('')
|
||||
const isMobile = useMediaQuery('(max-width: 767px)')
|
||||
|
||||
function handleLabels() {
|
||||
if (params.subpage == 'users') {
|
||||
|
|
@ -46,6 +48,20 @@ function UsersSettingsPage({ params }: { params: SettingsParams }) {
|
|||
handleLabels()
|
||||
}, [session, org, params.subpage, params])
|
||||
|
||||
if (isMobile) {
|
||||
// TODO: Work on a better mobile experience
|
||||
return (
|
||||
<div className="h-screen w-full bg-[#f8f8f8] flex items-center justify-center p-4">
|
||||
<div className="bg-white p-6 rounded-lg shadow-md text-center">
|
||||
<h2 className="text-xl font-bold mb-4">Desktop Only</h2>
|
||||
<Monitor className='mx-auto my-5' size={60} />
|
||||
<p>This page is only accessible from a desktop device.</p>
|
||||
<p>Please switch to a desktop to view and manage user settings.</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-screen w-full bg-[#f8f8f8] grid grid-rows-[auto,1fr]">
|
||||
<div className="pl-10 pr-10 tracking-tight bg-[#fcfbfc] z-10 shadow-[0px_4px_16px_rgba(0,0,0,0.06)]">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue