Merge pull request #73 from learnhouse/swve/eng-21-switch-to-modal-for-course-creation

Switch to modal for course creation
This commit is contained in:
Badr B 2023-04-21 00:15:03 +02:00 committed by GitHub
commit c9ad26782f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 137 additions and 76 deletions

View file

@ -1,70 +0,0 @@
"use client";
import { useRouter } from "next/navigation";
import React from "react";
import { Title } from "@components/UI/Elements/Styles/Title";
import { createNewCourse } from "@services/courses/courses";
import { getOrganizationContextInfo } from "@services/organizations/orgs";
import { getUriWithOrg } from "@services/config/config";
const NewCoursePage = (params: any) => {
const router = useRouter();
const orgslug = params.params.orgslug;
const [name, setName] = React.useState("");
const [description, setDescription] = React.useState("");
const [isLoading, setIsLoading] = React.useState(false);
const [thumbnail, setThumbnail] = React.useState(null) as any;
const [orgId, setOrgId] = React.useState(null) as any;
const getOrgMetadata = async () => {
const org = await getOrganizationContextInfo(orgslug);
setOrgId(org.org_id);
}
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
const handleDescriptionChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setDescription(event.target.value);
};
const handleThumbnailChange = (event: React.ChangeEvent<any>) => {
setThumbnail(event.target.files[0]);
};
const handleSubmit = async (e: any) => {
e.preventDefault();
let status = await createNewCourse(orgId, { name, description }, thumbnail);
// TODO : wow this is terrible - fix this
if (status.org_id == orgId) {
router.push(getUriWithOrg(orgslug, `/courses`));
} else {
alert("Error creating course, please see console logs");
console.log(status);
}
};
React.useEffect(() => {
if (orgslug) {
getOrgMetadata();
}
}, [isLoading, orgslug]);
return (
<>
<Title>New Course </Title>
<hr />
Name : <input onChange={handleNameChange} type="text" /> <br />
Description : <input onChange={handleDescriptionChange} type="text" /> <br />
Cover Photo : <input onChange={handleThumbnailChange} type="file" /> <br />
Learnings (empty for now) (separated by ; ) : <textarea id="story" name="story" rows={5} cols={33} /> <br />
<button onClick={handleSubmit}>Create</button>
</>
);
};
export default NewCoursePage;

View file

