mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: various UI updates
This commit is contained in:
parent
52bc9e556b
commit
d5ad9e2f2f
10 changed files with 214 additions and 291 deletions
|
|
@ -10,6 +10,7 @@ import { Check } from "lucide-react";
|
||||||
import { markActivityAsComplete } from "@services/courses/activity";
|
import { markActivityAsComplete } from "@services/courses/activity";
|
||||||
import ToolTip from "@components/UI/Tooltip/Tooltip";
|
import ToolTip from "@components/UI/Tooltip/Tooltip";
|
||||||
import DocumentPdfActivity from "@components/Pages/Activities/DocumentPdf/DocumentPdf";
|
import DocumentPdfActivity from "@components/Pages/Activities/DocumentPdf/DocumentPdf";
|
||||||
|
import ActivityIndicators from "@components/Pages/Courses/ActivityIndicators";
|
||||||
|
|
||||||
interface ActivityClientProps {
|
interface ActivityClientProps {
|
||||||
activityid: string;
|
activityid: string;
|
||||||
|
|
@ -35,7 +36,7 @@ function ActivityClient(props: ActivityClientProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ActivityLayout>
|
<div className="max-w-7xl mx-auto px-4 space-y-5 pt-0">
|
||||||
<pre style={{ display: "none" }}>{JSON.stringify(activity, null, 2)}</pre>
|
<pre style={{ display: "none" }}>{JSON.stringify(activity, null, 2)}</pre>
|
||||||
<ActivityTopWrapper>
|
<ActivityTopWrapper>
|
||||||
<ActivityThumbnail>
|
<ActivityThumbnail>
|
||||||
|
|
@ -48,31 +49,10 @@ function ActivityClient(props: ActivityClientProps) {
|
||||||
<h1>{course.course.name}</h1>
|
<h1>{course.course.name}</h1>
|
||||||
</ActivityInfo>
|
</ActivityInfo>
|
||||||
</ActivityTopWrapper>
|
</ActivityTopWrapper>
|
||||||
<ChaptersWrapper>
|
<ActivityIndicators current_activity={activityid} orgslug={orgslug} course={course} />
|
||||||
{course.chapters.map((chapter: any) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div style={{ display: "flex", flexDirection: "row" }} key={chapter.chapter_id}>
|
|
||||||
{chapter.activities.map((activity: any) => {
|
|
||||||
return (
|
|
||||||
<ToolTip sideOffset={-5} slateBlack content={activity.name} key={activity.id}>
|
|
||||||
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}/activity/${activity.id.replace("activity_", "")}`}>
|
|
||||||
<ChapterIndicator
|
|
||||||
done={course.trail.activities_marked_complete && course.trail.activities_marked_complete.includes(activity.id) && course.trail.status == "ongoing"}
|
|
||||||
active={"activity_" + activityid === activity.id ? true : false} key={activity.id}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
</ToolTip>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ChaptersWrapper>
|
|
||||||
|
|
||||||
{activity ? (
|
{activity ? (
|
||||||
|
<div className="p-7 pt-2 drop-shadow-sm rounded-lg bg-white">
|
||||||
<CourseContent>
|
<CourseContent>
|
||||||
{activity.type == "dynamic" && <Canva content={activity.content} activity={activity} />}
|
{activity.type == "dynamic" && <Canva content={activity.content} activity={activity} />}
|
||||||
{/* todo : use apis & streams instead of this */}
|
{/* todo : use apis & streams instead of this */}
|
||||||
|
|
@ -102,14 +82,14 @@ function ActivityClient(props: ActivityClientProps) {
|
||||||
)}
|
)}
|
||||||
</ActivityMarkerWrapper>
|
</ActivityMarkerWrapper>
|
||||||
</CourseContent>
|
</CourseContent>
|
||||||
|
</div>
|
||||||
) : (<div></div>)}
|
) : (<div></div>)}
|
||||||
{<div style={{ height: "100px" }}></div>}
|
{<div style={{ height: "100px" }}></div>}
|
||||||
</ActivityLayout>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActivityLayout = styled.div``;
|
|
||||||
|
|
||||||
const ActivityThumbnail = styled.div`
|
const ActivityThumbnail = styled.div`
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
|
|
@ -133,32 +113,8 @@ const ActivityInfo = styled.div`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ChaptersWrapper = styled.div`
|
|
||||||
display: flex;
|
|
||||||
// row
|
|
||||||
flex-direction: row;
|
|
||||||
width: 100%;
|
|
||||||
width: 1300px;
|
|
||||||
margin: 0 auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ChapterIndicator = styled.div < { active?: boolean, done?: boolean } > `
|
|
||||||
border-radius: 20px;
|
|
||||||
height: 5px;
|
|
||||||
background: #151515;
|
|
||||||
border-radius: 3px;
|
|
||||||
|
|
||||||
width: 35px;
|
|
||||||
background-color: ${props => props.done ? "green" : (props.active ? "#9d9d9d" : "black")};
|
|
||||||
margin: 10px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
margin-left: 0px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #9d9d9d;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ActivityTopWrapper = styled.div`
|
const ActivityTopWrapper = styled.div`
|
||||||
width: 1300px;
|
width: 1300px;
|
||||||
|
|
@ -171,7 +127,6 @@ const CourseContent = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
min-height: 600px;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ActivityMarkerWrapper = styled.div`
|
const ActivityMarkerWrapper = styled.div`
|
||||||
|
|
|
||||||
|
|
@ -2,68 +2,74 @@
|
||||||
import { EyeOpenIcon, Pencil2Icon } from "@radix-ui/react-icons";
|
import { EyeOpenIcon, Pencil2Icon } from "@radix-ui/react-icons";
|
||||||
import { removeCourse, startCourse } from "@services/courses/activity";
|
import { removeCourse, startCourse } from "@services/courses/activity";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import React from "react";
|
import React, { use } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config";
|
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import ToolTip from "@components/UI/Tooltip/Tooltip";
|
import ToolTip from "@components/UI/Tooltip/Tooltip";
|
||||||
import PageLoading from "@components/Pages/PageLoading";
|
import PageLoading from "@components/Pages/PageLoading";
|
||||||
import { revalidateTags } from "@services/utils/ts/requests";
|
import { revalidateTags } from "@services/utils/ts/requests";
|
||||||
|
import ActivityIndicators from "@components/Pages/Courses/ActivityIndicators";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
const CourseClient = (props: any) => {
|
const CourseClient = (props: any) => {
|
||||||
const courseid = props.courseid;
|
const courseid = props.courseid;
|
||||||
const orgslug = props.orgslug;
|
const orgslug = props.orgslug;
|
||||||
const course = props.course;
|
const course = props.course;
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
async function startCourseUI() {
|
async function startCourseUI() {
|
||||||
// Create activity
|
// Create activity
|
||||||
await startCourse("course_" + courseid, orgslug);
|
await startCourse("course_" + courseid, orgslug);
|
||||||
revalidateTags(['courses']);
|
revalidateTags(['courses']);
|
||||||
|
router.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function quitCourse() {
|
async function quitCourse() {
|
||||||
|
|
||||||
// Close activity
|
// Close activity
|
||||||
let activity = await removeCourse("course_" + courseid, orgslug);
|
let activity = await removeCourse("course_" + courseid, orgslug);
|
||||||
// Mutate course
|
// Mutate course
|
||||||
revalidateTags(['courses']);
|
revalidateTags(['courses']);
|
||||||
|
router.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(course);
|
console.log(course);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!course ? (
|
{!course ? (
|
||||||
<PageLoading></PageLoading>
|
<PageLoading></PageLoading>
|
||||||
) : (
|
) : (
|
||||||
<CoursePageLayout className="pt-6">
|
<div className="max-w-7xl mx-auto px-4 py-10 tracking-tight">
|
||||||
<p className="text-lg font-bold">Course</p>
|
<div className="pb-3">
|
||||||
<h1 className="text-3xl font-bold flex items-center space-x-5">
|
<p className="text-md font-bold text-gray-400 pb-2">Course</p>
|
||||||
{course.course.name}{" "}
|
<h1 className="text-3xl -mt-3 font-bold">
|
||||||
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}/edit`} rel="noopener noreferrer">
|
{course.course.name}
|
||||||
<Pencil2Icon />
|
|
||||||
</Link>{" "}
|
|
||||||
</h1>
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
<CourseThumbnailWrapper>
|
|
||||||
<img src={`${getBackendUrl()}content/uploads/img/${course.course.thumbnail}`} alt="" />
|
|
||||||
</CourseThumbnailWrapper>
|
|
||||||
|
|
||||||
<CourseMetaWrapper>
|
<div className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-auto h-[300px] bg-cover bg-center mb-4" style={{ backgroundImage: `url(${getBackendUrl()}content/uploads/img/${course.course.thumbnail})` }}>
|
||||||
<CourseMetaLeft>
|
|
||||||
<h2 className="py-3 font-bold">Description</h2>
|
|
||||||
|
|
||||||
<BoxWrapper>
|
</div>
|
||||||
|
|
||||||
|
<ActivityIndicators orgslug={orgslug} course={course} />
|
||||||
|
|
||||||
|
<div className="flex flex-row pt-10">
|
||||||
|
<div className="course_metadata_left grow space-y-2">
|
||||||
|
<h2 className="py-3 text-2xl font-bold">Description</h2>
|
||||||
|
<StyledBox>
|
||||||
<p className="py-3">{course.course.description}</p>
|
<p className="py-3">{course.course.description}</p>
|
||||||
</BoxWrapper>
|
</StyledBox>
|
||||||
|
|
||||||
|
<h2 className="py-3 text-2xl font-bold">What you will learn</h2>
|
||||||
|
<StyledBox>
|
||||||
|
|
||||||
<h2 className="py-3 font-bold">What you will learn</h2>
|
|
||||||
<BoxWrapper>
|
|
||||||
<p className="py-3">{course.learnings == ![] ? "no data" : course.learnings}</p>
|
<p className="py-3">{course.learnings == ![] ? "no data" : course.learnings}</p>
|
||||||
</BoxWrapper>
|
</StyledBox>
|
||||||
|
|
||||||
<h2 className="py-3 font-bold">Course Lessons</h2>
|
<h2 className="py-3 text-2xl font-bold">Course Lessons</h2>
|
||||||
|
<StyledBox>
|
||||||
<BoxWrapper>
|
|
||||||
{course.chapters.map((chapter: any) => {
|
{course.chapters.map((chapter: any) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
@ -88,142 +94,32 @@ const CourseClient = (props: any) => {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</BoxWrapper>
|
</StyledBox>
|
||||||
</CourseMetaLeft>
|
|
||||||
<CourseMetaRight>
|
</div>
|
||||||
|
<div className="course_metadata_right w-64 flex items-center ml-10 h-28 p-3 bg-white rounded-md justify-center drop-shadow-[0_33px_13px_rgba(0,0,0,0.042)] transition-all">
|
||||||
{course.trail.status == "ongoing" ? (
|
{course.trail.status == "ongoing" ? (
|
||||||
<button style={{ backgroundColor: "red" }} onClick={quitCourse}>
|
<button className="py-2 px-5 rounded-xl text-white font-bold h-12 w-[200px] drop-shadow-md bg-red-600 hover:bg-red-700 hover:cursor-pointer" onClick={quitCourse}>
|
||||||
Quit Course
|
Quit Course
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button onClick={startCourseUI}>Start Course</button>
|
<button className="py-2 px-5 rounded-xl text-white font-bold h-12 w-[200px] drop-shadow-md bg-black hover:bg-gray-900 hover:cursor-pointer" onClick={startCourseUI}>Start Course</button>
|
||||||
)}
|
)}
|
||||||
</CourseMetaRight>
|
</div>
|
||||||
</CourseMetaWrapper>
|
</div>
|
||||||
</CoursePageLayout>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const CourseThumbnailWrapper = styled.div`
|
|
||||||
display: flex;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 300px;
|
|
||||||
object-fit: cover;
|
|
||||||
object-position: center;
|
|
||||||
background: url(), #d9d9d9;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.19);
|
|
||||||
box-shadow: 0px 13px 33px -13px rgba(0, 0, 0, 0.42);
|
|
||||||
border-radius: 7px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
const CoursePageLayout = styled.div`
|
|
||||||
width: 1300px;
|
|
||||||
margin: 0 auto;
|
|
||||||
p {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
letter-spacing: -0.05em;
|
|
||||||
|
|
||||||
color: #727272;
|
const StyledBox = (props: any) => (
|
||||||
font-weight: 700;
|
<div className="p-3 pl-10 bg-white rounded-md w-[100%] h-auto drop-shadow-[0_33px_13px_rgba(0,0,0,0.042)]">
|
||||||
}
|
{props.children}
|
||||||
h1 {
|
</div>
|
||||||
margin-top: 5px;
|
|
||||||
letter-spacing: -0.05em;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ChaptersWrapper = styled.div`
|
);
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
const CourseIndicator = styled.div< { active?: boolean, done?: boolean } >`
|
|
||||||
border-radius: 20px;
|
|
||||||
height: 5px;
|
|
||||||
background: #151515;
|
|
||||||
border-radius: 3px;
|
|
||||||
|
|
||||||
background-color: ${props => props.done ? "green" : "black"};
|
|
||||||
|
|
||||||
width: 40px;
|
|
||||||
margin: 10px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
margin-left: 0px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #9d9d9d;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ChapterSeparator = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
padding-right: 7px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const BoxWrapper = styled.div`
|
|
||||||
background: #ffffff;
|
|
||||||
box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.03);
|
|
||||||
border-radius: 7px;
|
|
||||||
padding: 20px;
|
|
||||||
padding-top: 7px;
|
|
||||||
padding-left: 30px;
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-family: "DM Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 16px;
|
|
||||||
letter-spacing: -0.02em;
|
|
||||||
|
|
||||||
color: #9d9d9d;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const CourseMetaWrapper = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const CourseMetaLeft = styled.div`
|
|
||||||
width: 80%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const CourseMetaRight = styled.div`
|
|
||||||
background: #ffffff;
|
|
||||||
box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.03);
|
|
||||||
border-radius: 7px;
|
|
||||||
padding: 20px;
|
|
||||||
width: 30%;
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
margin-left: 50px;
|
|
||||||
margin-top: 20px;
|
|
||||||
button {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
background: #151515;
|
|
||||||
border-radius: 15px;
|
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
font-weight: 700;
|
|
||||||
font-family: "DM Sans";
|
|
||||||
font-size: 16px;
|
|
||||||
letter-spacing: -0.05em;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
box-shadow: 0px 13px 33px -13px rgba(0, 0, 0, 0.42);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
background: #000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default CourseClient;
|
export default CourseClient;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { createActivity, createFileActivity, createExternalVideoActivity } from
|
||||||
import { getOrganizationContextInfo } from "@services/organizations/orgs";
|
import { getOrganizationContextInfo } from "@services/organizations/orgs";
|
||||||
import Modal from "@components/UI/Modal/Modal";
|
import Modal from "@components/UI/Modal/Modal";
|
||||||
import { denyAccessToUser } from "@services/utils/react/middlewares/views";
|
import { denyAccessToUser } from "@services/utils/react/middlewares/views";
|
||||||
|
import { Folders, Package2 } from "lucide-react";
|
||||||
|
|
||||||
function CourseEdit(params: any) {
|
function CourseEdit(params: any) {
|
||||||
|
|
||||||
|
|
@ -243,21 +244,7 @@ function CourseEdit(params: any) {
|
||||||
<Page>
|
<Page>
|
||||||
<Title>
|
<Title>
|
||||||
Edit Course {" "}
|
Edit Course {" "}
|
||||||
<Modal
|
|
||||||
isDialogOpen={newChapterModal}
|
|
||||||
onOpenChange={setNewChapterModal}
|
|
||||||
minHeight="sm"
|
|
||||||
dialogContent={<NewChapterModal
|
|
||||||
closeModal={closeNewChapterModal}
|
|
||||||
submitChapter={submitChapter}
|
|
||||||
></NewChapterModal>}
|
|
||||||
dialogTitle="Create chapter"
|
|
||||||
dialogDescription="Add a new chapter to the course"
|
|
||||||
dialogTrigger={
|
|
||||||
<button> Add chapter +
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -287,7 +274,7 @@ function CourseEdit(params: any) {
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
{winReady && (
|
{winReady && (
|
||||||
<ChapterlistWrapper>
|
<div className="flex flex-col max-w-7xl justify-center items-center mx-auto">
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
<Droppable key="chapters" droppableId="chapters" type="chapter">
|
<Droppable key="chapters" droppableId="chapters" type="chapter">
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
|
|
@ -312,7 +299,24 @@ function CourseEdit(params: any) {
|
||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
</ChapterlistWrapper>
|
<Modal
|
||||||
|
isDialogOpen={newChapterModal}
|
||||||
|
onOpenChange={setNewChapterModal}
|
||||||
|
minHeight="sm"
|
||||||
|
dialogContent={<NewChapterModal
|
||||||
|
closeModal={closeNewChapterModal}
|
||||||
|
submitChapter={submitChapter}
|
||||||
|
></NewChapterModal>}
|
||||||
|
dialogTitle="Create chapter"
|
||||||
|
dialogDescription="Add a new chapter to the course"
|
||||||
|
dialogTrigger={
|
||||||
|
<div className="flex max-w-7xl bg-black shadow rounded-md text-white justify-center space-x-2 p-3 w-72 hover:bg-gray-900 hover:cursor-pointer">
|
||||||
|
<Folders size={20} />
|
||||||
|
<div>Add chapter +</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Page >
|
</Page >
|
||||||
</>
|
</>
|
||||||
|
|
@ -351,9 +355,5 @@ const Page = styled.div`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
const ChapterlistWrapper = styled.div`
|
|
||||||
display: flex;
|
|
||||||
padding-left: 30px;
|
|
||||||
justify-content: center;
|
|
||||||
`;
|
|
||||||
export default CourseEdit;
|
export default CourseEdit;
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ const OrgHomePage = async (params: any) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Courses */}
|
{/* Courses */}
|
||||||
|
<div className='h-5'></div>
|
||||||
<Title title="Courses" type="cou" />
|
<Title title="Courses" type="cou" />
|
||||||
<div className="home_courses flex flex-wrap">
|
<div className="home_courses flex flex-wrap">
|
||||||
{courses.map((course: any) => (
|
{courses.map((course: any) => (
|
||||||
|
|
@ -92,13 +93,13 @@ const OrgHomePage = async (params: any) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const Title = (props: any) => {
|
const Title = (props: any) => {
|
||||||
return (
|
return (
|
||||||
<div className="home_category_title flex my-5">
|
<div className="home_category_title flex my-5 items-center">
|
||||||
<div className="rounded-full ring-1 ring-slate-900/5 shadow-sm p-2 my-auto mr-4">
|
<div className="rounded-full ring-1 ring-slate-900/5 shadow-sm p-2 my-auto mr-4">
|
||||||
<Image className="" src={props.type == "col" ? CollectionsLogo : CoursesLogo} alt="Courses logo" />
|
<Image className="" src={props.type == "col" ? CollectionsLogo : CoursesLogo} alt="Courses logo" />
|
||||||
</div>
|
</div>
|
||||||
<h1 className="font-bold text-lg">{props.title}</h1>
|
<h1 className="font-bold text-2xl">{props.title}</h1>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,6 @@ const InfoCalloutWrapper = styled.div`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DragHandle = styled.div`
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 1rem;
|
|
||||||
height: 100%;
|
|
||||||
cursor: move;
|
|
||||||
z-index: 1;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default InfoCalloutComponent;
|
export default InfoCalloutComponent;
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ function Canva(props: Editor) {
|
||||||
|
|
||||||
const CanvaWrapper = styled.div`
|
const CanvaWrapper = styled.div`
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
width: 1300px;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ function Activity(props: any) {
|
||||||
<Draggable key={props.activity.id} draggableId={props.activity.id} index={props.index}>
|
<Draggable key={props.activity.id} draggableId={props.activity.id} index={props.index}>
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<div
|
<div
|
||||||
className="flex flex-row items-center py-2 my-3 rounded-md justify-center bg-gray-50 hover:bg-gray-100 space-x-2" key={props.activity.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
className="flex flex-row items-center py-2 my-3 rounded-md justify-center bg-gray-50 hover:bg-gray-100 space-x-2 w-auto" key={props.activity.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
||||||
<p>{props.activity.name} </p>
|
<p>{props.activity.name} </p>
|
||||||
<Link
|
<Link
|
||||||
href={getUriWithOrg(props.orgslug, "") + `/course/${props.courseid}/activity/${props.activity.id.replace("activity_", "")}`}
|
href={getUriWithOrg(props.orgslug, "") + `/course/${props.courseid}/activity/${props.activity.id.replace("activity_", "")}`}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
||||||
import Activity from "./Activity";
|
import Activity from "./Activity";
|
||||||
|
import { PlusSquare } from "lucide-react";
|
||||||
|
|
||||||
function Chapter(props: any) {
|
function Chapter(props: any) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -16,14 +17,7 @@ function Chapter(props: any) {
|
||||||
>
|
>
|
||||||
<h3 className="pt-3 font-bold text-md">
|
<h3 className="pt-3 font-bold text-md">
|
||||||
{props.info.list.chapter.name}
|
{props.info.list.chapter.name}
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
props.openNewActivityModal(props.info.list.chapter.id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
|
|
||||||
Create Activity
|
|
||||||
</button>
|
|
||||||
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|
@ -37,13 +31,24 @@ function Chapter(props: any) {
|
||||||
<Droppable key={props.info.list.chapter.id} droppableId={props.info.list.chapter.id} type="activity">
|
<Droppable key={props.info.list.chapter.id} droppableId={props.info.list.chapter.id} type="activity">
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<ActivitiesList {...provided.droppableProps} ref={provided.innerRef}>
|
<ActivitiesList {...provided.droppableProps} ref={provided.innerRef}>
|
||||||
|
<div className="flex flex-col ">
|
||||||
{props.info.list.activities.map((activity: any, index: any) => (
|
{props.info.list.activities.map((activity: any, index: any) => (
|
||||||
<Activity orgslug={props.orgslug} courseid={props.courseid} key={activity.id} activity={activity} index={index}></Activity>
|
<Activity orgslug={props.orgslug} courseid={props.courseid} key={activity.id} activity={activity} index={index}></Activity>
|
||||||
))}
|
))}
|
||||||
{provided.placeholder}
|
{provided.placeholder}
|
||||||
|
|
||||||
|
<div onClick={() => {
|
||||||
|
props.openNewActivityModal(props.info.list.chapter.id);
|
||||||
|
}} className="flex space-x-2 items-center py-2 my-3 rounded-md justify-center outline outline-3 text-slate-500 outline-slate-200 bg-slate-50 hover:cursor-pointer">
|
||||||
|
<PlusSquare className="" size={17} />
|
||||||
|
<div className="text-sm mx-auto my-auto items-center font-bold">Add Activity</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</ActivitiesList>
|
</ActivitiesList>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
|
|
||||||
</ChapterWrapper>
|
</ChapterWrapper>
|
||||||
)}
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
|
|
|
||||||
73
front/components/Pages/Courses/ActivityIndicators.tsx
Normal file
73
front/components/Pages/Courses/ActivityIndicators.tsx
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
import ToolTip from '@components/UI/Tooltip/Tooltip'
|
||||||
|
import { getUriWithOrg } from '@services/config/config'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
course: any
|
||||||
|
orgslug: string
|
||||||
|
current_activity?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
function ActivityIndicators(props: Props) {
|
||||||
|
const course = props.course
|
||||||
|
const orgslug = props.orgslug
|
||||||
|
const courseid = course.course.course_id.replace("course_", "")
|
||||||
|
|
||||||
|
const done_activity_style = 'bg-teal-600 hover:bg-teal-700'
|
||||||
|
const black_activity_style = 'bg-black hover:bg-gray-700'
|
||||||
|
const current_activity_style = 'bg-gray-600 animate-pulse hover:bg-gray-700'
|
||||||
|
|
||||||
|
|
||||||
|
function isActivityDone(activity: any) {
|
||||||
|
if (course.trail.activities_marked_complete && course.trail.activities_marked_complete.includes(activity.id) && course.trail.status == "ongoing") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActivityCurrent(activity: any) {
|
||||||
|
let activityid = activity.id.replace("activity_", "")
|
||||||
|
if (props.current_activity && props.current_activity == activityid) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActivityClass(activity: any) {
|
||||||
|
if (isActivityDone(activity)) {
|
||||||
|
return done_activity_style
|
||||||
|
}
|
||||||
|
if (isActivityCurrent(activity)) {
|
||||||
|
return current_activity_style
|
||||||
|
}
|
||||||
|
return black_activity_style
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='grid grid-flow-col justify-stretch space-x-6'>
|
||||||
|
{course.chapters.map((chapter: any) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='grid grid-flow-col justify-stretch space-x-2'>
|
||||||
|
{chapter.activities.map((activity: any) => {
|
||||||
|
return (
|
||||||
|
<ToolTip sideOffset={-5} slateBlack content={activity.name} key={activity.id}>
|
||||||
|
<Link href={getUriWithOrg(orgslug, "") + `/course/${courseid}/activity/${activity.id.replace("activity_", "")}`}>
|
||||||
|
<div className={`h-[7px] w-auto ${getActivityClass(activity)} rounded-lg shadow-md`}></div>
|
||||||
|
|
||||||
|
</Link>
|
||||||
|
</ToolTip>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ActivityIndicators
|
||||||
|
|
@ -79,7 +79,7 @@ const contentClose = keyframes({
|
||||||
const DialogOverlay = styled(Dialog.Overlay, {
|
const DialogOverlay = styled(Dialog.Overlay, {
|
||||||
backgroundColor: blackA.blackA9,
|
backgroundColor: blackA.blackA9,
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
|
zIndex: 500,
|
||||||
inset: 0,
|
inset: 0,
|
||||||
animation: `${overlayShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
|
animation: `${overlayShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
|
||||||
'&[data-state="closed"]': {
|
'&[data-state="closed"]': {
|
||||||
|
|
@ -111,6 +111,7 @@ const DialogContent = styled(Dialog.Content, {
|
||||||
|
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
borderRadius: 18,
|
borderRadius: 18,
|
||||||
|
zIndex: 501,
|
||||||
boxShadow: 'hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px',
|
boxShadow: 'hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px',
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: '50%',
|
top: '50%',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue