Calendar schedules component (clicking on storybook not working)
This commit is contained in:
142
src/stories/components/CalendarSchedules.stories.tsx
Normal file
142
src/stories/components/CalendarSchedules.stories.tsx
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import { Course, Status } from '@shared/types/Course';
|
||||||
|
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import React from 'react';
|
||||||
|
import { CourseMeeting, DAY_MAP } from 'src/shared/types/CourseMeeting';
|
||||||
|
import { CourseSchedule } from 'src/shared/types/CourseSchedule';
|
||||||
|
import Instructor from 'src/shared/types/Instructor';
|
||||||
|
import { CalendarSchedules } from 'src/views/components/common/CalendarSchedules/CalendarSchedules';
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: 'Components/Common/CalendarSchedules',
|
||||||
|
component: CalendarSchedules,
|
||||||
|
parameters: {
|
||||||
|
layout: 'centered',
|
||||||
|
tags: ['autodocs'],
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
dummySchedules: { control: 'object' },
|
||||||
|
dummyActiveIndex: { control: 'number' },
|
||||||
|
},
|
||||||
|
render: (args: any) => (
|
||||||
|
<div>
|
||||||
|
<CalendarSchedules {...args} />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
} satisfies Meta<typeof CalendarSchedules>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
|
const schedules = [
|
||||||
|
new UserSchedule({
|
||||||
|
courses: [
|
||||||
|
new Course({
|
||||||
|
uniqueId: 123,
|
||||||
|
number: '311C',
|
||||||
|
fullName: "311C - Bevo's Default Course",
|
||||||
|
courseName: "Bevo's Default Course",
|
||||||
|
department: 'BVO',
|
||||||
|
creditHours: 3,
|
||||||
|
status: Status.WAITLISTED,
|
||||||
|
instructors: [new Instructor({ firstName: '', lastName: 'Bevo', fullName: 'Bevo' })],
|
||||||
|
isReserved: false,
|
||||||
|
url: '',
|
||||||
|
flags: [],
|
||||||
|
schedule: new CourseSchedule({
|
||||||
|
meetings: [
|
||||||
|
new CourseMeeting({
|
||||||
|
days: [DAY_MAP.M, DAY_MAP.W, DAY_MAP.F],
|
||||||
|
startTime: 480,
|
||||||
|
endTime: 570,
|
||||||
|
location: {
|
||||||
|
building: 'UTC',
|
||||||
|
room: '123',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
instructionMode: 'In Person',
|
||||||
|
semester: {
|
||||||
|
year: 2024,
|
||||||
|
season: 'Fall',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
name: 'Main Schedule',
|
||||||
|
}),
|
||||||
|
new UserSchedule({
|
||||||
|
courses: [
|
||||||
|
new Course({
|
||||||
|
uniqueId: 123,
|
||||||
|
number: '311C',
|
||||||
|
fullName: "311C - Bevo's Default Course",
|
||||||
|
courseName: "Bevo's Default Course",
|
||||||
|
department: 'BVO',
|
||||||
|
creditHours: 3,
|
||||||
|
status: Status.WAITLISTED,
|
||||||
|
instructors: [new Instructor({ firstName: '', lastName: 'Bevo', fullName: 'Bevo' })],
|
||||||
|
isReserved: false,
|
||||||
|
url: '',
|
||||||
|
flags: [],
|
||||||
|
schedule: new CourseSchedule({
|
||||||
|
meetings: [
|
||||||
|
new CourseMeeting({
|
||||||
|
days: [DAY_MAP.M, DAY_MAP.W, DAY_MAP.F],
|
||||||
|
startTime: 480,
|
||||||
|
endTime: 570,
|
||||||
|
location: {
|
||||||
|
building: 'UTC',
|
||||||
|
room: '123',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
instructionMode: 'In Person',
|
||||||
|
semester: {
|
||||||
|
year: 2024,
|
||||||
|
season: 'Spring',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Course({
|
||||||
|
uniqueId: 123,
|
||||||
|
number: '311C',
|
||||||
|
fullName: "311C - Bevo's Default Course",
|
||||||
|
courseName: "Bevo's Default Course",
|
||||||
|
department: 'BVO',
|
||||||
|
creditHours: 3,
|
||||||
|
status: Status.WAITLISTED,
|
||||||
|
instructors: [new Instructor({ firstName: '', lastName: 'Bevo', fullName: 'Bevo' })],
|
||||||
|
isReserved: false,
|
||||||
|
url: '',
|
||||||
|
flags: [],
|
||||||
|
schedule: new CourseSchedule({
|
||||||
|
meetings: [
|
||||||
|
new CourseMeeting({
|
||||||
|
days: [DAY_MAP.M, DAY_MAP.W, DAY_MAP.F],
|
||||||
|
startTime: 480,
|
||||||
|
endTime: 570,
|
||||||
|
location: {
|
||||||
|
building: 'UTC',
|
||||||
|
room: '123',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
instructionMode: 'In Person',
|
||||||
|
semester: {
|
||||||
|
year: 2024,
|
||||||
|
season: 'Fall',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
name: 'Backup #3',
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
dummySchedules: schedules,
|
||||||
|
dummyActiveIndex: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
36
src/stories/components/ScheduleListItem.stories.tsx
Normal file
36
src/stories/components/ScheduleListItem.stories.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ScheduleListItem from 'src/views/components/common/ScheduleListItem/ScheduleListItem';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/Common/ScheduleListItem',
|
||||||
|
component: ScheduleListItem,
|
||||||
|
parameters: {
|
||||||
|
layout: 'centered',
|
||||||
|
tags: ['autodocs'],
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
active: { control: 'boolean' },
|
||||||
|
name: { control: 'text' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = (args) => <ScheduleListItem {...args} />;
|
||||||
|
|
||||||
|
Default.args = {
|
||||||
|
name: 'My Schedule',
|
||||||
|
active: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Active = (args) => <ScheduleListItem {...args} />;
|
||||||
|
|
||||||
|
Active.args = {
|
||||||
|
name: 'My Schedule',
|
||||||
|
active: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Inactive = (args) => <ScheduleListItem {...args} />;
|
||||||
|
|
||||||
|
Inactive.args = {
|
||||||
|
name: 'My Schedule',
|
||||||
|
active: false,
|
||||||
|
};
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import AddSchedule from '~icons/material-symbols/add';
|
||||||
|
import List from '../List/List';
|
||||||
|
import ScheduleListItem from '../ScheduleListItem/ScheduleListItem';
|
||||||
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
|
export type Props = {
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
dummySchedules?: UserSchedule[];
|
||||||
|
dummyActiveIndex?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function CalendarSchedules(props: Props) {
|
||||||
|
const [activeScheduleIndex, setActiveScheduleIndex] = useState(props.dummyActiveIndex || 0);
|
||||||
|
const [schedules, setSchedules] = useState(props.dummySchedules || []);
|
||||||
|
|
||||||
|
let scheduleComponents = schedules.map((schedule, index) => (
|
||||||
|
<div onClick={() => setActiveScheduleIndex(index)}>
|
||||||
|
<ScheduleListItem
|
||||||
|
active={index === activeScheduleIndex}
|
||||||
|
name={schedule.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ ...props.style }} className='items-center'>
|
||||||
|
<div className='m0 m-b-2 w-full flex justify-between'>
|
||||||
|
<Text variant='h3'>MY SCHEDULES</Text>
|
||||||
|
<div className='cursor-pointer items-center justify-center btn-transition -ml-1.5 hover:text-zinc-400'>
|
||||||
|
<Text variant='h3'>
|
||||||
|
<AddSchedule />
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<List gap={10} draggableElements={scheduleComponents} itemHeight={30} listHeight={0} listWidth={240} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import clsx from 'clsx';
|
||||||
|
import React from 'react';
|
||||||
|
import DropdownDrag from '~icons/material-symbols/drag-indicator';
|
||||||
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
|
|
||||||
|
export type Props = {
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
active?: boolean;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a reusable dropdown component that can be used to toggle the visiblity of information
|
||||||
|
*/
|
||||||
|
export default function ScheduleListItem(props: Props) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ ...props.style }} className='items-center'>
|
||||||
|
<li
|
||||||
|
className='text-ut-burntorange w-100% flex cursor-pointer items-center self-stretch justify-left'
|
||||||
|
>
|
||||||
|
<div className='group flex justify-center'>
|
||||||
|
<DropdownDrag className='h-6 w-6 cursor-move text-zinc-300 btn-transition -ml-1.5 hover:text-zinc-400' />
|
||||||
|
<div className='inline-flex items-center justify-center gap-1.5'>
|
||||||
|
<div className='h-5.5 w-5.5 flex items-center justify-center border-2px border-current rounded-full btn-transition group-active:scale-95'>
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'bg-current h-3 w-3 rounded-full transition tansform scale-100 ease-out-expo duration-250',
|
||||||
|
{
|
||||||
|
'scale-0! opacity-0 ease-in-out! duration-200!': !props.active
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Text variant='p'>{props.name}</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user