Skip to content

Commit

Permalink
Merge pull request #42 from ItsukiKigoshi/39-feat-google-drive-sync
Browse files Browse the repository at this point in the history
[feat] Add Course Manually
  • Loading branch information
ItsukiKigoshi authored Feb 4, 2024
2 parents 2e18e47 + 8fa4541 commit 6ffe564
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 84 deletions.
113 changes: 60 additions & 53 deletions src/components/AddCourse/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { Course } from "@/src/type/Types";
import {
ActionIcon,
Grid,
Group,
HoverCard,
Text,
TextInput,
rem,
} from "@mantine/core";
import { IconPlus, IconQuestionMark } from "@tabler/icons-react";
import { Button, Flex } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { IconPlus } from "@tabler/icons-react";
import { useEffect, useState } from "react";
import ModalCourseEditor from "../ModalCourseEditor";

export default function AddCourse(props: {
addCourse: (course: Course) => void;
courses: Course[];
courseController: {
addCourse: (course: Course) => void;
updateCourse: (course: Course) => void;
};
}) {
const [query, setQuery] = useState("");

Expand All @@ -25,6 +22,9 @@ export default function AddCourse(props: {
}
}, [query]);

const [modalCourseEditorOpened, { open: editorOpen, close: editorClose }] =
useDisclosure(false);

function parseCourseInfo(str: string): Course | undefined {
// replace "(" or "<" with "," in front of the schedule, and remove ")" and ">" after schedule
const modifiedStr = str
Expand Down Expand Up @@ -129,53 +129,60 @@ export default function AddCourse(props: {
if (isAlreadyInList(course)) {
setErrorMessage(`Already in the List! regno:${course.regno}`);
} else {
props.addCourse(course);
props.courseController.addCourse(course);
setQuery("");
}
}
};

return (
<Grid p="xs">
<Grid.Col span="auto">
<form onSubmit={handleSubmit}>
<TextInput
m="0"
placeholder="Add Course"
w="100%"
leftSection={
<IconPlus
style={{ width: rem(12), height: rem(12) }}
stroke={1.5}
/>
}
styles={{ section: { pointerEvents: "none" } }}
value={query}
error={errorMessage}
onChange={(e) => setQuery(e.currentTarget.value)}
/>
</form>
</Grid.Col>
<Grid.Col span="content">
<Group justify="center">
<HoverCard>
<HoverCard.Target>
<ActionIcon
color="gray"
size="lg"
component="a"
href="https://github.com/ItsukiKigoshi/catalogue.icu/releases/tag/v0.0.0"
target="_blank"
>
<IconQuestionMark />
</ActionIcon>
</HoverCard.Target>
<HoverCard.Dropdown>
<Text>Copy & Paste from Course Offerings!</Text>
</HoverCard.Dropdown>
</HoverCard>
</Group>
</Grid.Col>
</Grid>
<>
<ModalCourseEditor
title={"Add Course Manually"}
course={{
regno: 10000,
season: "Spring",
ay: 2024,
no: "",
lang: "E",
e: "",
j: "",
schedule: [],
unit: 0,
color: "",
isEnrolled: true,
modified: new Date(),
}}
updateCourse={props.courseController.updateCourse}
modalCourseEditorOpened={modalCourseEditorOpened}
editorClose={editorClose}
/>
<Flex justify="center" gap="xs">
<Button
leftSection={<IconPlus />}
color="gray"
onClick={editorOpen}
w="100%"
>
Add Manually
</Button>

{/* <TextInput
m="0"
placeholder="Paste it!"
leftSection={
<IconClipboard
style={{ width: rem(12), height: rem(12) }}
stroke={1.5}
/>
}
styles={{ section: { pointerEvents: "none" } }}
value={query}
error={errorMessage}
onChange={(e) => setQuery(e.currentTarget.value)}
onSubmit={handleSubmit}
/>*/}
</Flex>
</>
);
}
81 changes: 51 additions & 30 deletions src/components/ModalCourseEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@ import {
TagsInput,
TextInput,
} from "@mantine/core";
import { useState } from "react";
import { useEffect, useState } from "react";

