some work on course popup

update the stories and create the header component
This commit is contained in:
Abhinav Chadaga
2024-02-17 10:54:49 -06:00
parent 31bcef3099
commit 43d2675be5
5 changed files with 196 additions and 91 deletions

View File

@@ -1,99 +1,99 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Course, Status } from 'src/shared/types/Course'; import { Course, Status } from 'src/shared/types/Course';
import { CourseMeeting } from 'src/shared/types/CourseMeeting'; import { CourseMeeting } from 'src/shared/types/CourseMeeting';
import { UserSchedule } from 'src/shared/types/UserSchedule'; import { UserSchedule } from 'src/shared/types/UserSchedule';
import CoursePopup from 'src/views/components/injected/CoursePopup/CoursePopup'; import CoursePopup from 'src/views/components/injected/CoursePopup/CoursePopup';
import type { Meta, StoryObj } from '@storybook/react';
const exampleCourse: Course = new Course({ const exampleCourse: Course = new Course({
courseName: 'ELEMS OF COMPTRS/PROGRAMMNG-WB', courseName: 'ELEMS OF COMPTRS/PROGRAMMNG-WB',
creditHours: 3, creditHours: 3,
department: 'C S', department: 'C S',
description: [ description: [
'Problem solving and fundamental algorithms for various applications in science, business, and on the World Wide Web, and introductory programming in a modern object-oriented programming language.', 'Problem solving and fundamental algorithms for various applications in science, business, and on the World Wide Web, and introductory programming in a modern object-oriented programming language.',
'Only one of the following may be counted: Computer Science 303E, 312, 312H. Credit for Computer Science 303E may not be earned after a student has received credit for Computer Science 314, or 314H. May not be counted toward a degree in computer science.', 'Only one of the following may be counted: Computer Science 303E, 312, 312H. Credit for Computer Science 303E may not be earned after a student has received credit for Computer Science 314, or 314H. May not be counted toward a degree in computer science.',
'May be counted toward the Quantitative Reasoning flag requirement.', 'May be counted toward the Quantitative Reasoning flag requirement.',
'Designed to accommodate 100 or more students.', 'Designed to accommodate 100 or more students.',
'Taught as a Web-based course.', 'Taught as a Web-based course.',
],
flags: ['Quantitative Reasoning'],
fullName: 'C S 303E ELEMS OF COMPTRS/PROGRAMMNG-WB',
instructionMode: 'Online',
instructors: [],
isReserved: false,
number: '303E',
schedule: {
meetings: [
new CourseMeeting({
days: ['Tuesday', 'Thursday'],
endTime: 660,
startTime: 570,
}),
], ],
}, flags: ['Quantitative Reasoning'],
semester: { fullName: 'C S 303E ELEMS OF COMPTRS/PROGRAMMNG-WB',
code: '12345', instructionMode: 'Online',
season: 'Spring', instructors: [],
year: 2024, isReserved: false,
}, number: '303E',
status: Status.CANCELLED, schedule: {
uniqueId: 12345, meetings: [
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/12345/', new CourseMeeting({
days: ['Tuesday', 'Thursday'],
endTime: 660,
startTime: 570,
}),
],
},
semester: {
code: '12345',
season: 'Spring',
year: 2024,
},
status: Status.CANCELLED,
uniqueId: 12345,
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/12345/',
}); });
const exampleSchedule: UserSchedule = new UserSchedule({ const exampleSchedule: UserSchedule = new UserSchedule({
courses: [exampleCourse], courses: [exampleCourse],
name: 'Example Schedule', name: 'Example Schedule',
}); });
const meta = { const meta = {
title: 'Components/Injected/CoursePopup', title: 'Components/Injected/CoursePopup',
component: CoursePopup, component: CoursePopup,
// tags: ['autodocs'], // tags: ['autodocs'],
args: { args: {
course: exampleCourse, course: exampleCourse,
activeSchedule: exampleSchedule, activeSchedule: exampleSchedule,
},
argTypes: {
course: {
control: {
type: 'other',
},
}, },
activeSchedule: { argTypes: {
control: { course: {
type: 'other', control: {
}, type: 'other',
},
},
activeSchedule: {
control: {
type: 'other',
},
},
}, },
}, parameters: {
parameters: { design: {
design: { type: 'figma',
type: 'figma', url: 'https://www.figma.com/file/8tsCay2FRqctrdcZ3r9Ahw/UTRP?type=design&node-id=602-1879&mode=design&t=BoS5xBrpSsjgQXqv-11',
url: 'https://www.figma.com/file/8tsCay2FRqctrdcZ3r9Ahw/UTRP?type=design&node-id=602-1879&mode=design&t=BoS5xBrpSsjgQXqv-11', },
}, },
},
} satisfies Meta<typeof CoursePopup>; } satisfies Meta<typeof CoursePopup>;
export default meta; export default meta;
type Story = StoryObj<typeof meta>; type Story = StoryObj<typeof meta>;
export const Open: Story = { export const Open: Story = {
args: { args: {
course: new Course({ ...exampleCourse, status: Status.OPEN }), course: new Course({ ...exampleCourse, status: Status.OPEN }),
activeSchedule: new UserSchedule({ activeSchedule: new UserSchedule({
courses: [], courses: [],
name: 'Example Schedule', name: 'Example Schedule',
}), }),
}, },
}; };
export const Closed: Story = { export const Closed: Story = {
args: { args: {
course: new Course({ ...exampleCourse, status: Status.CLOSED }), course: new Course({ ...exampleCourse, status: Status.CLOSED }),
}, },
}; };
export const Cancelled: Story = { export const Cancelled: Story = {
args: { args: {
course: new Course({ ...exampleCourse, status: Status.CANCELLED }), course: new Course({ ...exampleCourse, status: Status.CANCELLED }),
}, },
}; };

