Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ready and copy text buttons #34

Merged
merged 13 commits into from
Dec 8, 2024
Binary file added public/help/ready-button.webp
Binary file not shown.
44 changes: 42 additions & 2 deletions src/components/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
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';
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';
Expand All @@ -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;
Expand Down Expand Up @@ -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 (
<div
className="absolute -bottom-[0.5rem] left-0 flex w-full items-center justify-center gap-4"
style={{ height: blockHeight + 'rem' }}
>
{/* TODO: Share Button */}
<Button
color="primary"
size="lg"
className="font-semibold"
onPress={onReadyModalOpen}
>
{t('calendar.end-actions.ready')} 🚀
</Button>
<EnrolmentModal
isOpen={isReadyModalOpen}
onOpenChange={onReadyModalOpenChange}
/>
</div>
);
};

const CalendarBg = ({ currentWeek }: { currentWeek: dayjs.Dayjs }) => {
const { t } = useTranslation();

Expand Down Expand Up @@ -373,6 +410,8 @@ export const Calendar = () => {
},
});

const noCourses = useEnrolledCourses((s) => s.courses.length === 0);

return (
<div ref={ref} className="touch-pan-y">
<CalendarHeader
Expand All @@ -384,6 +423,7 @@ export const Calendar = () => {
<CalendarBg currentWeek={currentWeek} />
<CalendarCourses courses={courses} currentWeek={currentWeek} />
{isDragging && <CalendarCourseOtherTimes currentWeek={currentWeek} />}
{!noCourses && <EndActions />}
</div>
</div>
);
Expand Down
93 changes: 93 additions & 0 deletions src/components/EnrolmentModal.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Modal
isOpen={isOpen}
onOpenChange={onOpenChange}
size={isOnlyCourse ? 'xs' : '2xl'}
>
<ModalContent>
<ModalHeader className="flex-col">
<div>{t('calendar.end-actions.ready')}</div>
<div className="text-xs font-normal">
Copy the numbers below and enter them on the enrollment page of
Access Adelaide.
</div>
</ModalHeader>
<ModalBody className={clsx(!isOnlyCourse && 'grid grid-cols-2')}>
{enrolledCourses.map((c) => (
<Card key={c.id}>
<CardHeader className="flex-col text-center">
<p className="text-lg font-black">
{c.name.subject} {c.name.code}
</p>
<p className="text-sm">{c.name.title}</p>
</CardHeader>
<Divider />
<CardBody className="grid grid-cols-2 items-center justify-center gap-2">
{c.classes.map((cls) => (
<div
key={cls.typeId}
className="rounded-lg border *:p-1 *:text-center"
>
<div className="border-b font-bold">{cls.type}</div>
<div>{cls.classNumber}</div>
</div>
))}
</CardBody>
phoenixpereira marked this conversation as resolved.
Show resolved Hide resolved
</Card>
))}
</ModalBody>
<ModalFooter className="justify-between">
<Tooltip content={t('calendar.end-actions.copy')} size="sm">
<Button
isIconOnly
className="text-xl"
onPress={copyText}
variant="flat"
>
📋
</Button>
</Tooltip>
<Button
href="https://access.adelaide.edu.au/"
as={Link}
showAnchorIcon
target="_blank"
>
Access Adelaide
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
};
7 changes: 7 additions & 0 deletions src/components/HelpModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
1 change: 1 addition & 0 deletions src/components/Tips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const TIPS = [
<a href="https://csclub.org.au/open-source">CS Club Open Source Team</a> to
work on projects like this!
</>,
<>You can search for courses using abbreviations</>,
];

const tips = shuffle(TIPS);
Expand Down
24 changes: 24 additions & 0 deletions src/helpers/export-calendar.ts
Original file line number Diff line number Diff line change
@@ -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 };
};
10 changes: 8 additions & 2 deletions src/locales/en-au.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
10 changes: 8 additions & 2 deletions src/locales/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@
"十一月",
"十二月"
],
"immoveable-course": "此课程无法移动"
"immoveable-course": "此课程无法移动",
"end-actions": {
"copy": "复制到剪切板",
"ready": "准备选课",
"copy-success": "已成功复制到剪切板!"
}
},
"help": {
"title": "如何使用 MyTimetable",
Expand All @@ -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": "下一步",
Expand Down
Loading