export default function ModalCourseEditor(props: {
title: string;
course: Course;
updateCourse: (course: Course) => void;
modalCourseEditorOpened: boolean;
editorClose: () => void;
modalDetailClose: () => void;
modalDetailClose?: () => void;
}) {
const [editedCourse, setEditedCourse] = useState<Course>(props.course);
// Reset the edited course when the props.course is changed
useEffect(() => {
setEditedCourse(props.course);
}, [props.course]);

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
Expand All @@ -34,37 +38,53 @@ export default function ModalCourseEditor(props: {
event.preventDefault();
props.updateCourse(editedCourse);
props.editorClose();
props.modalDetailClose();
props?.modalDetailClose?.();
};

const scheduleSelectData = ["M", "TU", "W", "TH", "F", "SA"].map((day) => ({
group: day,
items: ["1", "2", "3", "4", "5", "6", "7"].map(
(period) => `${period}/${day}`
),
}));

return (
<Modal
opened={props.modalCourseEditorOpened}
onClose={() => {
props.editorClose();
props.modalDetailClose();
props?.modalDetailClose?.();
}}
title={props.title}
centered
closeOnClickOutside={false}
closeOnEscape={false}
>
<form onSubmit={handleSubmit}>
<Stack gap="xs" pb="xs">
<Group grow>
<TextInput
<NumberInput
label="Registration Number"
withAsterisk
required
disabled
placeholder={props.course.regno.toString()}
placeholder={"18807"}
name="regno"
value={editedCourse.regno.toString()}
onChange={handleInputChange}
value={editedCourse.regno}
min={10000}
max={99999}
onChange={(value) =>
setEditedCourse((prevCourse) => ({
...prevCourse,
regno: Number(value),
}))
}
/>
<TextInput
label="Course Number"
data-autofocus
withAsterisk
required
placeholder={props.course.no}
placeholder={"WTS101"}
name="no"
value={editedCourse.no}
onChange={handleInputChange}
Expand All @@ -74,7 +94,7 @@ export default function ModalCourseEditor(props: {
label="English Title"
withAsterisk
required
placeholder={props.course.e}
placeholder={"Introductory Unsolved Cases"}
name="e"
value={editedCourse.e}
onChange={handleInputChange}
Expand All @@ -83,23 +103,25 @@ export default function ModalCourseEditor(props: {
label="Japanese Title"
withAsterisk
required
placeholder={props.course.j}
placeholder={"未解決事件入門"}
name="j"
value={editedCourse.j}
onChange={handleInputChange}
/>

<TagsInput
label="Schedule (e.g. 3/M)"
label="Schedule (e.g. 3/TH)"
placeholder="4/W, 3/TH, 5/F, ..."
withAsterisk
required
defaultValue={props.course.schedule}
name="schedule"
value={editedCourse.schedule}
data={scheduleSelectData}
onChange={(value: string[]) => {
const scheduleArray = value.map((item) => item.trim());
const validScheduleArray = scheduleArray.filter((item) =>
/^[1-7]+\/[M|TU|W|TH|F|SA]+$/.test(item)
/^[1-7]+\/(M|TU|W|TH|F|SA)$/.test(item)
);
setEditedCourse((prevCourse) => ({
...prevCourse,
Expand All @@ -110,14 +132,14 @@ export default function ModalCourseEditor(props: {
<Group grow>
<TextInput
label="Room"
placeholder={props.course.room}
placeholder={"B-221B"}
name="room"
value={editedCourse.room}
onChange={handleInputChange}
/>
<TextInput
label="Instructor"
placeholder={props.course.instructor}
placeholder={"Sherlock Holmes"}
name="instructor"
value={editedCourse.instructor}
onChange={handleInputChange}
Expand All @@ -129,9 +151,14 @@ export default function ModalCourseEditor(props: {
label="Language"
withAsterisk
required
defaultValue={props.course.lang}
name="lang"
value={editedCourse.lang}
onChange={(event) =>
setEditedCourse((prevCourse) => ({
...prevCourse,
lang: event?.currentTarget?.value || editedCourse.lang,
}))
}
data={[
{ value: "E", label: "English" },
{ value: "J", label: "Japanese" },
Expand Down Expand Up @@ -181,6 +208,7 @@ export default function ModalCourseEditor(props: {
placeholder={props.course.ay.toString()}
name="ay"
value={editedCourse.ay.toString()}
min={2000}
onChange={(value) =>
setEditedCourse((prevCourse) => ({
...prevCourse,
Expand All @@ -197,18 +225,11 @@ export default function ModalCourseEditor(props: {
placeholder={props.course.color}
name="color"
value={editedCourse.color}
onChange={
editedCourse.color
? (value) =>
setEditedCourse((prevCourse) => ({
...prevCourse,
color: value,
}))
: () =>
setEditedCourse((prevCourse) => ({
...prevCourse,
color: "#2e2e2e",
}))
onChange={(value) =>
setEditedCourse((prevCourse) => ({
...prevCourse,
color: value,
}))
}
format="hex"
withPicker={false}
Expand All @@ -230,7 +251,7 @@ export default function ModalCourseEditor(props: {
]}
/>
</Stack>
<Button type="submit">Submit</Button>
<Button type="submit">Save</Button>
</form>
</Modal>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/Navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export function Navbar(props: {
<Stack justify="flex-start" p="sm" h="100%">
<AddCourse
courses={props.courses}
addCourse={props.courseController.addCourse}
courseController={props.courseController}
/>
<ScrollArea>
{results}
Expand Down

0 comments on commit 6ffe564

Please sign in to comment.