diff --git a/public/help/ready-button.webp b/public/help/ready-button.webp
new file mode 100644
index 0000000..c9a40c8
Binary files /dev/null and b/public/help/ready-button.webp differ
diff --git a/src/components/Calendar.tsx b/src/components/Calendar.tsx
index 212df35..a5d8d4b 100644
--- a/src/components/Calendar.tsx
+++ b/src/components/Calendar.tsx
@@ -1,4 +1,4 @@
-import { Button, Tooltip } from '@nextui-org/react';
+import { Button, Tooltip, useDisclosure } from '@nextui-org/react';
import clsx from 'clsx';
import { useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
@@ -6,7 +6,11 @@ import { create } from 'zustand';
import { WEEK_DAYS } from '../constants/week-days';
import { YEAR } from '../constants/year';
-import { useCourseColor, useEnrolledCourse } from '../data/enrolled-courses';
+import {
+ useCourseColor,
+ useEnrolledCourse,
+ useEnrolledCourses,
+} from '../data/enrolled-courses';
import { useCalendar, useOtherWeekCourseTimes } from '../helpers/calendar';
import { useCalendarHourHeight } from '../helpers/calendar-hour-height';
import { calcHoursDuration } from '../helpers/hours-duration';
@@ -15,6 +19,7 @@ import type dayjs from '../lib/dayjs';
import type { DateTimeRange, WeekCourse, WeekCourses } from '../types/course';
import { timeToDayjs } from '../utils/date';
import { useDrag, useDrop } from '../utils/dnd';
+import { EnrolmentModal } from './EnrolmentModal';
type DraggingCourseState = {
isDragging: boolean;
@@ -175,6 +180,38 @@ const CalendarHeader = ({
);
};
+const EndActions = () => {
+ const { t } = useTranslation();
+
+ const blockHeight = useCalendarHourHeight((s) => s.height);
+
+ const {
+ isOpen: isReadyModalOpen,
+ onOpen: onReadyModalOpen,
+ onOpenChange: onReadyModalOpenChange,
+ } = useDisclosure();
+ return (
+
+ {/* TODO: Share Button */}
+
+
+
+ );
+};
+
const CalendarBg = ({ currentWeek }: { currentWeek: dayjs.Dayjs }) => {
const { t } = useTranslation();
@@ -373,6 +410,8 @@ export const Calendar = () => {
},
});
+ const noCourses = useEnrolledCourses((s) => s.courses.length === 0);
+
return (
{
{isDragging && }
+ {!noCourses && }
);
diff --git a/src/components/EnrolmentModal.tsx b/src/components/EnrolmentModal.tsx
new file mode 100644
index 0000000..9d385c8
--- /dev/null
+++ b/src/components/EnrolmentModal.tsx
@@ -0,0 +1,93 @@
+import {
+ Button,
+ Card,
+ CardBody,
+ CardHeader,
+ Divider,
+ Link,
+ Modal,
+ ModalBody,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ Tooltip,
+} from '@nextui-org/react';
+import clsx from 'clsx';
+import { useTranslation } from 'react-i18next';
+
+import { useDetailedEnrolledCourses } from '../data/enrolled-courses';
+import { useExportCalendar } from '../helpers/export-calendar';
+
+type ReadyModalProps = {
+ isOpen: boolean;
+ onOpenChange: (isOpen: boolean) => void;
+};
+export const EnrolmentModal = ({ isOpen, onOpenChange }: ReadyModalProps) => {
+ const { t } = useTranslation();
+ const { copyText } = useExportCalendar();
+
+ const enrolledCourses = useDetailedEnrolledCourses();
+ const isOnlyCourse = enrolledCourses.length === 1;
+
+ return (
+
+
+
+ {t('calendar.end-actions.ready')}
+
+ Copy the numbers below and enter them on the enrollment page of
+ Access Adelaide.
+
+
+
+ {enrolledCourses.map((c) => (
+
+
+
+ {c.name.subject} {c.name.code}
+
+ {c.name.title}
+
+
+
+ {c.classes.map((cls) => (
+
+
{cls.type}
+
{cls.classNumber}
+
+ ))}
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/HelpModal.tsx b/src/components/HelpModal.tsx
index 1b67bb7..cdc909a 100644
--- a/src/components/HelpModal.tsx
+++ b/src/components/HelpModal.tsx
@@ -66,6 +66,13 @@ export const HelpModal = () => {
alt: 'Course modal to change class time',
},
},
+ {
+ content: t('help.steps.ready-button'),
+ image: {
+ path: '/help/ready-button.webp',
+ alt: 'Ready button at bottom',
+ },
+ },
{
content: t('help.steps.access-adelaide'),
image: {
diff --git a/src/components/Tips.tsx b/src/components/Tips.tsx
index a30bea6..154230d 100644
--- a/src/components/Tips.tsx
+++ b/src/components/Tips.tsx
@@ -44,6 +44,7 @@ const TIPS = [
CS Club Open Source Team to
work on projects like this!
>,
+ <>You can search for courses using abbreviations>,
];
const tips = shuffle(TIPS);
diff --git a/src/helpers/export-calendar.ts b/src/helpers/export-calendar.ts
new file mode 100644
index 0000000..b3d432d
--- /dev/null
+++ b/src/helpers/export-calendar.ts
@@ -0,0 +1,24 @@
+import { useTranslation } from 'react-i18next';
+import { toast } from 'sonner';
+
+import { useDetailedEnrolledCourses } from '../data/enrolled-courses';
+
+export const useExportCalendar = () => {
+ const { t } = useTranslation();
+
+ const enrolledCourses = useDetailedEnrolledCourses();
+ const copyText = async () => {
+ const res = enrolledCourses.map((c) => ({
+ name: c.name.title + '\n' + c.name.subject + ' ' + c.name.code,
+ classes: c.classes
+ .map(({ type, classNumber }) => type + ': ' + classNumber)
+ .join('\n'),
+ }));
+ const resStr = res.map((d) => d.name + '\n\n' + d.classes).join('\n\n');
+ const advertisement =
+ 'Planned with MyTimetable\nhttps://mytimetable.csclub.org.au/';
+ await navigator.clipboard.writeText(resStr + '\n\n\n' + advertisement);
+ toast.success(t('calendar.end-actions.copy-success'));
+ };
+ return { copyText };
+};
diff --git a/src/locales/en-au.json b/src/locales/en-au.json
index 00f6d64..59758d0 100644
--- a/src/locales/en-au.json
+++ b/src/locales/en-au.json
@@ -39,7 +39,12 @@
"November",
"December"
],
- "immoveable-course": "Immoveable course"
+ "immoveable-course": "Immoveable course",
+ "end-actions": {
+ "copy": "Copy to clipboard",
+ "ready": "Ready for Enrolment",
+ "copy-success": "Copied to clipboard!"
+ }
},
"help": {
"title": "How to use MyTimetable",
@@ -51,7 +56,8 @@
"change-week": "Change the calendar week to see more classes.",
"course-details": "Click your enrolled course to see details of your enrolled classes.",
"course-modal": "If you encounter any class clashes when using MyTimetable, you can open the modal to change the class.",
- "access-adelaide": "You can enrol for courses in Access Adelaide by using the class numbers, once you are happy with your class times."
+ "ready-button": "Once you are satisfied with your class times, click the \"Ready for Enrollment\" button at the bottom of the calendar.",
+ "access-adelaide": "You can easily enroll in courses on Access Adelaide using the class numbers shown in the modal."
},
"actions": {
"next-step": "Next Step",
diff --git a/src/locales/zh-cn.json b/src/locales/zh-cn.json
index d9e410d..ff5288d 100644
--- a/src/locales/zh-cn.json
+++ b/src/locales/zh-cn.json
@@ -39,7 +39,12 @@
"十一月",
"十二月"
],
- "immoveable-course": "此课程无法移动"
+ "immoveable-course": "此课程无法移动",
+ "end-actions": {
+ "copy": "复制到剪切板",
+ "ready": "准备选课",
+ "copy-success": "已成功复制到剪切板!"
+ }
},
"help": {
"title": "如何使用 MyTimetable",
@@ -51,7 +56,8 @@
"change-week": "切换周数查看更多课程",
"course-details": "点击你的选课查看详情",
"course-modal": "如果在使用 MyTimetable 时遇到任何课程冲突,可以随时打开详情弹窗来更改课程",
- "access-adelaide": "课程调整完毕后,可以使用详情中的 Class Number 在 Access Adelaide 中进行选课"
+ "ready-button": "课程调整完毕后,点击日历底部的“准备选课”按钮",
+ "access-adelaide": "你可以用弹窗中的 Class Number 在 Access Adelaide 中进行选课"
},
"actions": {
"next-step": "下一步",