View File

@@ -1,16 +1,67 @@
import { Meta } from '@storybook/react'; import type { Meta, StoryObj } from '@storybook/react';
import { Course } from 'src/shared/types/Course'; import { Course, Status } from 'src/shared/types/Course';
import { CourseMeeting, DAY_MAP } from 'src/shared/types/CourseMeeting';
import { CourseSchedule } from 'src/shared/types/CourseSchedule';
import Instructor from 'src/shared/types/Instructor';
const testCourse: Course = { import CoursePopup2 from 'src/views/components/injected/CoursePopup2/CoursePopup2';
} const exampleCourse: Course = new Course({
uniqueId: 47280,
number: '331C',
fullName: "BVO 331C Bevo's Seminar Longhorn Care",
courseName: "Bevo's Seminar Longhorn Care",
department: 'BVO',
creditHours: 3,
status: Status.OPEN,
instructors: [new Instructor({ fullName: "Hook'em", firstName: '', lastName: "Hook'em" })],
isReserved: true,
description: [
'Restricted to Students in the School of Longhorn Enthusiasts',
'Immerse yourself in the daily routine of a longhorn—sunrise pasture walks and the best shady spots for a midday siesta. Understand the behavioral science behind our mascots stoic demeanor during games.',
'BVO 311C and 312H may not both be counted.',
'Prerequisite: Grazing 311 or 311H.',
'May be counted toward the Independent Inquiry flag requirement. May be counted toward the Writing flag requirement.',
'Offered on the letter-grade basis only.',
],
schedule: new CourseSchedule({
meetings: [
new CourseMeeting({
days: [DAY_MAP.T, DAY_MAP.TH],
startTime: 480,
endTime: 570,
location: { building: 'UTC', room: '123' },
}),
new CourseMeeting({
days: [DAY_MAP.TH],
startTime: 570,
endTime: 630,
location: { building: 'JES', room: '123' },
}),
],
}),
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/12345/',
flags: ['Writing', 'Independent Inquiry'],
instructionMode: 'In Person',
semester: {
year: 2024,
season: 'Spring',
},
});
const meta: Meta<typeof CoursePopup2> = { const meta: Meta<typeof CoursePopup2> = {
title: 'Components/Injected/CoursePopup2',
component: CoursePopup2, component: CoursePopup2,
argTypes: {
onClose: { action: 'onClose' },
},
}; };
export default meta; export default meta;
type Story = StoryObj<typeof meta>; type Story = StoryObj<typeof CoursePopup2>;
export const Open: Story = {
export const Default: Story = {
args: {
course: exampleCourse,
},
}; };

View File