@ -9,10 +9,13 @@ import { deleteCourseFromBackend } from "@services/courses/courses";
import useSWR, { mutate } from "swr"; import useSWR, { mutate } from "swr";
import { swrFetcher } from "@services/utils/ts/requests"; import { swrFetcher } from "@services/utils/ts/requests";
import { Edit2, Trash } from "lucide-react"; import { Edit2, Trash } from "lucide-react";
import Modal from "@components/UI/Modal/Modal";
import CreateCourseModal from "@components/Pages/CreateCourse/CreateCourse";
const CoursesIndexPage = (params: any) => { const CoursesIndexPage = (params: any) => {
const router = useRouter(); const router = useRouter();
const orgslug = params.params.orgslug; const orgslug = params.params.orgslug;
const [newCourseModal, setNewCourseModal] = React.useState(false);
const { data: courses, error: error } = useSWR(`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`, swrFetcher); const { data: courses, error: error } = useSWR(`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`, swrFetcher);
@ -21,18 +24,34 @@ const CoursesIndexPage = (params: any) => {
mutate(`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`); mutate(`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`);
} }
async function closeNewCourseModal() {
setNewCourseModal(false);
}
// function to remove "course_" from the course_id // function to remove "course_" from the course_id
function removeCoursePrefix(course_id: string) { function removeCoursePrefix(course_id: string) {
return course_id.replace("course_", ""); return course_id.replace("course_", "");
} }
return ( return (
<> <>
<Title> <Title>
Courses :{" "} Courses {" "}
<Link href={getUriWithOrg(orgslug, "/courses/new")}> <Modal
<button>+</button> isDialogOpen={newCourseModal}
</Link>{" "} onOpenChange={setNewCourseModal}
minHeight="md"
dialogContent={<CreateCourseModal
closeModal={closeNewCourseModal}
orgslug={orgslug}
></CreateCourseModal>}
dialogTitle="Create Course"
dialogDescription="Create a new course"
dialogTrigger={
<button> Add Course +
</button>
}
/>
</Title> </Title>
{error && <p>Failed to load</p>} {error && <p>Failed to load</p>}
{!courses ? ( {!courses ? (

View file

@ -0,0 +1,112 @@
import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, Input, Textarea } from '@components/UI/Form/Form'
import * as Form from '@radix-ui/react-form'
import { getAPIUrl, getUriWithOrg } from '@services/config/config';
import { FormMessage } from "@radix-ui/react-form";
import { createNewCourse } from '@services/courses/courses';
import { getOrganizationContextInfo } from '@services/organizations/orgs';
import React, { useState } from 'react'
import { BarLoader } from 'react-spinners'
import { mutate } from 'swr';
function CreateCourseModal({ closeModal, orgslug }: any) {
const [isSubmitting, setIsSubmitting] = useState(false);
const [name, setName] = React.useState("");
const [description, setDescription] = React.useState("");
const [isLoading, setIsLoading] = React.useState(false);
const [thumbnail, setThumbnail] = React.useState(null) as any;
const [orgId, setOrgId] = React.useState(null) as any;
const getOrgMetadata = async () => {
const org = await getOrganizationContextInfo(orgslug);
setOrgId(org.org_id);
}
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
const handleDescriptionChange = (event: React.ChangeEvent<any>) => {
setDescription(event.target.value);
};
const handleThumbnailChange = (event: React.ChangeEvent<any>) => {
setThumbnail(event.target.files[0]);
};
const handleSubmit = async (e: any) => {
e.preventDefault();
setIsSubmitting(true);
let status = await createNewCourse(orgId, { name, description }, thumbnail);
mutate(`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`);
setIsSubmitting(false);
if (status.org_id == orgId) {
closeModal();
} else {
alert("Error creating course, please see console logs");
console.log(status);
}
};
React.useEffect(() => {
if (orgslug) {
getOrgMetadata();
}
}, [isLoading, orgslug]);
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="course-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course name</FormLabel>
<FormMessage match="valueMissing">Please provide a course name</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleNameChange} type="text" required />
</Form.Control>
</FormField>
<FormField name="course-desc">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course description</FormLabel>
<FormMessage match="valueMissing">Please provide a course description</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea onChange={handleDescriptionChange} required />
</Form.Control>
</FormField>
<FormField name="course-thumbnail">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course thumbnail</FormLabel>
<FormMessage match="valueMissing">Please provide a thumbnail for your course</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleThumbnailChange} type="file" required />
</Form.Control>
</FormField>
<FormField name="course-learnings">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Course Learnings</FormLabel>
<FormMessage match="valueMissing">Please provide learning elements, separated by comma (,)</FormMessage>
</Flex>
<Form.Control asChild>
<Textarea required />
</Form.Control>
</FormField>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{ borderRadius: 60, }} width={60} color="#ffffff" />
: "Create Course"}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
)
}
export default CreateCourseModal

View file

@ -27,7 +27,7 @@ export const Menu = (props : any ) => {
<SearchArea> <SearchArea>
<Search> <Search>
<ToolTip content={<div> <ToolTip content={<div>
<p>{process.env.VERCEL_GIT_COMMIT_SHA}</p> <p>{process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA}</p>
</div>}><PreAlphaLabel>pre-alpha</PreAlphaLabel></ToolTip> </div>}><PreAlphaLabel>pre-alpha</PreAlphaLabel></ToolTip>
</Search> </Search>
</SearchArea> </SearchArea>