feat: init new modal

This commit is contained in:
swve 2023-04-08 15:11:24 +02:00
parent f4c239d848
commit ca5110e4f7
7 changed files with 283 additions and 26 deletions

View file

@ -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();
@ -123,6 +124,8 @@ function CourseEdit(params: any) {
};
const closeNewActivityModal = () => {
console.log("closeNewActivityModal");
setNewActivityModal(false);
};
@ -233,13 +236,22 @@ function CourseEdit(params: any) {
<Page>
<Title>
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>
</Title>
{newChapterModal && <NewChapterModal closeModal={closeNewChapterModal} submitChapter={submitChapter}></NewChapterModal>}
{newActivityModal && (
<NewActivityModal
</Title>-
<Modal
isDialogOpen={newActivityModal}
onOpenChange={setNewActivityModal}
minHeight="md"
dialogContent={<NewActivityModal
closeModal={closeNewActivityModal}
submitFileActivity={submitFileActivity}
submitActivity={submitActivity}
chapterId={newActivityModalData}
></NewActivityModal>
)}
></NewActivityModal>}
dialogTitle="Create Activity"
dialogDescription="Choose between types of activities to add to the course"
/>
<br />
{winReady && (
@ -287,7 +305,7 @@ function CourseEdit(params: any) {
</DragDropContext>
</ChapterlistWrapper>
)}
</Page>
</Page >
</>
);
}

View file

@ -21,8 +21,11 @@ function Chapter(props: any) {
props.openNewActivityModal(props.info.list.chapter.id);
}}
>
Create Activity
</button>
<button
onClick={() => {
props.deleteChapter(props.info.list.chapter.id);

View file

@ -9,20 +9,18 @@ function NewActivityModal({ closeModal, submitActivity, submitFileActivity, chap
const [selectedView, setSelectedView] = useState("home");
return (
<Modal>
<button onClick={ () => {setSelectedView("home")}}>
<div>
<button onClick={() => { setSelectedView("home") }}>
<ArrowLeftIcon />
</button>
<button onClick={closeModal}>
<Cross1Icon />
</button>
<h1>Add New Activity</h1>
<br />
{selectedView === "home" && (
<ActivityChooserWrapper>
<ActivityButton onClick={() => {setSelectedView("dynamic")}}>📄</ActivityButton>
<ActivityButton onClick={() => {setSelectedView("video")}}>📹</ActivityButton>
<ActivityButton onClick={() => { setSelectedView("dynamic") }}>📄</ActivityButton>
<ActivityButton onClick={() => { setSelectedView("video") }}>📹</ActivityButton>
</ActivityChooserWrapper>
)}
@ -34,7 +32,7 @@ function NewActivityModal({ closeModal, submitActivity, submitFileActivity, chap
<VideoModal submitFileActivity={submitFileActivity} chapterId={chapterId} />
)}
</Modal>
</div>
);
}

View file

@ -20,13 +20,13 @@ function NewChapterModal({ submitChapter , closeModal }: any) {
};
return (
<Modal>
<h1>Add New Chapter <button onClick={closeModal}>X</button></h1>
<div>
<button onClick={closeModal}>X</button>
<input type="text" onChange={handleChapterNameChange} placeholder="Chapter Name" /> <br />
<input type="text" onChange={handleChapterDescriptionChange} placeholder="Chapter Description" />
<br />
<button onClick={handleSubmit}>Add Chapter</button>
</Modal>
</div>
);
}

View file

@ -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) => (
<Dialog.Root open={params.isDialogOpen} onOpenChange={params.onOpenChange}>
{params.dialogTrigger ? (
<Dialog.Trigger asChild>
{params.dialogTrigger}
</Dialog.Trigger>
) : null}
<Dialog.Portal>
<DialogOverlay />
<DialogContent minHeight={params.minHeight}>
<DialogTopBar>
<DialogTitle>{params.dialogTitle}</DialogTitle>
<DialogDescription>
{params.dialogDescription}
</DialogDescription>
</DialogTopBar>
{params.dialogContent}
<Dialog.Close asChild>
{params.dialogClose}
</Dialog.Close>
</DialogContent>
</Dialog.Portal>
</Dialog.Root>
);
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;

View file

@ -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",

View file

@ -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",