diff --git a/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/edit/page.tsx b/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/edit/page.tsx index d4be427d..1b2a686a 100644 --- a/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/edit/page.tsx +++ b/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/edit/page.tsx @@ -14,6 +14,7 @@ import NewChapterModal from "@components/Modals/CourseEdit/NewChapter"; import NewActivityModal from "@components/Modals/CourseEdit/NewActivity"; import { createActivity, createFileActivity } from "@services/courses/activities"; import { getOrganizationContextInfo } from "@services/organizations/orgs"; +import Modal from "@components/UI/Modal/Modal"; function CourseEdit(params: any) { const router = useRouter(); @@ -32,7 +33,7 @@ function CourseEdit(params: any) { const courseid = params.params.courseid; const orgslug = params.params.orgslug; - + async function getCourseChapters() { const courseChapters = await getCourseChaptersMetadata(courseid); @@ -123,6 +124,8 @@ function CourseEdit(params: any) { }; const closeNewActivityModal = () => { + console.log("closeNewActivityModal"); + setNewActivityModal(false); }; @@ -233,13 +236,22 @@ function CourseEdit(params: any) { Edit Course {" "} - <button - onClick={() => { - setNewChapterModal(true); - }} - > - Add chapter + - </button> + <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 onClick={() => { updateChapters(); @@ -247,16 +259,22 @@ function CourseEdit(params: any) { > Save </button> - - {newChapterModal && } - {newActivityModal && ( - - + + - )} + >} + dialogTitle="Create Activity" + dialogDescription="Choose between types of activities to add to the course" + + />
{winReady && ( @@ -287,7 +305,7 @@ function CourseEdit(params: any) { )} -
+ ); } diff --git a/front/components/Drags/Chapter.tsx b/front/components/Drags/Chapter.tsx index f4253593..850e189a 100644 --- a/front/components/Drags/Chapter.tsx +++ b/front/components/Drags/Chapter.tsx @@ -21,8 +21,11 @@ function Chapter(props: any) { props.openNewActivityModal(props.info.list.chapter.id); }} > + Create Activity + + -

Add New Activity

-
{selectedView === "home" && ( - {setSelectedView("dynamic")}}>✨📄 - {setSelectedView("video")}}>📹 + { setSelectedView("dynamic") }}>✨📄 + { setSelectedView("video") }}>📹 )} @@ -33,8 +31,8 @@ function NewActivityModal({ closeModal, submitActivity, submitFileActivity, chap {selectedView === "video" && ( )} - - + + ); } diff --git a/front/components/Modals/CourseEdit/NewChapter.tsx b/front/components/Modals/CourseEdit/NewChapter.tsx index 1910ebde..aa7549ca 100644 --- a/front/components/Modals/CourseEdit/NewChapter.tsx +++ b/front/components/Modals/CourseEdit/NewChapter.tsx @@ -20,13 +20,13 @@ function NewChapterModal({ submitChapter , closeModal }: any) { }; return ( - -

Add New Chapter

+
+

- +
); } diff --git a/front/components/UI/Modal/Modal.tsx b/front/components/UI/Modal/Modal.tsx new file mode 100644 index 00000000..ff49fadd --- /dev/null +++ b/front/components/UI/Modal/Modal.tsx @@ -0,0 +1,226 @@ +import React from 'react'; +import * as Dialog from '@radix-ui/react-dialog'; +import { styled, keyframes } from '@stitches/react'; +import { violet, blackA, mauve, green } from '@radix-ui/colors'; +import { Cross2Icon } from '@radix-ui/react-icons'; + +type ModalParams = { + dialogTitle: string; + dialogDescription: string; + dialogContent: React.ReactNode; + dialogClose?: React.ReactNode | null; + dialogTrigger?: React.ReactNode; + onOpenChange: any; + isDialogOpen?: boolean; + minHeight?: "sm" | "md" | "lg" | "xl" +}; + +const Modal = (params: ModalParams) => ( + + {params.dialogTrigger ? ( + + {params.dialogTrigger} + + ) : null} + + + + + + {params.dialogTitle} + + {params.dialogDescription} + + + {params.dialogContent} + + {params.dialogClose} + + + + +); + +const overlayShow = keyframes({ + '0%': { opacity: 0 }, + '100%': { opacity: 1 }, +}); + +const overlayClose = keyframes({ + '0%': { opacity: 1 }, + '100%': { opacity: 0 }, +}); + +const contentShow = keyframes({ + '0%': { opacity: 0, transform: 'translate(-50%, -50%) scale(.96)' }, + '100%': { opacity: 1, transform: 'translate(-50%, -50%) scale(1)' }, +}); + +const contentClose = keyframes({ + '0%': { opacity: 1, transform: 'translate(-50%, -50%) scale(1)' }, + '100%': { opacity: 0, transform: 'translate(-50%, -52%) scale(.96)' }, +}); + +const DialogOverlay = styled(Dialog.Overlay, { + backgroundColor: blackA.blackA9, + position: 'fixed', + + inset: 0, + animation: `${overlayShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`, + '&[data-state="closed"]': { + animation: `${overlayClose} 150ms cubic-bezier(0.16, 1, 0.3, 1)`, + }, +}); + +const DialogContent = styled(Dialog.Content, { + + variants: { + minHeight: { + 'sm': { + minHeight: '300px', + }, + 'md': { + minHeight: '500px', + }, + 'lg': { + minHeight: '700px', + }, + 'xl': { + minHeight: '900px', + }, + }, + }, + + backgroundColor: 'white', + borderRadius: 18, + boxShadow: 'hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px', + position: 'fixed', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '90vw', + overflow: 'hidden', + maxHeight: '85vh', + minHeight: '300px', + maxWidth: '600px', + padding: 11, + animation: `${contentShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`, + '&:focus': { outline: 'none' }, + + '&[data-state="closed"]': { + animation: `${contentClose} 150ms cubic-bezier(0.16, 1, 0.3, 1)`, + }, + transition: "max-height 0.3s ease-out", +}); + +const DialogTopBar = styled('div', { + background: "#F7F7F7", + padding: "8px 14px ", + borderRadius: 14, +}); +const DialogTitle = styled(Dialog.Title, { + margin: 0, + fontWeight: 700, + letterSpacing: "-0.05em", + padding: 0, + color: mauve.mauve12, + fontSize: 21, +}); + +const DialogDescription = styled(Dialog.Description, { + color: mauve.mauve11, + letterSpacing: "-0.03em", + fontSize: 15, + padding: 0, + margin: 0, +}); + +const Flex = styled('div', { display: 'flex' }); + +const Button = styled('button', { + all: 'unset', + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + borderRadius: 4, + padding: '0 15px', + fontSize: 15, + lineHeight: 1, + fontWeight: 500, + height: 35, + + variants: { + variant: { + violet: { + backgroundColor: 'white', + color: violet.violet11, + boxShadow: `0 2px 10px ${blackA.blackA7}`, + '&:hover': { backgroundColor: mauve.mauve3 }, + '&:focus': { boxShadow: `0 0 0 2px black` }, + }, + green: { + backgroundColor: green.green4, + color: green.green11, + '&:hover': { backgroundColor: green.green5 }, + '&:focus': { boxShadow: `0 0 0 2px ${green.green7}` }, + }, + }, + }, + + defaultVariants: { + variant: 'violet', + }, +}); + +const IconButton = styled('button', { + all: 'unset', + fontFamily: 'inherit', + borderRadius: '100%', + height: 25, + width: 25, + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + color: violet.violet11, + position: 'absolute', + top: 10, + right: 10, + + '&:hover': { backgroundColor: violet.violet4 }, + '&:focus': { boxShadow: `0 0 0 2px ${violet.violet7}` }, +}); + +const Fieldset = styled('fieldset', { + all: 'unset', + display: 'flex', + gap: 20, + alignItems: 'center', + marginBottom: 15, +}); + +const Label = styled('label', { + fontSize: 15, + color: violet.violet11, + width: 90, + textAlign: 'right', +}); + +const Input = styled('input', { + all: 'unset', + width: '100%', + flex: '1', + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + borderRadius: 4, + padding: '0 10px', + fontSize: 15, + lineHeight: 1, + color: violet.violet11, + boxShadow: `0 0 0 1px ${violet.violet7}`, + height: 35, + + '&:focus': { boxShadow: `0 0 0 2px ${violet.violet8}` }, +}); + +export default Modal; \ No newline at end of file diff --git a/front/package-lock.json b/front/package-lock.json index 749c6bb9..b562f2b7 100644 --- a/front/package-lock.json +++ b/front/package-lock.json @@ -8,6 +8,7 @@ "name": "learnhouse", "version": "0.1.0", "dependencies": { + "@radix-ui/colors": "^0.1.8", "@radix-ui/react-dialog": "^1.0.2", "@radix-ui/react-icons": "^1.1.1", "@stitches/react": "^1.2.8", @@ -2352,6 +2353,11 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@radix-ui/colors": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/colors/-/colors-0.1.8.tgz", + "integrity": "sha512-jwRMXYwC0hUo0mv6wGpuw254Pd9p/R6Td5xsRpOmaWkUHlooNWqVcadgyzlRumMq3xfOTXwJReU0Jv+EIy4Jbw==" + }, "node_modules/@radix-ui/primitive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz", @@ -8906,6 +8912,11 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" }, + "@radix-ui/colors": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/colors/-/colors-0.1.8.tgz", + "integrity": "sha512-jwRMXYwC0hUo0mv6wGpuw254Pd9p/R6Td5xsRpOmaWkUHlooNWqVcadgyzlRumMq3xfOTXwJReU0Jv+EIy4Jbw==" + }, "@radix-ui/primitive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz", diff --git a/front/package.json b/front/package.json index 50b1bf6c..f7ab0554 100644 --- a/front/package.json +++ b/front/package.json @@ -9,6 +9,7 @@ "lint": "next lint" }, "dependencies": { + "@radix-ui/colors": "^0.1.8", "@radix-ui/react-dialog": "^1.0.2", "@radix-ui/react-icons": "^1.1.1", "@stitches/react": "^1.2.8",