@@ -1,21 +1,75 @@
import React from 'react'; import React from 'react';
import { Course } from 'src/shared/types/Course'; import { Course } from 'src/shared/types/Course';
import Text from '../../common/Text/Text';
import { Button } from '../../common/Button/Button'; import { Button } from '../../common/Button/Button';
import Icon from '../../common/Icon/Icon';
import Text from '../../common/Text/Text';
interface CourseHeadingAndActionsProps { interface CourseHeadingAndActionsProps {
course: Course; course: Course;
onClose: () => void;
} }
const CourseHeadingAndActions = ({ course }: CourseHeadingAndActionsProps) => { const CourseHeadingAndActions = ({ course, onClose }: CourseHeadingAndActionsProps) => {
const { courseName, department, number, uniqueId } = course; const { courseName, department, number, uniqueId, instructors, flags, schedule } = course;
const instructorString = instructors
.map(instructor => {
const firstInitial = instructor.firstName.length > 0 ? `${instructor.firstName.charAt(0)}. ` : '';
return `${firstInitial}${instructor.lastName}`;
})
.join(', ');
return ( return (
<div className='w-full pb-3 pt-6'> <div className='w-full pb-3 pt-6'>
<div className='flex gap-1'> <div className='flex flex-col gap-1'>
<Text variant='h1'> <div className='flex justify-center gap-1'>
{courseName} ({department} {number}) <Text variant='h1' className='flex items-center'>
</Text> {courseName} ({department} {number})
<Button>{uniqueId}</Button> </Text>
{/* TODO: change this button, include the left icon */}
<Button>{uniqueId}</Button>
<Button onClick={onClose}>
<Icon name='close' />
</Button>
</div>
<div className='flex gap-2.5 flex-content-center'>
<Text variant='h4'>
with <span className='text-ut-burntorange underline'>{instructorString}</span>
</Text>
<div className='flex gap-1 flex-content-center'>
{flags.map(flag => (
<div className='p flex justify-center flex-content-center rounded-lg bg-ut-yellow px-1 py-px'>
{/* get the first letter of each word in flag */}
<Text variant='h4' className='text-ut-black'>
{flag
.split(' ')
.map(word => word.charAt(0))
.join('')}
</Text>
</div>
))}
</div>
</div>
<div className='flex flex-col'>
{schedule.meetings.map(meeting => (
<Text variant='h4'>
{meeting.getDaysString({ format: 'long', separator: 'long' })}{' '}
{meeting.getTimeString({ separator: ' to ', capitalize: false })}
{meeting.location && (
<>
{` in `}
<Text variant='h4' className='text-ut-burntorange underline'>
{meeting.location.building}
</Text>
</>
)}
</Text>
))}
</div>
</div>
<div className='my-3 flex justify-start gap-1'>
<Button className='m0'>
<Icon name='calendar_today' />
</Button>
<Button>RateMyProf</Button>
</div> </div>
</div> </div>
); );

View File

@@ -1,20 +1,20 @@
import Popup from '@views/components/common/Popup/Popup';
import React from 'react'; import React from 'react';
import { Course } from 'src/shared/types/Course'; import { Course } from 'src/shared/types/Course';
import { UserSchedule } from 'src/shared/types/UserSchedule'; import { UserSchedule } from 'src/shared/types/UserSchedule';
import Popup from '../../common/Popup/Popup';
import CourseHeadingAndActions from './CourseHeadingAndActions'; import CourseHeadingAndActions from './CourseHeadingAndActions';
interface CoursePopup2Props { interface CoursePopup2Props {
course: Course; course: Course;
activeSchedule?: UserSchedule; activeSchedule?: UserSchedule;
onClose: () => void;
} }
const CoursePopup2 = ({ course, activeSchedule }: CoursePopup2Props) => ( const CoursePopup2 = ({ course, activeSchedule, onClose }: CoursePopup2Props) => (
<Popup className='px-6'> <Popup overlay className='px-6' onClose={onClose}>
<div className='flex flex-col'> <div className='flex flex-col'>
<CourseHeadingAndActions course={course} /> <CourseHeadingAndActions course={course} onClose={onClose} />
</div> </div>
</Popup> </Popup>
); );
export default CoursePopup2; export default CoursePopup2;

View File

@@ -24,7 +24,7 @@ export default defineConfig({
}, },
colors: { colors: {
ut: { ut: {
'burnt-orange': '#BF5700', burntorange: '#BF5700',
black: '#333F48', black: '#333F48',
orange: '#f8971f', orange: '#f8971f',
yellow: '#ffd600', yellow: '#ffd600',