Compare commits
6 Commits
vinson/rep
...
injected-i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c4dd36f27 | ||
|
|
5daccc8349 | ||
|
|
e4ce051086 | ||
|
|
51b6799d73 | ||
|
|
141f5cc70e | ||
|
|
6883a0bc8d |
@@ -34,4 +34,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"prettier": "prettier src --check",
|
"prettier": "prettier src --check",
|
||||||
"prettier:fix": "prettier src --write",
|
"prettier:fix": "prettier src --write",
|
||||||
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives",
|
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --fix",
|
"lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix",
|
||||||
"test": "vitest",
|
"test": "vitest",
|
||||||
"test:ui": "vitest --ui",
|
"test:ui": "vitest --ui",
|
||||||
"coverage": "vitest run --coverage",
|
"coverage": "vitest run --coverage",
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-devtools-core": "^5.0.0",
|
"react-devtools-core": "^5.0.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-window": "^1.8.10",
|
||||||
"sass": "^1.71.1",
|
"sass": "^1.71.1",
|
||||||
"sql.js": "1.10.2",
|
"sql.js": "1.10.2",
|
||||||
"styled-components": "^6.1.8",
|
"styled-components": "^6.1.8",
|
||||||
|
|||||||
2687
pnpm-lock.yaml
generated
2687
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
|||||||
import { defineManifest } from '@crxjs/vite-plugin';
|
import { defineManifest } from '@crxjs/vite-plugin';
|
||||||
|
|
||||||
import packageJson from '../package.json';
|
import packageJson from '../package.json';
|
||||||
|
|
||||||
// Convert from Semver (example: 0.1.0-beta6)
|
// Convert from Semver (example: 0.1.0-beta6)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type { BACKGROUND_MESSAGES } from '@shared/messages';
|
import { BACKGROUND_MESSAGES } from '@shared/messages';
|
||||||
import { MessageListener } from 'chrome-extension-toolkit';
|
import { MessageListener } from 'chrome-extension-toolkit';
|
||||||
|
|
||||||
import onInstall from './events/onInstall';
|
import onInstall from './events/onInstall';
|
||||||
import onServiceWorkerAlive from './events/onServiceWorkerAlive';
|
import onServiceWorkerAlive from './events/onServiceWorkerAlive';
|
||||||
import onUpdate from './events/onUpdate';
|
import onUpdate from './events/onUpdate';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type BrowserActionMessages from '@shared/messages/BrowserActionMessages';
|
import BrowserActionMessages from '@shared/messages/BrowserActionMessages';
|
||||||
import type { MessageHandler } from 'chrome-extension-toolkit';
|
import { MessageHandler } from 'chrome-extension-toolkit';
|
||||||
|
|
||||||
const browserActionHandler: MessageHandler<BrowserActionMessages> = {
|
const browserActionHandler: MessageHandler<BrowserActionMessages> = {
|
||||||
disableBrowserAction({ sender, sendResponse }) {
|
disableBrowserAction({ sender, sendResponse }) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type HotReloadingMessages from '@shared/messages/HotReloadingMessages';
|
import HotReloadingMessages from '@shared/messages/HotReloadingMessages';
|
||||||
import { DevStore } from '@shared/storage/DevStore';
|
import { DevStore } from '@shared/storage/DevStore';
|
||||||
import type { MessageHandler } from 'chrome-extension-toolkit';
|
import { MessageHandler } from 'chrome-extension-toolkit';
|
||||||
|
|
||||||
const hotReloadingHandler: MessageHandler<HotReloadingMessages> = {
|
const hotReloadingHandler: MessageHandler<HotReloadingMessages> = {
|
||||||
async reloadExtension({ sendResponse }) {
|
async reloadExtension({ sendResponse }) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type TabManagementMessages from '@shared/messages/TabManagementMessages';
|
import TabManagementMessages from '@shared/messages/TabManagementMessages';
|
||||||
import type { MessageHandler } from 'chrome-extension-toolkit';
|
import { MessageHandler } from 'chrome-extension-toolkit';
|
||||||
|
|
||||||
import openNewTab from '../util/openNewTab';
|
import openNewTab from '../util/openNewTab';
|
||||||
|
|
||||||
const tabManagementHandler: MessageHandler<TabManagementMessages> = {
|
const tabManagementHandler: MessageHandler<TabManagementMessages> = {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { UserScheduleMessages } from '@shared/messages/UserScheduleMessages';
|
import { UserScheduleMessages } from '@shared/messages/UserScheduleMessages';
|
||||||
import { Course } from '@shared/types/Course';
|
import { Course } from '@shared/types/Course';
|
||||||
import type { MessageHandler } from 'chrome-extension-toolkit';
|
import { MessageHandler } from 'chrome-extension-toolkit';
|
||||||
|
|
||||||
import addCourse from '../lib/addCourse';
|
import addCourse from '../lib/addCourse';
|
||||||
import clearCourses from '../lib/clearCourses';
|
import clearCourses from '../lib/clearCourses';
|
||||||
import createSchedule from '../lib/createSchedule';
|
import createSchedule from '../lib/createSchedule';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
||||||
import type { Course } from '@shared/types/Course';
|
import { Course } from '@shared/types/Course';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the courses for a given schedule.
|
|
||||||
* @param scheduleName - The name of the schedule.
|
|
||||||
* @throws Error if the schedule does not exist.
|
|
||||||
*/
|
|
||||||
export default async function clearCourses(scheduleName: string): Promise<void> {
|
export default async function clearCourses(scheduleName: string): Promise<void> {
|
||||||
const schedules = await UserScheduleStore.get('schedules');
|
const schedules = await UserScheduleStore.get('schedules');
|
||||||
const schedule = schedules.find(schedule => schedule.name === scheduleName);
|
const schedule = schedules.find(schedule => schedule.name === scheduleName);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default async function createSchedule(scheduleName: string): Promise<stri
|
|||||||
schedules.push({
|
schedules.push({
|
||||||
name: scheduleName,
|
name: scheduleName,
|
||||||
courses: [],
|
courses: [],
|
||||||
hours: 0,
|
hours: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
await UserScheduleStore.set('schedules', schedules);
|
await UserScheduleStore.set('schedules', schedules);
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a schedule with the specified name.
|
|
||||||
*
|
|
||||||
* @param scheduleName - The name of the schedule to delete.
|
|
||||||
* @returns A promise that resolves to a string if there is an error, or undefined if the schedule is deleted successfully.
|
|
||||||
*/
|
|
||||||
export default async function deleteSchedule(scheduleName: string): Promise<string | undefined> {
|
export default async function deleteSchedule(scheduleName: string): Promise<string | undefined> {
|
||||||
const [schedules, activeIndex] = await Promise.all([
|
const [schedules, activeIndex] = await Promise.all([
|
||||||
UserScheduleStore.get('schedules'),
|
UserScheduleStore.get('schedules'),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
||||||
import type { Course } from '@shared/types/Course';
|
import { Course } from '@shared/types/Course';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
||||||
|
|
||||||
/**
|
|
||||||
* Renames a schedule with the specified name to a new name.
|
|
||||||
* @param scheduleName - The name of the schedule to be renamed.
|
|
||||||
* @param newName - The new name for the schedule.
|
|
||||||
* @returns A promise that resolves to a string if there is an error, or undefined if the schedule is renamed successfully.
|
|
||||||
*/
|
|
||||||
export default async function renameSchedule(scheduleName: string, newName: string): Promise<string | undefined> {
|
export default async function renameSchedule(scheduleName: string, newName: string): Promise<string | undefined> {
|
||||||
const schedules = await UserScheduleStore.get('schedules');
|
const schedules = await UserScheduleStore.get('schedules');
|
||||||
const scheduleIndex = schedules.findIndex(schedule => schedule.name === scheduleName);
|
const scheduleIndex = schedules.findIndex(schedule => schedule.name === scheduleName);
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
||||||
|
|
||||||
/**
|
|
||||||
* Switches the active schedule to the specified schedule name.
|
|
||||||
* Throws an error if the schedule does not exist.
|
|
||||||
* @param scheduleName - The name of the schedule to switch to.
|
|
||||||
* @returns A Promise that resolves when the active schedule is successfully switched.
|
|
||||||
*/
|
|
||||||
export default async function switchSchedule(scheduleName: string): Promise<void> {
|
export default async function switchSchedule(scheduleName: string): Promise<void> {
|
||||||
const schedules = await UserScheduleStore.get('schedules');
|
const schedules = await UserScheduleStore.get('schedules');
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
||||||
import { Calendar } from 'src/views/components/calendar/Calendar/Calendar';
|
import { Calendar } from 'src/views/components/calendar/Calendar/Calendar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<title>Calendar</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<head>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<meta charset="utf-8" />
|
||||||
<div id="root"></div>
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<title>Calendar</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
|
||||||
|
<script src="./index.tsx" type="module"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
<script src="./index.tsx" type="module"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
import CalendarMain from './CalendarMain';
|
import CalendarMain from './CalendarMain';
|
||||||
|
|
||||||
createRoot(document.getElementById('root')).render(<CalendarMain />);
|
createRoot(document.getElementById('root')).render(<CalendarMain />);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import CourseCatalogMain from '@views/components/CourseCatalogMain';
|
|
||||||
import getSiteSupport, { SiteSupport } from '@views/lib/getSiteSupport';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import CourseCatalogMain from '@views/components/CourseCatalogMain';
|
||||||
|
import getSiteSupport, { SiteSupport } from '@views/lib/getSiteSupport';
|
||||||
|
|
||||||
const support = getSiteSupport(window.location.href);
|
const support = getSiteSupport(window.location.href);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<title>Debug</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<head>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<meta charset="utf-8" />
|
||||||
<div id="root"></div>
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<title>Debug</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
|
||||||
|
<script src="./index.tsx" type="module"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
<script src="./index.tsx" type="module"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<title>Popup</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<head>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<meta charset="utf-8" />
|
||||||
<div id="root"></div>
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<title>Popup</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
|
||||||
|
<script src="./index.tsx" type="module"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
<script src="./index.tsx" type="module"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
createRoot(document.getElementById('root')).render(<App />);
|
createRoot(document.getElementById('root')).render(<App />);
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<title>Popup</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<head>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<meta charset="utf-8" />
|
||||||
<div id="root"></div>
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<title>Popup</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
|
||||||
|
<script src="./index.tsx" type="module"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
<script src="./index.tsx" type="module"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
import PopupMain from '../../views/components/PopupMain';
|
import PopupMain from '../../views/components/PopupMain';
|
||||||
|
|
||||||
createRoot(document.getElementById('root')).render(<PopupMain />);
|
createRoot(document.getElementById('root')).render(<PopupMain />);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable jsdoc/require-jsdoc */
|
|
||||||
export default interface BrowserActionMessages {
|
export default interface BrowserActionMessages {
|
||||||
/** make it so that clicking the browser action will open the popup.html */
|
/** make it so that clicking the browser action will open the popup.html */
|
||||||
enableBrowserAction: () => void;
|
enableBrowserAction: () => void;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable jsdoc/require-jsdoc */
|
|
||||||
export default interface HotReloadingMessages {
|
export default interface HotReloadingMessages {
|
||||||
reloadExtension: () => void;
|
reloadExtension: () => void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
import type { Course } from '@shared/types/Course';
|
import { Course } from '../types/Course';
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a collection of user schedule messages.
|
|
||||||
*/
|
|
||||||
export interface UserScheduleMessages {
|
export interface UserScheduleMessages {
|
||||||
/**
|
/**
|
||||||
* Add a course to a schedule
|
* Add a course to a schedule
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { createMessenger } from 'chrome-extension-toolkit';
|
import { createMessenger } from 'chrome-extension-toolkit';
|
||||||
|
import BrowserActionMessages from './BrowserActionMessages';
|
||||||
import type BrowserActionMessages from './BrowserActionMessages';
|
import TabManagementMessages from './TabManagementMessages';
|
||||||
import type TabManagementMessages from './TabManagementMessages';
|
import TAB_MESSAGES from './TabMessages';
|
||||||
import type TAB_MESSAGES from './TabMessages';
|
import { UserScheduleMessages } from './UserScheduleMessages';
|
||||||
import type { UserScheduleMessages } from './UserScheduleMessages';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a type with all the message definitions that can be sent TO the background script
|
* This is a type with all the message definitions that can be sent TO the background script
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ export const ExtensionStore = createLocalStore<IExtensionStore>({
|
|||||||
lastUpdate: Date.now(),
|
lastUpdate: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
debugStore({ ExtensionStore });
|
debugStore({ ExtensionStore });
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Serialized } from 'chrome-extension-toolkit';
|
/* eslint-disable max-classes-per-file */
|
||||||
|
import { Serialized } from 'chrome-extension-toolkit';
|
||||||
import type { CourseMeeting } from './CourseMeeting';
|
import { CourseMeeting } from './CourseMeeting';
|
||||||
import { CourseSchedule } from './CourseSchedule';
|
import { CourseSchedule } from './CourseSchedule';
|
||||||
import Instructor from './Instructor';
|
import Instructor from './Instructor';
|
||||||
|
|
||||||
@@ -12,17 +12,12 @@ export type InstructionMode = 'Online' | 'In Person' | 'Hybrid';
|
|||||||
/**
|
/**
|
||||||
* The status of a course (e.g. open, closed, waitlisted, cancelled)
|
* The status of a course (e.g. open, closed, waitlisted, cancelled)
|
||||||
*/
|
*/
|
||||||
export const Status = {
|
export enum Status {
|
||||||
OPEN: 'OPEN',
|
OPEN = 'OPEN',
|
||||||
CLOSED: 'CLOSED',
|
CLOSED = 'CLOSED',
|
||||||
WAITLISTED: 'WAITLISTED',
|
WAITLISTED = 'WAITLISTED',
|
||||||
CANCELLED: 'CANCELLED',
|
CANCELLED = 'CANCELLED',
|
||||||
} as const;
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the type of status for a course.
|
|
||||||
*/
|
|
||||||
export type StatusType = (typeof Status)[keyof typeof Status];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a semester, with the year and the season for when a course is offered
|
* Represents a semester, with the year and the season for when a course is offered
|
||||||
@@ -54,7 +49,7 @@ export class Course {
|
|||||||
/** The number of credits that a course is worth */
|
/** The number of credits that a course is worth */
|
||||||
creditHours: number;
|
creditHours: number;
|
||||||
/** Is the course open, closed, waitlisted, or cancelled? */
|
/** Is the course open, closed, waitlisted, or cancelled? */
|
||||||
status: StatusType;
|
status: Status;
|
||||||
/** all the people that are teaching this course, and some metadata about their names */
|
/** all the people that are teaching this course, and some metadata about their names */
|
||||||
instructors: Instructor[];
|
instructors: Instructor[];
|
||||||
/** Some courses at UT are reserved for certain groups of people or people within a certain major, which makes it difficult for people outside of that group to register for the course. */
|
/** Some courses at UT are reserved for certain groups of people or people within a certain major, which makes it difficult for people outside of that group to register for the course. */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Serialized } from 'chrome-extension-toolkit';
|
import { Serialized } from 'chrome-extension-toolkit';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a map of the days of the week that a class is taught, and the corresponding abbreviation
|
* a map of the days of the week that a class is taught, and the corresponding abbreviation
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import type { Serialized } from 'chrome-extension-toolkit';
|
import { Serialized } from 'chrome-extension-toolkit';
|
||||||
|
import { CourseMeeting, Day, DAY_MAP } from './CourseMeeting';
|
||||||
import type { Day } from './CourseMeeting';
|
|
||||||
import { CourseMeeting, DAY_MAP } from './CourseMeeting';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This represents the schedule for a course, which includes all the meeting times for the course, as well as helper functions for parsing, serializing, and deserializing the schedule
|
* This represents the schedule for a course, which includes all the meeting times for the course, as well as helper functions for parsing, serializing, and deserializing the schedule
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
/* eslint-disable max-classes-per-file */
|
||||||
import { PointOptionsObject } from 'highcharts';
|
import { PointOptionsObject } from 'highcharts';
|
||||||
|
|
||||||
import { Semester } from './Course';
|
import { Semester } from './Course';
|
||||||
/**
|
/**
|
||||||
* Each of the possible letter grades that can be given in a course
|
* Each of the possible letter grades that can be given in a course
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { Serialized } from 'chrome-extension-toolkit';
|
import { Serialized } from 'chrome-extension-toolkit';
|
||||||
|
|
||||||
import { capitalize } from '../util/string';
|
import { capitalize } from '../util/string';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { Serialized } from 'chrome-extension-toolkit';
|
import { Serialized } from 'chrome-extension-toolkit';
|
||||||
|
|
||||||
import { Course } from './Course';
|
import { Course } from './Course';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,4 +21,4 @@ export class UserSchedule {
|
|||||||
containsCourse(course: Course): boolean {
|
containsCourse(course: Course): boolean {
|
||||||
return this.courses.some(c => c.uniqueId === course.uniqueId);
|
return this.courses.some(c => c.uniqueId === course.uniqueId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,11 @@
|
|||||||
import { theme } from 'unocss/preset-mini';
|
import { theme } from 'unocss/preset-mini';
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the colors for a course.
|
|
||||||
*/
|
|
||||||
export interface CourseColors {
|
export interface CourseColors {
|
||||||
primaryColor: string;
|
primaryColor: string;
|
||||||
secondaryColor: string;
|
secondaryColor: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// calculates luminance of a hex string
|
||||||
* Calculates the luminance of a given hexadecimal color.
|
|
||||||
*
|
|
||||||
* @param hex - The hexadecimal color value.
|
|
||||||
* @returns The luminance value between 0 and 1.
|
|
||||||
*/
|
|
||||||
export function getLuminance(hex: string): number {
|
export function getLuminance(hex: string): number {
|
||||||
let r = parseInt(hex.substring(1, 3), 16);
|
let r = parseInt(hex.substring(1, 3), 16);
|
||||||
let g = parseInt(hex.substring(3, 5), 16);
|
let g = parseInt(hex.substring(3, 5), 16);
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
import type { StatusType } from '@shared/types/Course';
|
import React, { SVGProps } from 'react';
|
||||||
import { Status } from '@shared/types/Course';
|
|
||||||
import type { SVGProps } from 'react';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import ClosedIcon from '~icons/material-symbols/lock';
|
import ClosedIcon from '~icons/material-symbols/lock';
|
||||||
import WaitlistIcon from '~icons/material-symbols/timelapse';
|
import WaitlistIcon from '~icons/material-symbols/timelapse';
|
||||||
import CancelledIcon from '~icons/material-symbols/warning';
|
import CancelledIcon from '~icons/material-symbols/warning';
|
||||||
|
import { Status } from '../types/Course';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Icon component based on status
|
* Get Icon component based on status
|
||||||
* @param props.status status
|
* @param props.status status
|
||||||
* @returns React.ReactElement - the icon component
|
* @returns React.ReactElement - the icon component
|
||||||
*/
|
*/
|
||||||
export function StatusIcon(props: SVGProps<SVGSVGElement> & { status: StatusType }): React.ReactElement {
|
export function StatusIcon(props: SVGProps<SVGSVGElement> & { status: Status }): React.ReactElement {
|
||||||
const { status, ...rest } = props;
|
const { status, ...rest } = props;
|
||||||
|
|
||||||
switch (props.status) {
|
switch (props.status) {
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ export function capitalize(input: string): string {
|
|||||||
}
|
}
|
||||||
capitalized += ' ';
|
capitalized += ' ';
|
||||||
}
|
}
|
||||||
capitalized = capitalized.trim(); // Remove extra space
|
|
||||||
|
|
||||||
return capitalized;
|
return capitalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +31,7 @@ export function capitalizeFirstLetter(input: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cuts the input string to the specified length and adds an ellipsis if the string is longer than the specified length.
|
* Cuts the
|
||||||
* @param input The string to ellipsify.
|
* @param input The string to ellipsify.
|
||||||
* @param length The length of the string to return.
|
* @param length The length of the string to return.
|
||||||
* @returns The ellipsified string.
|
* @returns The ellipsified string.
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { capitalize, capitalizeFirstLetter, ellipsify } from '../string';
|
import { capitalize } from '../string';
|
||||||
|
|
||||||
// TODO: Fix `string.ts` and `string.test.ts` to make the tests pass
|
// TODO: Fix `string.ts` and `string.test.ts` to make the tests pass
|
||||||
// `capitalize` is adding an extra space at the end of the word.
|
// `capitalize` is adding an extra space at the end of the word.
|
||||||
describe('capitalize', () => {
|
describe('capitalize', () => {
|
||||||
it('should capitalize the first letter of each word', () => {
|
it('should capitalize the first letter of each word', () => {
|
||||||
// Debug
|
// Debug
|
||||||
// const word = 'hello world';
|
const word = 'hello world';
|
||||||
// const capitalized = capitalize(word);
|
const capitalized = capitalize(word);
|
||||||
// console.log(capitalize(word));
|
console.log(capitalize(word));
|
||||||
// console.log(capitalized.length);
|
console.log(capitalized.length);
|
||||||
// console.log(capitalized.split(''));
|
console.log(capitalized.split(''));
|
||||||
|
|
||||||
// Test case 1: Single word
|
// Test case 1: Single word
|
||||||
expect(capitalize('hello')).toBe('Hello');
|
expect(capitalize('hello')).toBe('Hello');
|
||||||
@@ -25,40 +25,15 @@ describe('capitalize', () => {
|
|||||||
// Test case 4: Words with hyphens and spaces
|
// Test case 4: Words with hyphens and spaces
|
||||||
expect(capitalize('hello-world test')).toBe('Hello-World Test');
|
expect(capitalize('hello-world test')).toBe('Hello-World Test');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('capitalizeFirstLetter', () => {
|
it('should not change the capitalization of the remaining letters', () => {
|
||||||
it('should return a string with the first letter capitalized', () => {
|
// Test case 1: All lowercase
|
||||||
// Test case 1: Single word
|
expect(capitalize('hello')).toBe('Hello');
|
||||||
expect(capitalizeFirstLetter('hello')).toBe('Hello');
|
|
||||||
|
|
||||||
// Test case 2: Word with all lowercase letters
|
// Test case 2: All uppercase
|
||||||
expect(capitalizeFirstLetter('world')).toBe('World');
|
expect(capitalize('WORLD')).toBe('WORLD');
|
||||||
|
|
||||||
// Test case 3: Word with all uppercase letters
|
// Test case 3: Mixed case
|
||||||
expect(capitalizeFirstLetter('EXAMPLE')).toBe('Example');
|
expect(capitalize('HeLLo WoRLd')).toBe('Hello World');
|
||||||
|
|
||||||
// Test case 4: Word with mixed case letters
|
|
||||||
expect(capitalizeFirstLetter('tEsT')).toBe('Test');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle empty string input', () => {
|
|
||||||
expect(capitalizeFirstLetter('')).toBe('');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('ellipsify', () => {
|
|
||||||
it('should add ellipsis if the input string exceeds the specified character limit', () => {
|
|
||||||
// Test case 1: Input string is shorter than the character limit
|
|
||||||
expect(ellipsify('Hello', 10)).toBe('Hello');
|
|
||||||
|
|
||||||
// Test case 2: Input string is equal to the character limit
|
|
||||||
expect(ellipsify('Hello World', 11)).toBe('Hello World');
|
|
||||||
|
|
||||||
// Test case 3: Input string is longer than the character limit
|
|
||||||
expect(ellipsify('Hello World', 5)).toBe('Hello...');
|
|
||||||
|
|
||||||
// Test case 4: Input string is empty
|
|
||||||
expect(ellipsify('', 5)).toBe('');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
|
||||||
|
|
||||||
import { getThemeColorHexByName, getThemeColorRgbByName, hexToRgb } from '../themeColors';
|
|
||||||
|
|
||||||
describe('hexToRgb', () => {
|
|
||||||
it('should convert hex color to RGB', () => {
|
|
||||||
expect(hexToRgb('#BF5700')).toEqual([191, 87, 0]);
|
|
||||||
expect(hexToRgb('#333F48')).toEqual([51, 63, 72]);
|
|
||||||
expect(hexToRgb('#f8971f')).toEqual([248, 151, 31]);
|
|
||||||
expect(hexToRgb('#ffd600')).toEqual([255, 214, 0]);
|
|
||||||
expect(hexToRgb('#a6cd57')).toEqual([166, 205, 87]);
|
|
||||||
expect(hexToRgb('#579d42')).toEqual([87, 157, 66]);
|
|
||||||
expect(hexToRgb('#00a9b7')).toEqual([0, 169, 183]);
|
|
||||||
expect(hexToRgb('#005f86')).toEqual([0, 95, 134]);
|
|
||||||
expect(hexToRgb('#9cadb7')).toEqual([156, 173, 183]);
|
|
||||||
expect(hexToRgb('#d6d2c4')).toEqual([214, 210, 196]);
|
|
||||||
expect(hexToRgb('#95a5a6')).toEqual([149, 165, 166]);
|
|
||||||
expect(hexToRgb('#B91C1C')).toEqual([185, 28, 28]);
|
|
||||||
expect(hexToRgb('#af2e2d')).toEqual([175, 46, 45]);
|
|
||||||
expect(hexToRgb('#1a2024')).toEqual([26, 32, 36]);
|
|
||||||
expect(hexToRgb('#22c55e')).toEqual([34, 197, 94]);
|
|
||||||
expect(hexToRgb('#a3e635')).toEqual([163, 230, 53]);
|
|
||||||
expect(hexToRgb('#84CC16')).toEqual([132, 204, 22]);
|
|
||||||
expect(hexToRgb('#FDE047')).toEqual([253, 224, 71]);
|
|
||||||
expect(hexToRgb('#FACC15')).toEqual([250, 204, 21]);
|
|
||||||
expect(hexToRgb('#F59E0B')).toEqual([245, 158, 11]);
|
|
||||||
expect(hexToRgb('#FB923C')).toEqual([251, 146, 60]);
|
|
||||||
expect(hexToRgb('#F97316')).toEqual([249, 115, 22]);
|
|
||||||
expect(hexToRgb('#EA580C')).toEqual([234, 88, 12]);
|
|
||||||
expect(hexToRgb('#DC2626')).toEqual([220, 38, 38]);
|
|
||||||
expect(hexToRgb('#B91C1C')).toEqual([185, 28, 28]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getThemeColorHexByName', () => {
|
|
||||||
it('should return the hex color value by name', () => {
|
|
||||||
expect(getThemeColorHexByName('ut-burntorange')).toEqual('#BF5700');
|
|
||||||
expect(getThemeColorHexByName('ut-offwhite')).toEqual('#D6D2C4');
|
|
||||||
expect(getThemeColorHexByName('ut-black')).toEqual('#333F48');
|
|
||||||
// Add more test cases for other theme color names
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getThemeColorRgbByName', () => {
|
|
||||||
it('should return the RGB color value by name', () => {
|
|
||||||
expect(getThemeColorRgbByName('ut-burntorange')).toEqual([191, 87, 0]);
|
|
||||||
expect(getThemeColorRgbByName('ut-offwhite')).toEqual([214, 210, 196]);
|
|
||||||
expect(getThemeColorRgbByName('ut-black')).toEqual([51, 63, 72]);
|
|
||||||
// Add more test cases for other theme color names
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -2,24 +2,24 @@ export const colors = {
|
|||||||
ut: {
|
ut: {
|
||||||
burntorange: '#BF5700',
|
burntorange: '#BF5700',
|
||||||
black: '#333F48',
|
black: '#333F48',
|
||||||
orange: '#F8971F',
|
orange: '#f8971f',
|
||||||
yellow: '#FFD600',
|
yellow: '#ffd600',
|
||||||
lightgreen: '#A6CD57',
|
lightgreen: '#a6cd57',
|
||||||
green: '#579D42',
|
green: '#579d42',
|
||||||
teal: '#00A9B7',
|
teal: '#00a9b7',
|
||||||
blue: '#005F86',
|
blue: '#005f86',
|
||||||
gray: '#9CADB7',
|
gray: '#9cadb7',
|
||||||
offwhite: '#D6D2C4',
|
offwhite: '#d6d2c4',
|
||||||
concrete: '#95A5A6',
|
concrete: '#95a5a6',
|
||||||
red: '#B91C1C', // Not sure if this should be here, but it's used for remove course, and add course is ut-green
|
red: '#B91C1C' // Not sure if this should be here, but it's used for remove course, and add course is ut-green
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
red: '#AF2E2D',
|
red: '#af2e2d',
|
||||||
black: '#1A2024',
|
black: '#1a2024',
|
||||||
},
|
},
|
||||||
gradeDistribution: {
|
gradeDistribution: {
|
||||||
a: '#22C55E',
|
a: '#22c55e',
|
||||||
aminus: '#A3E635',
|
aminus: '#a3e635',
|
||||||
bplus: '#84CC16',
|
bplus: '#84CC16',
|
||||||
b: '#FDE047',
|
b: '#FDE047',
|
||||||
bminus: '#FACC15',
|
bminus: '#FACC15',
|
||||||
@@ -31,7 +31,7 @@ export const colors = {
|
|||||||
dminus: '#B91C1C',
|
dminus: '#B91C1C',
|
||||||
f: '#B91C1C',
|
f: '#B91C1C',
|
||||||
},
|
},
|
||||||
} as const satisfies Record<string, Record<string, string>>;
|
} as const;
|
||||||
|
|
||||||
type NestedKeys<T> = {
|
type NestedKeys<T> = {
|
||||||
[K in keyof T]: T[K] extends Record<string, any> ? `${string & K}-${string & keyof T[K]}` : never;
|
[K in keyof T]: T[K] extends Record<string, any> ? `${string & K}-${string & keyof T[K]}` : never;
|
||||||
@@ -42,10 +42,6 @@ type NestedKeys<T> = {
|
|||||||
*/
|
*/
|
||||||
export type ThemeColor = NestedKeys<typeof colors>;
|
export type ThemeColor = NestedKeys<typeof colors>;
|
||||||
|
|
||||||
/**
|
|
||||||
* Flattened colors object.
|
|
||||||
* @type {Record<ThemeColor, string>}
|
|
||||||
*/
|
|
||||||
export const colorsFlattened = Object.entries(colors).reduce(
|
export const colorsFlattened = Object.entries(colors).reduce(
|
||||||
(acc, [prefix, group]) => {
|
(acc, [prefix, group]) => {
|
||||||
for (const [name, hex] of Object.entries(group)) {
|
for (const [name, hex] of Object.entries(group)) {
|
||||||
@@ -56,18 +52,9 @@ export const colorsFlattened = Object.entries(colors).reduce(
|
|||||||
{} as Record<ThemeColor, string>
|
{} as Record<ThemeColor, string>
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
const hexToRgb = (hex: string) =>
|
||||||
* Converts a hexadecimal color code to an RGB color array.
|
|
||||||
* @param hex The hexadecimal color code to convert.
|
|
||||||
* @returns An array representing the RGB color values.
|
|
||||||
*/
|
|
||||||
export const hexToRgb = (hex: string) =>
|
|
||||||
hex.match(/[0-9a-f]{2}/gi).map(partialHex => parseInt(partialHex, 16)) as [number, number, number];
|
hex.match(/[0-9a-f]{2}/gi).map(partialHex => parseInt(partialHex, 16)) as [number, number, number];
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the flattened RGB values of the colors.
|
|
||||||
* @type {Record<ThemeColor, ReturnType<typeof hexToRgb>>}
|
|
||||||
*/
|
|
||||||
const colorsFlattenedRgb = Object.fromEntries(
|
const colorsFlattenedRgb = Object.fromEntries(
|
||||||
Object.entries(colorsFlattened).map(([name, hex]) => [name, hexToRgb(hex)])
|
Object.entries(colorsFlattened).map(([name, hex]) => [name, hexToRgb(hex)])
|
||||||
) as Record<ThemeColor, ReturnType<typeof hexToRgb>>;
|
) as Record<ThemeColor, ReturnType<typeof hexToRgb>>;
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ export const HOUR = 60 * MINUTE;
|
|||||||
export const DAY = 24 * HOUR;
|
export const DAY = 24 * HOUR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pauses the execution for the specified number of milliseconds.
|
*
|
||||||
* @param milliseconds - The number of milliseconds to sleep.
|
|
||||||
* @returns A promise that resolves after the specified number of milliseconds.
|
|
||||||
*/
|
*/
|
||||||
export const sleep = (milliseconds: number): Promise<void> => new Promise(resolve => setTimeout(resolve, milliseconds));
|
export const sleep = (milliseconds: number): Promise<void> => new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { colorsFlattened } from '@shared/util/themeColors';
|
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import { Button } from '@views/components/common/Button/Button';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { colorsFlattened } from 'src/shared/util/themeColors';
|
||||||
|
import { Button } from 'src/views/components/common/Button/Button';
|
||||||
import AddIcon from '~icons/material-symbols/add';
|
import AddIcon from '~icons/material-symbols/add';
|
||||||
import CalendarMonthIcon from '~icons/material-symbols/calendar-month';
|
import CalendarMonthIcon from '~icons/material-symbols/calendar-month';
|
||||||
import DescriptionIcon from '~icons/material-symbols/description';
|
import DescriptionIcon from '~icons/material-symbols/description';
|
||||||
@@ -136,7 +135,7 @@ export const CourseCatalogActionButtons: Story = {
|
|||||||
<Button {...props} variant='outline' color='ut-teal' icon={HappyFaceIcon}>
|
<Button {...props} variant='outline' color='ut-teal' icon={HappyFaceIcon}>
|
||||||
CES
|
CES
|
||||||
</Button>
|
</Button>
|
||||||
<Button {...props} variant='outline' color='ut-orange' icon={DescriptionIcon}>
|
<Button {...props} variant='outline' color='ut-yellow' icon={DescriptionIcon}>
|
||||||
Past Syllabi
|
Past Syllabi
|
||||||
</Button>
|
</Button>
|
||||||
<Button {...props} variant='filled' color='ut-green' icon={AddIcon}>
|
<Button {...props} variant='filled' color='ut-green' icon={AddIcon}>
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
|
import Card from 'src/views/components/common/Card/Card';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import Card from '@views/components/common/Card/Card';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/Card',
|
title: 'Components/Common/Card',
|
||||||
component: Card,
|
component: Card,
|
||||||
parameters: {
|
parameters: {
|
||||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
|
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
|
||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
},
|
},
|
||||||
args: {
|
args: {
|
||||||
children: <div>Hello</div>,
|
children: <div>Hello</div>,
|
||||||
},
|
},
|
||||||
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
||||||
tags: ['autodocs'],
|
tags: ['autodocs'],
|
||||||
} satisfies Meta<typeof Card>;
|
} satisfies Meta<typeof Card>;
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { Chip } from '@views/components/common/Chip/Chip';
|
import { Chip } from 'src/views/components/common/Chip/Chip';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/Chip',
|
title: 'Components/Common/Chip',
|
||||||
@@ -20,4 +20,4 @@ export const Default: Story = {
|
|||||||
args: {
|
args: {
|
||||||
label: 'QR',
|
label: 'QR',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Course, Status } from '@shared/types/Course';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { CourseMeeting } from '@shared/types/CourseMeeting';
|
|
||||||
import Instructor from '@shared/types/Instructor';
|
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
|
||||||
import ConflictsWithWarning from '@views/components/common/ConflictsWithWarning/ConflictsWithWarning';
|
import ConflictsWithWarning from '@views/components/common/ConflictsWithWarning/ConflictsWithWarning';
|
||||||
|
import { Course, Status } from 'src/shared/types/Course';
|
||||||
|
import { CourseMeeting } from 'src/shared/types/CourseMeeting';
|
||||||
|
import Instructor from 'src/shared/types/Instructor';
|
||||||
|
|
||||||
export const ExampleCourse: Course = new Course({
|
export const ExampleCourse: Course = new Course({
|
||||||
courseName: 'ELEMS OF COMPTRS/PROGRAMMNG-WB',
|
courseName: 'ELEMS OF COMPTRS/PROGRAMMNG-WB',
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Status } from '@shared/types/Course';
|
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
|
||||||
import CourseStatus from '@views/components/common/CourseStatus/CourseStatus';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Status } from '@shared/types/Course';
|
||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import CourseStatus from '@views/components/common/CourseStatus/CourseStatus';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/CourseStatus',
|
title: 'Components/Common/CourseStatus',
|
||||||
component: CourseStatus,
|
component: CourseStatus,
|
||||||
@@ -39,7 +40,7 @@ export const Default: Story = {};
|
|||||||
|
|
||||||
export const Variants: Story = {
|
export const Variants: Story = {
|
||||||
render: args => (
|
render: args => (
|
||||||
<div className='flex flex-col items-center gap-4'>
|
<div className='flex flex-col gap-4 items-center'>
|
||||||
<CourseStatus {...args} size='small' />
|
<CourseStatus {...args} size='small' />
|
||||||
<CourseStatus {...args} size='mini' />
|
<CourseStatus {...args} size='mini' />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
18
src/stories/components/Divider.stories.ts
Normal file
18
src/stories/components/Divider.stories.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import Divider from 'src/views/components/common/Divider/Divider';
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: 'Components/Common/Divider',
|
||||||
|
component: Divider,
|
||||||
|
tags: ['autodocs'],
|
||||||
|
argTypes: {
|
||||||
|
color: {
|
||||||
|
control: 'color',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies Meta<typeof Divider>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
|
export const Default: Story = {};
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
|
||||||
import { Button } from '@views/components/common/Button/Button';
|
|
||||||
import Divider from '@views/components/common/Divider/Divider';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import AddIcon from '~icons/material-symbols/add';
|
|
||||||
import CalendarMonthIcon from '~icons/material-symbols/calendar-month';
|
|
||||||
import DescriptionIcon from '~icons/material-symbols/description';
|
|
||||||
import HappyFaceIcon from '~icons/material-symbols/mood';
|
|
||||||
import ReviewsIcon from '~icons/material-symbols/reviews';
|
|
||||||
|
|
||||||
const meta = {
|
|
||||||
title: 'Components/Common/Divider',
|
|
||||||
component: Divider,
|
|
||||||
parameters: {
|
|
||||||
layout: 'centered',
|
|
||||||
},
|
|
||||||
tags: ['autodocs'],
|
|
||||||
} satisfies Meta<typeof Divider>;
|
|
||||||
export default meta;
|
|
||||||
|
|
||||||
type Story = StoryObj<typeof meta>;
|
|
||||||
|
|
||||||
export const Vertical: Story = {
|
|
||||||
args: {
|
|
||||||
size: '2.5rem',
|
|
||||||
orientation: 'vertical',
|
|
||||||
},
|
|
||||||
render: props => <Divider {...props} />,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Horizontal: Story = {
|
|
||||||
args: {
|
|
||||||
size: '2.5rem',
|
|
||||||
orientation: 'horizontal',
|
|
||||||
},
|
|
||||||
render: props => <Divider {...props} />,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const IGotHorizontalIGotVerticalWhatYouWant: Story = {
|
|
||||||
args: {
|
|
||||||
size: '2.5rem',
|
|
||||||
orientation: 'vertical',
|
|
||||||
},
|
|
||||||
|
|
||||||
render: props => (
|
|
||||||
<div className='grid grid-cols-7 grid-rows-3 items-center justify-items-center gap-3.75'>
|
|
||||||
{Array.from({ length: 21 }).map((_, i) => (
|
|
||||||
<Divider {...props} orientation={i % 2 === 0 ? 'horizontal' : 'vertical'} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CourseCatalogActionButtons: Story = {
|
|
||||||
args: {
|
|
||||||
size: '1.75rem',
|
|
||||||
orientation: 'vertical',
|
|
||||||
},
|
|
||||||
render: props => (
|
|
||||||
<div className='flex items-center gap-3.75'>
|
|
||||||
<Button variant='filled' color='ut-burntorange' icon={CalendarMonthIcon} />
|
|
||||||
<Divider {...props} />
|
|
||||||
<Button variant='outline' color='ut-blue' icon={ReviewsIcon}>
|
|
||||||
RateMyProf
|
|
||||||
</Button>
|
|
||||||
<Button variant='outline' color='ut-teal' icon={HappyFaceIcon}>
|
|
||||||
CES
|
|
||||||
</Button>
|
|
||||||
<Button variant='outline' color='ut-orange' icon={DescriptionIcon}>
|
|
||||||
Past Syllabi
|
|
||||||
</Button>
|
|
||||||
<Button variant='filled' color='ut-green' icon={AddIcon}>
|
|
||||||
Add Course
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Course, Status } from '@shared/types/Course';
|
import { Course, Status } from '@shared/types/Course';
|
||||||
import { CourseMeeting, DAY_MAP } from '@shared/types/CourseMeeting';
|
|
||||||
import { CourseSchedule } from '@shared/types/CourseSchedule';
|
|
||||||
import Instructor from '@shared/types/Instructor';
|
|
||||||
import { UserSchedule } from '@shared/types/UserSchedule';
|
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import Dropdown from '@views/components/common/Dropdown/Dropdown';
|
|
||||||
import ScheduleListItem from '@views/components/common/ScheduleListItem/ScheduleListItem';
|
|
||||||
import type { Serialized } from 'chrome-extension-toolkit';
|
import type { Serialized } from 'chrome-extension-toolkit';
|
||||||
import React from '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 Dropdown from 'src/views/components/common/Dropdown/Dropdown';
|
||||||
|
import ScheduleListItem from 'src/views/components/common/ScheduleListItem/ScheduleListItem';
|
||||||
|
|
||||||
const meta: Meta<typeof Dropdown> = {
|
const meta: Meta<typeof Dropdown> = {
|
||||||
title: 'Components/Common/Dropdown',
|
title: 'Components/Common/Dropdown',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import ImportantLinks from '@views/components/calendar/ImportantLinks';
|
import ImportantLinks from 'src/views/components/calendar/ImportantLinks';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/ImportantLinks',
|
title: 'Components/Common/ImportantLinks',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { InfoCard } from '@views/components/common/InfoCard/InfoCard';
|
import { InfoCard } from 'src/views/components/common/InfoCard/InfoCard';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/InfoCard',
|
title: 'Components/Common/InfoCard',
|
||||||
@@ -22,4 +22,4 @@ export const Default: Story = {
|
|||||||
titleText: 'WAITLIST SIZE',
|
titleText: 'WAITLIST SIZE',
|
||||||
bodyText: '14 Students',
|
bodyText: '14 Students',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
|
import Link from 'src/views/components/common/Link/Link';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import Link from '@views/components/common/Link/Link';
|
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/Link',
|
title: 'Components/Common/Link',
|
||||||
component: Link,
|
component: Link,
|
||||||
parameters: {
|
parameters: {
|
||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
},
|
},
|
||||||
tags: ['autodocs'],
|
tags: ['autodocs'],
|
||||||
argTypes: {
|
argTypes: {
|
||||||
color: {
|
color: {
|
||||||
control: 'color',
|
control: 'color',
|
||||||
},
|
|
||||||
},
|
|
||||||
args: {
|
|
||||||
children: 'Link',
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
children: 'Link',
|
||||||
|
},
|
||||||
} satisfies Meta<typeof Link>;
|
} satisfies Meta<typeof Link>;
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|||||||
@@ -1,22 +1,15 @@
|
|||||||
import { Course, Status } from '@shared/types/Course';
|
import { Course, Status } from '@shared/types/Course';
|
||||||
import { CourseMeeting } from '@shared/types/CourseMeeting';
|
import { CourseMeeting } from '@shared/types/CourseMeeting';
|
||||||
import Instructor from '@shared/types/Instructor';
|
import Instructor from '@shared/types/Instructor';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import List from '@views/components/common/List/List';
|
import List from '@views/components/common/List/List';
|
||||||
import PopupCourseBlock from '@views/components/common/PopupCourseBlock/PopupCourseBlock';
|
import PopupCourseBlock from '@views/components/common/PopupCourseBlock/PopupCourseBlock';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { test_colors } from './PopupCourseBlock.stories';
|
||||||
import { TestColors } from './PopupCourseBlock.stories';
|
|
||||||
|
|
||||||
const numberOfCourses = 5;
|
const numberOfCourses = 5;
|
||||||
|
|
||||||
/**
|
export const generateCourses = count => {
|
||||||
* Generates an array of courses.
|
|
||||||
*
|
|
||||||
* @param count - The number of courses to generate.
|
|
||||||
* @returns An array of generated courses.
|
|
||||||
*/
|
|
||||||
export const GenerateCourses = count => {
|
|
||||||
const courses = [];
|
const courses = [];
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
@@ -68,10 +61,10 @@ export const GenerateCourses = count => {
|
|||||||
return courses;
|
return courses;
|
||||||
};
|
};
|
||||||
|
|
||||||
const exampleCourses = GenerateCourses(numberOfCourses);
|
const exampleCourses = generateCourses(numberOfCourses);
|
||||||
const generateCourseBlocks = (exampleCourses, colors) =>
|
const generateCourseBlocks = (exampleCourses, colors) =>
|
||||||
exampleCourses.map((course, i) => <PopupCourseBlock key={course.uniqueId} course={course} colors={colors[i]} />);
|
exampleCourses.map((course, i) => <PopupCourseBlock key={course.uniqueId} course={course} colors={colors[i]} />);
|
||||||
export const ExampleCourseBlocks = generateCourseBlocks(exampleCourses, TestColors);
|
export const exampleCourseBlocks = generateCourseBlocks(exampleCourses, test_colors);
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/List',
|
title: 'Components/Common/List',
|
||||||
@@ -94,7 +87,7 @@ type Story = StoryObj<typeof meta>;
|
|||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
draggableElements: ExampleCourseBlocks,
|
draggableElements: exampleCourseBlocks,
|
||||||
itemHeight: 55,
|
itemHeight: 55,
|
||||||
listHeight: 300,
|
listHeight: 300,
|
||||||
listWidth: 300,
|
listWidth: 300,
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
import { Course, Status } from '@shared/types/Course';
|
|
||||||
import { CourseMeeting } from '@shared/types/CourseMeeting';
|
|
||||||
import Instructor from '@shared/types/Instructor';
|
|
||||||
import { getCourseColors } from '@shared/util/colors';
|
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import PopupCourseBlock from '@views/components/common/PopupCourseBlock/PopupCourseBlock';
|
import PopupCourseBlock from '@views/components/common/PopupCourseBlock/PopupCourseBlock';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Course, Status } from 'src/shared/types/Course';
|
||||||
|
import { CourseMeeting } from 'src/shared/types/CourseMeeting';
|
||||||
|
import Instructor from 'src/shared/types/Instructor';
|
||||||
|
import { getCourseColors } from 'src/shared/util/colors';
|
||||||
import { theme } from 'unocss/preset-mini';
|
import { theme } from 'unocss/preset-mini';
|
||||||
|
|
||||||
/**
|
export const exampleCourse: Course = new Course({
|
||||||
* Represents an example course.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* This is a sample course object that provides information about a specific course.
|
|
||||||
*/
|
|
||||||
export 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',
|
||||||
@@ -68,7 +62,7 @@ const meta = {
|
|||||||
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
||||||
args: {
|
args: {
|
||||||
colors: getCourseColors('emerald'),
|
colors: getCourseColors('emerald'),
|
||||||
course: ExampleCourse,
|
course: exampleCourse,
|
||||||
},
|
},
|
||||||
argTypes: {
|
argTypes: {
|
||||||
colors: {
|
colors: {
|
||||||
@@ -93,15 +87,15 @@ export const Default: Story = {
|
|||||||
export const Variants: Story = {
|
export const Variants: Story = {
|
||||||
render: props => (
|
render: props => (
|
||||||
<div className='grid grid-cols-2 max-w-2xl w-90vw gap-x-4 gap-y-2'>
|
<div className='grid grid-cols-2 max-w-2xl w-90vw gap-x-4 gap-y-2'>
|
||||||
<PopupCourseBlock {...props} course={new Course({ ...ExampleCourse, status: Status.OPEN })} />
|
<PopupCourseBlock {...props} course={new Course({ ...exampleCourse, status: Status.OPEN })} />
|
||||||
<PopupCourseBlock {...props} course={new Course({ ...ExampleCourse, status: Status.CLOSED })} />
|
<PopupCourseBlock {...props} course={new Course({ ...exampleCourse, status: Status.CLOSED })} />
|
||||||
<PopupCourseBlock {...props} course={new Course({ ...ExampleCourse, status: Status.WAITLISTED })} />
|
<PopupCourseBlock {...props} course={new Course({ ...exampleCourse, status: Status.WAITLISTED })} />
|
||||||
<PopupCourseBlock {...props} course={new Course({ ...ExampleCourse, status: Status.CANCELLED })} />
|
<PopupCourseBlock {...props} course={new Course({ ...exampleCourse, status: Status.CANCELLED })} />
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TestColors = Object.keys(theme.colors)
|
export const test_colors = Object.keys(theme.colors)
|
||||||
// check that the color is a colorway (is an object)
|
// check that the color is a colorway (is an object)
|
||||||
.filter(color => typeof theme.colors[color] === 'object')
|
.filter(color => typeof theme.colors[color] === 'object')
|
||||||
.slice(0, 17)
|
.slice(0, 17)
|
||||||
@@ -110,8 +104,8 @@ export const TestColors = Object.keys(theme.colors)
|
|||||||
export const AllColors: Story = {
|
export const AllColors: Story = {
|
||||||
render: props => (
|
render: props => (
|
||||||
<div className='grid grid-flow-col grid-cols-2 grid-rows-9 max-w-2xl w-90vw gap-x-4 gap-y-2'>
|
<div className='grid grid-flow-col grid-cols-2 grid-rows-9 max-w-2xl w-90vw gap-x-4 gap-y-2'>
|
||||||
{TestColors.map((color, i) => (
|
{test_colors.map((color, i) => (
|
||||||
<PopupCourseBlock key={color.primaryColor} course={ExampleCourse} colors={color} />
|
<PopupCourseBlock key={color.primaryColor} course={exampleCourse} colors={color} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import PopupMain from '@views/components/PopupMain';
|
import PopupMain from '@views/components/PopupMain';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
@@ -8,12 +8,16 @@ const meta = {
|
|||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
},
|
},
|
||||||
tags: ['autodocs'],
|
tags: ['autodocs'],
|
||||||
argTypes: {},
|
argTypes: {
|
||||||
|
|
||||||
|
},
|
||||||
} satisfies Meta<typeof PopupMain>;
|
} satisfies Meta<typeof PopupMain>;
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<typeof meta>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {},
|
args: {
|
||||||
};
|
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import ScheduleTotalHoursAndCourses from '@views/components/common/ScheduleTotalHoursAndCourses/ScheduleTotalHoursAndCourses';
|
import ScheduleTotalHoursAndCourses from '@views/components/common/ScheduleTotalHoursAndCourses/ScheduleTotalHoursAndCourses';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
@@ -11,7 +11,7 @@ const meta = {
|
|||||||
argTypes: {
|
argTypes: {
|
||||||
scheduleName: { control: 'text' },
|
scheduleName: { control: 'text' },
|
||||||
totalHours: { control: 'number' },
|
totalHours: { control: 'number' },
|
||||||
totalCourses: { control: 'number' },
|
totalCourses: { control: 'number' }
|
||||||
},
|
},
|
||||||
} satisfies Meta<typeof ScheduleTotalHoursAndCourses>;
|
} satisfies Meta<typeof ScheduleTotalHoursAndCourses>;
|
||||||
export default meta;
|
export default meta;
|
||||||
@@ -22,6 +22,6 @@ export const Default: Story = {
|
|||||||
args: {
|
args: {
|
||||||
scheduleName: 'SCHEDULE',
|
scheduleName: 'SCHEDULE',
|
||||||
totalHours: 22,
|
totalHours: 22,
|
||||||
totalCourses: 8,
|
totalCourses: 8
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/* eslint-disable jsdoc/require-jsdoc */
|
|
||||||
import ScheduleListItem from '@views/components/common/ScheduleListItem/ScheduleListItem';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import ScheduleListItem from 'src/views/components/common/ScheduleListItem/ScheduleListItem';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/Common/ScheduleListItem',
|
title: 'Components/Common/ScheduleListItem',
|
||||||
@@ -15,21 +14,21 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Default = args => <ScheduleListItem {...args} />;
|
export const Default = (args) => <ScheduleListItem {...args} />;
|
||||||
|
|
||||||
Default.args = {
|
Default.args = {
|
||||||
name: 'My Schedule',
|
name: 'My Schedule',
|
||||||
active: true,
|
active: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Active = args => <ScheduleListItem {...args} />;
|
export const Active = (args) => <ScheduleListItem {...args} />;
|
||||||
|
|
||||||
Active.args = {
|
Active.args = {
|
||||||
name: 'My Schedule',
|
name: 'My Schedule',
|
||||||
active: true,
|
active: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Inactive = args => <ScheduleListItem {...args} />;
|
export const Inactive = (args) => <ScheduleListItem {...args} />;
|
||||||
|
|
||||||
Inactive.args = {
|
Inactive.args = {
|
||||||
name: 'My Schedule',
|
name: 'My Schedule',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import Settings from '@views/components/Settings';
|
import Settings from 'src/views/components/Settings';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/Settings',
|
title: 'Components/Common/Settings',
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
import Spinner from 'src/views/components/common/Spinner/Spinner';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import Spinner from '@views/components/common/Spinner/Spinner';
|
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Common/Spinner',
|
title: 'Components/Common/Spinner',
|
||||||
component: Spinner,
|
component: Spinner,
|
||||||
tags: ['autodocs'],
|
tags: ['autodocs'],
|
||||||
argTypes: {},
|
argTypes: {},
|
||||||
} satisfies Meta<typeof Spinner>;
|
} satisfies Meta<typeof Spinner>;
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { Button } from 'src/views/components/common/Button/Button';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import Text from '@views/components/common/Text/Text';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Text from '../../views/components/common/Text/Text';
|
||||||
|
|
||||||
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
||||||
const meta = {
|
const meta = {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { Calendar } from '@views/components/calendar/Calendar/Calendar';
|
import { Calendar } from 'src/views/components/calendar/Calendar/Calendar';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Calendar/Calendar',
|
title: 'Components/Calendar/Calendar',
|
||||||
@@ -8,12 +8,16 @@ const meta = {
|
|||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
},
|
},
|
||||||
tags: ['autodocs'],
|
tags: ['autodocs'],
|
||||||
argTypes: {},
|
argTypes: {
|
||||||
|
|
||||||
|
},
|
||||||
} satisfies Meta<typeof Calendar>;
|
} satisfies Meta<typeof Calendar>;
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<typeof meta>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {},
|
args: {
|
||||||
};
|
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { Course, Status } from '@shared/types/Course';
|
import { Course, Status } from '@shared/types/Course';
|
||||||
import Instructor from '@shared/types/Instructor';
|
import Instructor from '@shared/types/Instructor';
|
||||||
import { getCourseColors } from '@shared/util/colors';
|
import { CalendarBottomBar } from 'src/views/components/calendar/CalendarBottomBar/CalendarBottomBar';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { getCourseColors } from '../../../shared/util/colors';
|
||||||
import { CalendarBottomBar } from '@views/components/calendar/CalendarBottomBar/CalendarBottomBar';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const exampleGovCourse: Course = new Course({
|
const exampleGovCourse: Course = new Course({
|
||||||
courseName: 'Nope',
|
courseName: 'Nope',
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { Course, Status } from '@shared/types/Course';
|
import { Course, Status } from '@shared/types/Course';
|
||||||
import { CourseMeeting, DAY_MAP } from '@shared/types/CourseMeeting';
|
import { CourseMeeting, DAY_MAP } from '@shared/types/CourseMeeting';
|
||||||
import { CourseSchedule } from '@shared/types/CourseSchedule';
|
import { CourseSchedule } from '@shared/types/CourseSchedule';
|
||||||
import Instructor from '@shared/types/Instructor';
|
import Instructor from '@shared/types/Instructor';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import CalendarCourse from 'src/views/components/calendar/CalendarCourseBlock/CalendarCourseMeeting';
|
||||||
import CalendarCourse from '@views/components/calendar/CalendarCourseBlock/CalendarCourseMeeting';
|
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Calendar/CalendarCourseMeeting',
|
title: 'Components/Calendar/CalendarCourseMeeting',
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { Course, Status } from '@shared/types/Course';
|
import { Course, Status } from '@shared/types/Course';
|
||||||
import { getCourseColors } from '@shared/util/colors';
|
import { getCourseColors } from '@shared/util/colors';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import CalendarCourseCell from '@views/components/calendar/CalendarCourseCell/CalendarCourseCell';
|
import CalendarCourseCell from 'src/views/components/calendar/CalendarCourseCell/CalendarCourseCell';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { exampleCourse } from '../PopupCourseBlock.stories';
|
||||||
import { ExampleCourse } from '../PopupCourseBlock.stories';
|
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Calendar/CalendarCourseCell',
|
title: 'Components/Calendar/CalendarCourseCell',
|
||||||
@@ -26,10 +25,10 @@ const meta = {
|
|||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
args: {
|
args: {
|
||||||
courseDeptAndInstr: ExampleCourse.department,
|
courseDeptAndInstr: exampleCourse.department,
|
||||||
className: ExampleCourse.number,
|
className: exampleCourse.number,
|
||||||
status: ExampleCourse.status,
|
status: exampleCourse.status,
|
||||||
timeAndLocation: ExampleCourse.schedule.meetings[0].getTimeString({ separator: '-' }),
|
timeAndLocation: exampleCourse.schedule.meetings[0].getTimeString({ separator: '-' }),
|
||||||
|
|
||||||
colors: getCourseColors('emerald', 500),
|
colors: getCourseColors('emerald', 500),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import { Status } from '@shared/types/Course';
|
import { Course, Status } from '@shared/types/Course';
|
||||||
import { getCourseColors } from '@shared/util/colors';
|
import { getCourseColors } from '@shared/util/colors';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import CalendarGrid from '@views/components/calendar/CalendarGrid/CalendarGrid';
|
|
||||||
import type { CalendarGridCourse } from '@views/hooks/useFlattenedCourseSchedule';
|
import type { CalendarGridCourse } from '@views/hooks/useFlattenedCourseSchedule';
|
||||||
|
import { Serialized } from 'chrome-extension-toolkit';
|
||||||
|
import { CourseMeeting, DAY_MAP } from 'src/shared/types/CourseMeeting';
|
||||||
|
import { CourseSchedule } from 'src/shared/types/CourseSchedule';
|
||||||
|
import Instructor from 'src/shared/types/Instructor';
|
||||||
|
import { UserSchedule } from 'src/shared/types/UserSchedule';
|
||||||
|
import CalendarGrid from 'src/views/components/calendar/CalendarGrid/CalendarGrid';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Calendar/CalendarGrid',
|
title: 'Components/Calendar/CalendarGrid',
|
||||||
@@ -17,6 +22,57 @@ const meta = {
|
|||||||
} satisfies Meta<typeof CalendarGrid>;
|
} satisfies Meta<typeof CalendarGrid>;
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
const exampleCourse: Course = new Course({
|
||||||
|
uniqueId: 50805,
|
||||||
|
number: '314',
|
||||||
|
fullName: 'C S 314 DATA STRUCTURES',
|
||||||
|
courseName: 'DATA STRUCTURES',
|
||||||
|
department: 'C S',
|
||||||
|
creditHours: 3,
|
||||||
|
status: Status.OPEN,
|
||||||
|
instructors: [
|
||||||
|
new Instructor({ fullName: 'SCOTT, MICHAEL', firstName: 'MICHAEL', lastName: 'SCOTT', middleInitial: 'D' }),
|
||||||
|
],
|
||||||
|
isReserved: true,
|
||||||
|
description: [
|
||||||
|
'Second part of a two-part sequence in programming. Introduction to specifications, simple unit testing, and debugging; building and using canonical data structures; algorithm analysis and reasoning techniques such as assertions and invariants.',
|
||||||
|
'Computer Science 314 and 314H may not both be counted.',
|
||||||
|
'BVO 311C and 312H may not both be counted.',
|
||||||
|
'Prerequisite: Computer Science 312 or 312H with a grade of at least C-.',
|
||||||
|
'May be counted toward the Quantitative Reasoning flag requirement.',
|
||||||
|
],
|
||||||
|
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: {
|
||||||
|
code: '12345',
|
||||||
|
year: 2024,
|
||||||
|
season: 'Spring',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const exampleSchedule = new UserSchedule({
|
||||||
|
name: 'Example Schedule',
|
||||||
|
courses: [exampleCourse],
|
||||||
|
hours: 3,
|
||||||
|
} as Serialized<UserSchedule>);
|
||||||
|
|
||||||
const testData: CalendarGridCourse[] = [
|
const testData: CalendarGridCourse[] = [
|
||||||
{
|
{
|
||||||
calendarGridPoint: {
|
calendarGridPoint: {
|
||||||
@@ -30,6 +86,11 @@ const testData: CalendarGridCourse[] = [
|
|||||||
status: Status.OPEN,
|
status: Status.OPEN,
|
||||||
colors: getCourseColors('emerald', 500),
|
colors: getCourseColors('emerald', 500),
|
||||||
},
|
},
|
||||||
|
popupProps: {
|
||||||
|
course: exampleCourse,
|
||||||
|
activeSchedule: exampleSchedule,
|
||||||
|
onClose: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
calendarGridPoint: {
|
calendarGridPoint: {
|
||||||
@@ -43,6 +104,11 @@ const testData: CalendarGridCourse[] = [
|
|||||||
status: Status.OPEN,
|
status: Status.OPEN,
|
||||||
colors: getCourseColors('emerald', 500),
|
colors: getCourseColors('emerald', 500),
|
||||||
},
|
},
|
||||||
|
popupProps: {
|
||||||
|
course: exampleCourse,
|
||||||
|
activeSchedule: exampleSchedule,
|
||||||
|
onClose: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
calendarGridPoint: {
|
calendarGridPoint: {
|
||||||
@@ -56,6 +122,11 @@ const testData: CalendarGridCourse[] = [
|
|||||||
status: Status.CLOSED,
|
status: Status.CLOSED,
|
||||||
colors: getCourseColors('emerald', 500),
|
colors: getCourseColors('emerald', 500),
|
||||||
},
|
},
|
||||||
|
popupProps: {
|
||||||
|
course: exampleCourse,
|
||||||
|
activeSchedule: exampleSchedule,
|
||||||
|
onClose: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
calendarGridPoint: {
|
calendarGridPoint: {
|
||||||
@@ -69,6 +140,11 @@ const testData: CalendarGridCourse[] = [
|
|||||||
status: Status.OPEN,
|
status: Status.OPEN,
|
||||||
colors: getCourseColors('emerald', 500),
|
colors: getCourseColors('emerald', 500),
|
||||||
},
|
},
|
||||||
|
popupProps: {
|
||||||
|
course: exampleCourse,
|
||||||
|
activeSchedule: exampleSchedule,
|
||||||
|
onClose: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
calendarGridPoint: {
|
calendarGridPoint: {
|
||||||
@@ -82,6 +158,11 @@ const testData: CalendarGridCourse[] = [
|
|||||||
status: Status.CLOSED,
|
status: Status.CLOSED,
|
||||||
colors: getCourseColors('emerald', 500),
|
colors: getCourseColors('emerald', 500),
|
||||||
},
|
},
|
||||||
|
popupProps: {
|
||||||
|
course: exampleCourse,
|
||||||
|
activeSchedule: exampleSchedule,
|
||||||
|
onClose: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
calendarGridPoint: {
|
calendarGridPoint: {
|
||||||
@@ -95,6 +176,11 @@ const testData: CalendarGridCourse[] = [
|
|||||||
status: Status.CLOSED,
|
status: Status.CLOSED,
|
||||||
colors: getCourseColors('emerald', 500),
|
colors: getCourseColors('emerald', 500),
|
||||||
},
|
},
|
||||||
|
popupProps: {
|
||||||
|
course: exampleCourse,
|
||||||
|
activeSchedule: exampleSchedule,
|
||||||
|
onClose: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
calendarGridPoint: {
|
calendarGridPoint: {
|
||||||
@@ -108,6 +194,11 @@ const testData: CalendarGridCourse[] = [
|
|||||||
status: Status.CLOSED,
|
status: Status.CLOSED,
|
||||||
colors: getCourseColors('emerald', 500),
|
colors: getCourseColors('emerald', 500),
|
||||||
},
|
},
|
||||||
|
popupProps: {
|
||||||
|
course: exampleCourse,
|
||||||
|
activeSchedule: exampleSchedule,
|
||||||
|
onClose: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Calendar.stories.tsx
|
// Calendar.stories.tsx
|
||||||
|
import React from 'react';
|
||||||
|
import CalendarCell from 'src/views/components/calendar/CalendarGridCell/CalendarGridCell';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import CalendarCell from '@views/components/calendar/CalendarGridCell/CalendarGridCell';
|
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Calendar/CalendarGridCell',
|
title: 'Components/Calendar/CalendarGridCell',
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import React from 'react';
|
||||||
import CalendarHeader from '@views/components/calendar/CalendarHeader/CalenderHeader';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import CalendarHeader from 'src/views/components/calendar/CalendarHeader/CalenderHeader';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Calendar/CalendarHeader',
|
title: 'Components/Calendar/CalendarHeader',
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Course, Status } from '@shared/types/Course';
|
import { Course, Status } from '@shared/types/Course';
|
||||||
import { CourseMeeting, DAY_MAP } from '@shared/types/CourseMeeting';
|
|
||||||
import { CourseSchedule } from '@shared/types/CourseSchedule';
|
|
||||||
import Instructor from '@shared/types/Instructor';
|
|
||||||
import { UserSchedule } from '@shared/types/UserSchedule';
|
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import { CalendarSchedules } from '@views/components/calendar/CalendarSchedules/CalendarSchedules';
|
|
||||||
import React from '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/calendar/CalendarSchedules/CalendarSchedules';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Components/Calendar/CalendarSchedules',
|
title: 'Components/Calendar/CalendarSchedules',
|
||||||
@@ -17,6 +17,7 @@ const meta = {
|
|||||||
argTypes: {
|
argTypes: {
|
||||||
dummySchedules: { control: 'object' },
|
dummySchedules: { control: 'object' },
|
||||||
dummyActiveIndex: { control: 'number' },
|
dummyActiveIndex: { control: 'number' },
|
||||||
|
|
||||||
},
|
},
|
||||||
render: (args: any) => (
|
render: (args: any) => (
|
||||||
<div>
|
<div>
|
||||||
@@ -140,5 +141,6 @@ export const Default: Story = {
|
|||||||
args: {
|
args: {
|
||||||
dummySchedules: schedules,
|
dummySchedules: schedules,
|
||||||
dummyActiveIndex: 0,
|
dummyActiveIndex: 0,
|
||||||
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Course, Status } from '@shared/types/Course';
|
|
||||||
import { CourseMeeting, DAY_MAP } from '@shared/types/CourseMeeting';
|
|
||||||
import { CourseSchedule } from '@shared/types/CourseSchedule';
|
|
||||||
import Instructor from '@shared/types/Instructor';
|
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import CourseCatalogInjectedPopup from '@views/components/injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup';
|
import type { Serialized } from 'chrome-extension-toolkit';
|
||||||
|
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';
|
||||||
|
import { UserSchedule } from 'src/shared/types/UserSchedule';
|
||||||
|
import CourseCatalogInjectedPopup from 'src/views/components/injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup';
|
||||||
|
|
||||||
const exampleCourse: Course = new Course({
|
const exampleCourse: Course = new Course({
|
||||||
uniqueId: 50805,
|
uniqueId: 50805,
|
||||||
@@ -50,11 +52,19 @@ const exampleCourse: Course = new Course({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const exampleSchedule = new UserSchedule({
|
||||||
|
name: 'Example Schedule',
|
||||||
|
courses: [exampleCourse],
|
||||||
|
hours: 3,
|
||||||
|
} as Serialized<UserSchedule>);
|
||||||
|
|
||||||
const meta: Meta<typeof CourseCatalogInjectedPopup> = {
|
const meta: Meta<typeof CourseCatalogInjectedPopup> = {
|
||||||
title: 'Components/Injected/CourseCatalogInjectedPopup',
|
title: 'Components/Injected/CourseCatalogInjectedPopup',
|
||||||
component: CourseCatalogInjectedPopup,
|
component: CourseCatalogInjectedPopup,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
onClose: { action: 'onClose' },
|
onClose: { action: 'onClose' },
|
||||||
|
activeSchedule: { control: 'object' },
|
||||||
|
course: { control: 'object' },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -63,6 +73,7 @@ type Story = StoryObj<typeof CourseCatalogInjectedPopup>;
|
|||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
activeSchedule: exampleSchedule,
|
||||||
course: exampleCourse,
|
course: exampleCourse,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Course, Status } from '@shared/types/Course';
|
import { Course, Status } from 'src/shared/types/Course';
|
||||||
import { CourseMeeting } from '@shared/types/CourseMeeting';
|
import { CourseMeeting } from 'src/shared/types/CourseMeeting';
|
||||||
import Instructor from '@shared/types/Instructor';
|
import { UserSchedule } from 'src/shared/types/UserSchedule';
|
||||||
import { UserSchedule } from '@shared/types/UserSchedule';
|
import CoursePopup from 'src/views/components/injected/CoursePopupOld/CoursePopup';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import CoursePopup from '@views/components/injected/CoursePopupOld/CoursePopup';
|
import Instructor from 'src/shared/types/Instructor';
|
||||||
|
|
||||||
const exampleCourse: Course = new Course({
|
const exampleCourse: Course = new Course({
|
||||||
courseName: 'ELEMS OF COMPTRS/PROGRAMMNG-WB',
|
courseName: 'ELEMS OF COMPTRS/PROGRAMMNG-WB',
|
||||||
|
|||||||
@@ -2,7 +2,13 @@
|
|||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"lib": ["DOM", "es2021"],
|
"lib": [
|
||||||
"types": ["chrome", "node"]
|
"DOM",
|
||||||
}
|
"es2021"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"chrome",
|
||||||
|
"node",
|
||||||
|
],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
import type { Course, ScrapedRow } from '@shared/types/Course';
|
import { Course, ScrapedRow } from '@shared/types/Course';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { useKeyPress } from '../hooks/useKeyPress';
|
import { useKeyPress } from '../hooks/useKeyPress';
|
||||||
import useSchedules from '../hooks/useSchedules';
|
import useSchedules from '../hooks/useSchedules';
|
||||||
import { CourseCatalogScraper } from '../lib/CourseCatalogScraper';
|
import { CourseCatalogScraper } from '../lib/CourseCatalogScraper';
|
||||||
import getCourseTableRows from '../lib/getCourseTableRows';
|
import getCourseTableRows from '../lib/getCourseTableRows';
|
||||||
import type { SiteSupport } from '../lib/getSiteSupport';
|
import { SiteSupport } from '../lib/getSiteSupport';
|
||||||
import { populateSearchInputs } from '../lib/populateSearchInputs';
|
import { populateSearchInputs } from '../lib/populateSearchInputs';
|
||||||
import ExtensionRoot from './common/ExtensionRoot/ExtensionRoot';
|
import ExtensionRoot from './common/ExtensionRoot/ExtensionRoot';
|
||||||
import AutoLoad from './injected/AutoLoad/AutoLoad';
|
import AutoLoad from './injected/AutoLoad/AutoLoad';
|
||||||
import CourseCatalogInjectedPopup from './injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup';
|
|
||||||
import CoursePopup from './injected/CoursePopupOld/CoursePopup';
|
import CoursePopup from './injected/CoursePopupOld/CoursePopup';
|
||||||
import RecruitmentBanner from './injected/RecruitmentBanner/RecruitmentBanner';
|
import RecruitmentBanner from './injected/RecruitmentBanner/RecruitmentBanner';
|
||||||
import TableHead from './injected/TableHead';
|
import TableHead from './injected/TableHead';
|
||||||
import TableRow from './injected/TableRow/TableRow';
|
import TableRow from './injected/TableRow/TableRow';
|
||||||
import TableSubheading from './injected/TableSubheading/TableSubheading';
|
import TableSubheading from './injected/TableSubheading/TableSubheading';
|
||||||
|
import CourseCatalogInjectedPopup from './injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
support: SiteSupport.COURSE_CATALOG_DETAILS | SiteSupport.COURSE_CATALOG_LIST;
|
support: SiteSupport.COURSE_CATALOG_DETAILS | SiteSupport.COURSE_CATALOG_LIST;
|
||||||
|
|||||||
@@ -1,32 +1,23 @@
|
|||||||
import logoImage from '@assets/logo.png'; // Adjust the path as necessary
|
|
||||||
import { Status } from '@shared/types/Course';
|
|
||||||
import { StatusIcon } from '@shared/util/icons';
|
import { StatusIcon } from '@shared/util/icons';
|
||||||
import Divider from '@views/components/common/Divider/Divider';
|
|
||||||
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
|
||||||
import List from '@views/components/common/List/List'; // Ensure this path is correctly pointing to your List component
|
|
||||||
import PopupCourseBlock from '@views/components/common/PopupCourseBlock/PopupCourseBlock';
|
|
||||||
import Text from '@views/components/common/Text/Text';
|
|
||||||
import { handleOpenCalendar } from '@views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions';
|
|
||||||
import useSchedules from '@views/hooks/useSchedules';
|
|
||||||
import { openTabFromContentScript } from '@views/lib/openNewTabFromContentScript';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { TestColors } from 'src/stories/components/PopupCourseBlock.stories';
|
// import { FaCalendarAlt, FaCog, FaRedo } from 'react-icons/fa'; // Added FaRedo for the refresh icon
|
||||||
|
import { Status } from 'src/shared/types/Course';
|
||||||
|
import { test_colors } from 'src/stories/components/PopupCourseBlock.stories';
|
||||||
|
import logoImage from '../../assets/logo.png'; // Adjust the path as necessary
|
||||||
|
import useSchedules from '../hooks/useSchedules';
|
||||||
|
import { openTabFromContentScript } from '../lib/openNewTabFromContentScript';
|
||||||
|
import Divider from './common/Divider/Divider';
|
||||||
|
import ExtensionRoot from './common/ExtensionRoot/ExtensionRoot';
|
||||||
|
import List from './common/List/List'; // Ensure this path is correctly pointing to your List component
|
||||||
|
import PopupCourseBlock from './common/PopupCourseBlock/PopupCourseBlock';
|
||||||
|
import Text from './common/Text/Text';
|
||||||
|
import { handleOpenCalendar } from './injected/CourseCatalogInjectedPopup/HeadingAndActions';
|
||||||
|
|
||||||
import CalendarMonthIcon from '~icons/material-symbols/calendar-month';
|
|
||||||
import RedoIcon from '~icons/material-symbols/redo';
|
|
||||||
import SettingsIcon from '~icons/material-symbols/settings';
|
|
||||||
|
|
||||||
import { Button } from './common/Button/Button';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the main popup component.
|
|
||||||
* This component displays the main schedule, courses, and options buttons.
|
|
||||||
*/
|
|
||||||
export default function PopupMain() {
|
export default function PopupMain() {
|
||||||
const [activeSchedule] = useSchedules();
|
const [activeSchedule] = useSchedules();
|
||||||
|
|
||||||
const draggableElements = activeSchedule?.courses.map((course, i) => (
|
const draggableElements = activeSchedule?.courses.map((course, i) => (
|
||||||
<PopupCourseBlock key={course.uniqueId} course={course} colors={TestColors[i]} />
|
<PopupCourseBlock key={course.uniqueId} course={course} colors={test_colors[i]} />
|
||||||
));
|
));
|
||||||
|
|
||||||
const handleOpenOptions = async () => {
|
const handleOpenOptions = async () => {
|
||||||
@@ -51,25 +42,27 @@ export default function PopupMain() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center'>
|
<div className='flex items-center'>
|
||||||
<Button
|
<button
|
||||||
className='rounded-lg px-4 py-2'
|
style={{ backgroundColor: '#bf5700', borderRadius: '8px', padding: '8px' }}
|
||||||
onClick={handleOpenCalendar}
|
onClick={handleOpenCalendar}
|
||||||
variant='filled'
|
|
||||||
color='ut-burntorange'
|
|
||||||
>
|
>
|
||||||
<CalendarMonthIcon className='text-white' />
|
{/* <FaCalendarAlt color='white' /> */}
|
||||||
</Button>
|
</button>
|
||||||
<Button
|
<button
|
||||||
className='ml-10 rounded-lg px-4 py-2 shadow-sm'
|
style={{
|
||||||
|
backgroundColor: 'white',
|
||||||
|
marginLeft: '10px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
padding: '8px',
|
||||||
|
boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)',
|
||||||
|
}}
|
||||||
onClick={handleOpenOptions}
|
onClick={handleOpenOptions}
|
||||||
variant='filled'
|
|
||||||
color='ut-offwhite'
|
|
||||||
>
|
>
|
||||||
<SettingsIcon className='text-ut-burntorange' />
|
{/* <FaCog color='#C05621' /> */}
|
||||||
</Button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Divider orientation='horizontal' size='width' />
|
<Divider color='#E2E8F0' type='solid' style={{ margin: '1rem 0' }} />
|
||||||
<div
|
<div
|
||||||
className='mb-4 rounded-lg bg-white p-2 text-left shadow-inner'
|
className='mb-4 rounded-lg bg-white p-2 text-left shadow-inner'
|
||||||
style={{ backgroundColor: 'white', border: '1px solid #FBD38D', borderRadius: '0.5rem' }}
|
style={{ backgroundColor: 'white', border: '1px solid #FBD38D', borderRadius: '0.5rem' }}
|
||||||
@@ -155,7 +148,7 @@ export default function PopupMain() {
|
|||||||
<Text as='div' variant='mini'>
|
<Text as='div' variant='mini'>
|
||||||
DATA UPDATED ON: 12:00 AM 02/01/2024
|
DATA UPDATED ON: 12:00 AM 02/01/2024
|
||||||
</Text>
|
</Text>
|
||||||
<RedoIcon className='ml-2 h-4 w-4 text-gray' />
|
{/* <FaRedo className='ml-2 h-4 w-4 text-gray-600' /> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import CalendarHeader from 'src/views/components/calendar/CalendarHeader/CalenderHeader';
|
import CalendarHeader from 'src/views/components/calendar/CalendarHeader/CalenderHeader';
|
||||||
|
|
||||||
import { CalendarBottomBar } from '../CalendarBottomBar/CalendarBottomBar';
|
import { CalendarBottomBar } from '../CalendarBottomBar/CalendarBottomBar';
|
||||||
import CalendarGrid from '../CalendarGrid/CalendarGrid';
|
|
||||||
import { CalendarSchedules } from '../CalendarSchedules/CalendarSchedules';
|
import { CalendarSchedules } from '../CalendarSchedules/CalendarSchedules';
|
||||||
import ImportantLinks from '../ImportantLinks';
|
import ImportantLinks from '../ImportantLinks';
|
||||||
|
import CalendarGrid from '../CalendarGrid/CalendarGrid';
|
||||||
|
|
||||||
export const flags = ['WR', 'QR', 'GC', 'CD', 'E', 'II'];
|
export const flags = ['WR', 'QR', 'GC', 'CD', 'E', 'II'];
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import clsx from 'clsx';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
import CalendarMonthIcon from '~icons/material-symbols/calendar-month';
|
|
||||||
import ImageIcon from '~icons/material-symbols/image';
|
|
||||||
|
|
||||||
import { Button } from '../../common/Button/Button';
|
|
||||||
import Text from '../../common/Text/Text';
|
import Text from '../../common/Text/Text';
|
||||||
import type { CalendarCourseCellProps } from '../CalendarCourseCell/CalendarCourseCell';
|
import CalendarCourseBlock, { CalendarCourseCellProps } from '../CalendarCourseCell/CalendarCourseCell';
|
||||||
import CalendarCourseBlock from '../CalendarCourseCell/CalendarCourseCell';
|
import { Button } from '../../common/Button/Button';
|
||||||
|
import ImageIcon from '~icons/material-symbols/image';
|
||||||
|
import CalendarMonthIcon from '~icons/material-symbols/calendar-month';
|
||||||
|
|
||||||
type CalendarBottomBarProps = {
|
type CalendarBottomBarProps = {
|
||||||
courses?: CalendarCourseCellProps[];
|
courses?: CalendarCourseCellProps[];
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { Course } from 'src/shared/types/Course';
|
import { Course } from 'src/shared/types/Course';
|
||||||
import type { CourseMeeting } from 'src/shared/types/CourseMeeting';
|
import { CourseMeeting } from 'src/shared/types/CourseMeeting';
|
||||||
|
|
||||||
import styles from './CalendarCourseMeeting.module.scss';
|
import styles from './CalendarCourseMeeting.module.scss';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,8 +26,6 @@ export interface CalendarCourseMeetingProps {
|
|||||||
const CalendarCourseMeeting: React.FC<CalendarCourseMeetingProps> = ({
|
const CalendarCourseMeeting: React.FC<CalendarCourseMeetingProps> = ({
|
||||||
course,
|
course,
|
||||||
meetingIdx,
|
meetingIdx,
|
||||||
color,
|
|
||||||
rightIcon,
|
|
||||||
}: CalendarCourseMeetingProps) => {
|
}: CalendarCourseMeetingProps) => {
|
||||||
let meeting: CourseMeeting | null = meetingIdx !== undefined ? course.schedule.meetings[meetingIdx] : null;
|
let meeting: CourseMeeting | null = meetingIdx !== undefined ? course.schedule.meetings[meetingIdx] : null;
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Status } from '@shared/types/Course';
|
import { Status } from '@shared/types/Course';
|
||||||
import Text from '@views/components/common/Text/Text';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { CourseColors } from 'src/shared/util/colors';
|
import type { CourseColors } from 'src/shared/util/colors';
|
||||||
@@ -9,36 +8,26 @@ import ClosedIcon from '~icons/material-symbols/lock';
|
|||||||
import WaitlistIcon from '~icons/material-symbols/timelapse';
|
import WaitlistIcon from '~icons/material-symbols/timelapse';
|
||||||
import CancelledIcon from '~icons/material-symbols/warning';
|
import CancelledIcon from '~icons/material-symbols/warning';
|
||||||
|
|
||||||
/**
|
import Text from '../../common/Text/Text';
|
||||||
* Props for the CalendarCourseCell component.
|
|
||||||
*/
|
|
||||||
export interface CalendarCourseCellProps {
|
export interface CalendarCourseCellProps {
|
||||||
courseDeptAndInstr: string;
|
courseDeptAndInstr: string;
|
||||||
timeAndLocation?: string;
|
timeAndLocation?: string;
|
||||||
status: Status;
|
status: Status;
|
||||||
colors: CourseColors;
|
colors: CourseColors;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
popup?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a cell for a calendar course.
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @param {CalendarCourseCellProps} props - The component props.
|
|
||||||
* @param {string} props.courseDeptAndInstr - The course department and instructor.
|
|
||||||
* @param {string} props.timeAndLocation - The time and location of the course.
|
|
||||||
* @param {Status} props.status - The status of the course.
|
|
||||||
* @param {Colors} props.colors - The colors for styling the cell.
|
|
||||||
* @param {string} props.className - Additional CSS class name for the cell.
|
|
||||||
* @returns {JSX.Element} The rendered component.
|
|
||||||
*/
|
|
||||||
const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
|
const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
|
||||||
courseDeptAndInstr,
|
courseDeptAndInstr,
|
||||||
timeAndLocation,
|
timeAndLocation,
|
||||||
status,
|
status,
|
||||||
colors,
|
colors,
|
||||||
className,
|
className,
|
||||||
|
popup,
|
||||||
}: CalendarCourseCellProps) => {
|
}: CalendarCourseCellProps) => {
|
||||||
|
const [showPopup, setShowPopup] = React.useState(false);
|
||||||
let rightIcon: React.ReactNode | null = null;
|
let rightIcon: React.ReactNode | null = null;
|
||||||
if (status === Status.WAITLISTED) {
|
if (status === Status.WAITLISTED) {
|
||||||
rightIcon = <WaitlistIcon className='h-5 w-5' />;
|
rightIcon = <WaitlistIcon className='h-5 w-5' />;
|
||||||
@@ -48,15 +37,26 @@ const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
|
|||||||
rightIcon = <CancelledIcon className='h-5 w-5' />;
|
rightIcon = <CancelledIcon className='h-5 w-5' />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// popup.onClose = () => setShowPopup(false);
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
setShowPopup(true);
|
||||||
|
};
|
||||||
|
|
||||||
// whiteText based on secondaryColor
|
// whiteText based on secondaryColor
|
||||||
const fontColor = pickFontColor(colors.primaryColor);
|
const fontColor = pickFontColor(colors.primaryColor);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx('h-full w-full flex justify-center rounded p-2 overflow-x-hidden', fontColor, className)}
|
className={clsx(
|
||||||
|
'h-full w-full flex justify-center rounded p-2 overflow-x-hidden cursor-pointer',
|
||||||
|
fontColor,
|
||||||
|
className
|
||||||
|
)}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.primaryColor,
|
backgroundColor: colors.primaryColor,
|
||||||
}}
|
}}
|
||||||
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
<div className='flex flex-1 flex-col gap-1'>
|
<div className='flex flex-1 flex-col gap-1'>
|
||||||
<Text
|
<Text
|
||||||
@@ -83,6 +83,7 @@ const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
|
|||||||
{rightIcon}
|
{rightIcon}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<div>{showPopup ? popup : null}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { CalendarGridCourse } from '@views/hooks/useFlattenedCourseSchedule';
|
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
// import html2canvas from 'html2canvas';
|
// import html2canvas from 'html2canvas';
|
||||||
import { DAY_MAP } from 'src/shared/types/CourseMeeting';
|
import { DAY_MAP } from 'src/shared/types/CourseMeeting';
|
||||||
|
import CourseCatalogInjectedPopup from 'src/views/components/injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup';
|
||||||
|
import type { CalendarGridCourse } from 'src/views/hooks/useFlattenedCourseSchedule';
|
||||||
|
|
||||||
import CalendarCourseCell from '../CalendarCourseCell/CalendarCourseCell';
|
import CalendarCourseCell from '../CalendarCourseCell/CalendarCourseCell';
|
||||||
/* import calIcon from 'src/assets/icons/cal.svg';
|
/* import calIcon from 'src/assets/icons/cal.svg';
|
||||||
@@ -10,6 +11,7 @@ import pngIcon from 'src/assets/icons/png.svg';
|
|||||||
import CalendarCell from '../CalendarGridCell/CalendarGridCell';
|
import CalendarCell from '../CalendarGridCell/CalendarGridCell';
|
||||||
import styles from './CalendarGrid.module.scss';
|
import styles from './CalendarGrid.module.scss';
|
||||||
|
|
||||||
|
|
||||||
/* const daysOfWeek = Object.keys(DAY_MAP).filter(key => !['S', 'SU'].includes(key));
|
/* const daysOfWeek = Object.keys(DAY_MAP).filter(key => !['S', 'SU'].includes(key));
|
||||||
const hoursOfDay = Array.from({ length: 14 }, (_, index) => index + 8);
|
const hoursOfDay = Array.from({ length: 14 }, (_, index) => index + 8);
|
||||||
const grid = [];
|
const grid = [];
|
||||||
@@ -108,7 +110,7 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
|
|||||||
newGrid.push(row);
|
newGrid.push(row);
|
||||||
}
|
}
|
||||||
setGrid(newGrid);
|
setGrid(newGrid);
|
||||||
}, [hoursOfDay]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.calendarGrid}>
|
<div className={styles.calendarGrid}>
|
||||||
@@ -204,6 +206,7 @@ function AccountForCourseConflicts({ courseCells }: AccountForCourseConflictsPro
|
|||||||
timeAndLocation={block.componentProps.timeAndLocation}
|
timeAndLocation={block.componentProps.timeAndLocation}
|
||||||
status={block.componentProps.status}
|
status={block.componentProps.status}
|
||||||
colors={block.componentProps.colors}
|
colors={block.componentProps.colors}
|
||||||
|
popup={<CourseCatalogInjectedPopup course={block.popupProps.course} activeSchedule={block.popupProps.activeSchedule} onClose={block.popupProps.onClose} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
import { Status } from '@shared/types/Course';
|
|
||||||
import { Button } from '@views/components/common/Button/Button';
|
|
||||||
import CourseStatus from '@views/components/common/CourseStatus/CourseStatus';
|
|
||||||
import Divider from '@views/components/common/Divider/Divider';
|
|
||||||
import ScheduleTotalHoursAndCourses from '@views/components/common/ScheduleTotalHoursAndCourses/ScheduleTotalHoursAndCourses';
|
|
||||||
import Text from '@views/components/common/Text/Text';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import calIcon from 'src/assets/logo.png';
|
import { Status } from '@shared/types/Course';
|
||||||
|
import Divider from '../../common/Divider/Divider';
|
||||||
|
import { Button } from '../../common/Button/Button';
|
||||||
|
import Text from '../../common/Text/Text';
|
||||||
import MenuIcon from '~icons/material-symbols/menu';
|
import MenuIcon from '~icons/material-symbols/menu';
|
||||||
|
import UndoIcon from '~icons/material-symbols/undo';
|
||||||
import RedoIcon from '~icons/material-symbols/redo';
|
import RedoIcon from '~icons/material-symbols/redo';
|
||||||
import SettingsIcon from '~icons/material-symbols/settings';
|
import SettingsIcon from '~icons/material-symbols/settings';
|
||||||
import UndoIcon from '~icons/material-symbols/undo';
|
import ScheduleTotalHoursAndCourses from '../../common/ScheduleTotalHoursAndCourses/ScheduleTotalHoursAndCourses';
|
||||||
|
import CourseStatus from '../../common/CourseStatus/CourseStatus';
|
||||||
|
import calIcon from 'src/assets/logo.png';
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the header component for the calendar.
|
|
||||||
* @returns The CalendarHeader component.
|
|
||||||
*/
|
|
||||||
const CalendarHeader = () => (
|
const CalendarHeader = () => (
|
||||||
<div className='min-h-79px min-w-672px flex px-0 py-15'>
|
<div className='min-h-79px min-w-672px flex px-0 py-15'>
|
||||||
<div className='flex flex-row gap-20'>
|
<div className='flex flex-row gap-20'>
|
||||||
@@ -23,9 +18,9 @@ const CalendarHeader = () => (
|
|||||||
<div className='flex gap-1'>
|
<div className='flex gap-1'>
|
||||||
<Button variant='single' icon={MenuIcon} color='ut-gray' />
|
<Button variant='single' icon={MenuIcon} color='ut-gray' />
|
||||||
<div className='flex items-center'>
|
<div className='flex items-center'>
|
||||||
<img src={calIcon} className='max-w-[48px] min-w-[48px]' alt='UT Registration Plus Logo' />
|
<img src={calIcon} className='min-w-[48px] max-w-[48px]' alt='UT Registration Plus Logo' />
|
||||||
<div className='flex flex-col whitespace-nowrap'>
|
<div className='flex flex-col whitespace-nowrap'>
|
||||||
<Text className='leading-trim font-roboto text-cap text-base text-ut-burntorange font-medium'>
|
<Text className='leading-trim text-cap font-roboto text-base text-ut-burntorange font-medium'>
|
||||||
UT Registration
|
UT Registration
|
||||||
</Text>
|
</Text>
|
||||||
<Text className='leading-trim text-cap font-roboto text-base text-ut-orange font-medium'>
|
<Text className='leading-trim text-cap font-roboto text-base text-ut-orange font-medium'>
|
||||||
@@ -52,7 +47,7 @@ const CalendarHeader = () => (
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Divider orientation='horizontal' size='width' />
|
<Divider type='solid' />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,16 @@
|
|||||||
import type { UserSchedule } from '@shared/types/UserSchedule';
|
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||||
import List from '@views/components/common/List/List';
|
|
||||||
import ScheduleListItem from '@views/components/common/ScheduleListItem/ScheduleListItem';
|
|
||||||
import Text from '@views/components/common/Text/Text';
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import AddSchedule from '~icons/material-symbols/add';
|
import AddSchedule from '~icons/material-symbols/add';
|
||||||
|
import List from '../../common/List/List';
|
||||||
|
import ScheduleListItem from '../../common/ScheduleListItem/ScheduleListItem';
|
||||||
|
import Text from '../../common/Text/Text';
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the CalendarSchedules component.
|
|
||||||
*/
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
dummySchedules?: UserSchedule[];
|
dummySchedules?: UserSchedule[];
|
||||||
dummyActiveIndex?: number;
|
dummyActiveIndex?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a component that displays a list of schedules.
|
|
||||||
*
|
|
||||||
* @param props - The component props.
|
|
||||||
* @returns The rendered component.
|
|
||||||
*/
|
|
||||||
export function CalendarSchedules(props: Props) {
|
export function CalendarSchedules(props: Props) {
|
||||||
const [activeScheduleIndex, setActiveScheduleIndex] = useState(props.dummyActiveIndex || 0);
|
const [activeScheduleIndex, setActiveScheduleIndex] = useState(props.dummyActiveIndex || 0);
|
||||||
const [schedules, setSchedules] = useState(props.dummySchedules || []);
|
const [schedules, setSchedules] = useState(props.dummySchedules || []);
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import clsx from 'clsx';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
import OutwardArrowIcon from '~icons/material-symbols/arrow-outward';
|
|
||||||
|
|
||||||
import Text from '../common/Text/Text';
|
import Text from '../common/Text/Text';
|
||||||
|
import OutwardArrowIcon from '~icons/material-symbols/arrow-outward';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import type IconComponent from '~icons/material-symbols';
|
import type IconComponent from '~icons/material-symbols';
|
||||||
|
import { ThemeColor, getThemeColorHexByName, getThemeColorRgbByName } from '../../../../shared/util/themeColors';
|
||||||
import type { ThemeColor } from '../../../../shared/util/themeColors';
|
|
||||||
import { getThemeColorHexByName, getThemeColorRgbByName } from '../../../../shared/util/themeColors';
|
|
||||||
import Text from '../Text/Text';
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import styles from './Card.module.scss';
|
import styles from './Card.module.scss';
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the Card component.
|
|
||||||
*/
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Text from '../Text/Text';
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import clsx from 'clsx';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { Course } from 'src/shared/types/Course';
|
import { Course } from 'src/shared/types/Course';
|
||||||
|
import clsx from 'clsx';
|
||||||
import Text from '../Text/Text';
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +28,9 @@ export default function ConflictsWithWarning({ className, conflicts }: Conflicts
|
|||||||
>
|
>
|
||||||
<div>Conflicts With:</div>
|
<div>Conflicts With:</div>
|
||||||
{conflicts.map(course => (
|
{conflicts.map(course => (
|
||||||
<div>{`${course.department} ${course.number} (${course.uniqueId})`}</div>
|
<div>
|
||||||
|
{`${course.department} ${course.number} (${course.uniqueId})`}
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import type { Status } from '@shared/types/Course';
|
import { Status } from '@shared/types/Course';
|
||||||
import { StatusIcon } from '@shared/util/icons';
|
import { StatusIcon } from '@shared/util/icons';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Text from '../Text/Text';
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
type SizeType = 'small' | 'mini';
|
type SizeType = 'small' | 'mini';
|
||||||
|
|||||||
5
src/views/components/common/Divider/Divider.module.scss
Normal file
5
src/views/components/common/Divider/Divider.module.scss
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@use 'src/views/styles/colors.module.scss';
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 1px solid colors.$limestone;
|
||||||
|
}
|
||||||
@@ -1,48 +1,25 @@
|
|||||||
import type { Color } from '@views/styles/colors.module.scss';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Color } from '@views/styles/colors.module.scss';
|
||||||
|
import styles from './Divider.module.scss';
|
||||||
|
|
||||||
/**
|
export type Props = {
|
||||||
* Props for the Divider component
|
color?: Color | React.CSSProperties['borderColor'];
|
||||||
*
|
type?: 'solid' | 'dashed' | 'dotted';
|
||||||
* @param orientation - Orientation of the divider (horizontal or vertical)
|
style?: React.CSSProperties;
|
||||||
* @param size - Size of the divider (forwards to width or height in CSS)
|
|
||||||
* @param className - Additional classes to be added to the divider
|
|
||||||
* @param testId - Test id for the divider
|
|
||||||
*/
|
|
||||||
export type DividerProps = {
|
|
||||||
orientation: 'horizontal' | 'vertical';
|
|
||||||
size: React.CSSProperties['width' | 'height'];
|
|
||||||
className?: string;
|
className?: string;
|
||||||
testId?: string;
|
testId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a reusable divider component that can be used to separate content
|
* This is a reusable divider component that can be used to separate content
|
||||||
*
|
|
||||||
* @returns A divider component
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```tsx
|
|
||||||
* <Divider size="2.5rem" orientation="vertical" />
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```tsx
|
|
||||||
* <Divider size="19px" orientation="horizontal" />
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
export default function Divider({ className, testId, size, orientation }: DividerProps) {
|
export default function Divider(props: Props) {
|
||||||
const style: React.CSSProperties =
|
const style = {
|
||||||
orientation === 'horizontal'
|
...props.style,
|
||||||
? { width: size, borderBottomWidth: '1px' }
|
borderColor: props.color,
|
||||||
: { height: size, borderRightWidth: '1px' };
|
borderStyle: props.type,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return <hr data-testid={props.testId} style={style} className={clsx(styles.divider, props.className)} />;
|
||||||
<div
|
|
||||||
style={style}
|
|
||||||
data-testid={testId}
|
|
||||||
className={clsx('border-solid border-ut-offwhite w-0 h-0', className)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
import { Disclosure, Transition } from '@headlessui/react';
|
import { Disclosure, Transition } from '@headlessui/react';
|
||||||
import type { UserSchedule } from '@shared/types/UserSchedule';
|
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||||
import List from '@views/components/common/List/List';
|
|
||||||
import Text from '@views/components/common/Text/Text';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import userScheduleHandler from 'src/pages/background/handler/userScheduleHandler';
|
import userScheduleHandler from 'src/pages/background/handler/userScheduleHandler';
|
||||||
|
|
||||||
import DropdownArrowDown from '~icons/material-symbols/arrow-drop-down';
|
import DropdownArrowDown from '~icons/material-symbols/arrow-drop-down';
|
||||||
import DropdownArrowUp from '~icons/material-symbols/arrow-drop-up';
|
import DropdownArrowUp from '~icons/material-symbols/arrow-drop-up';
|
||||||
|
import List from '../List/List';
|
||||||
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the Dropdown component.
|
|
||||||
*/
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
// Dummy value solely for storybook
|
// Dummy value solely for storybook
|
||||||
@@ -66,7 +62,7 @@ export default function Dropdown(props: Props) {
|
|||||||
<Disclosure.Button>
|
<Disclosure.Button>
|
||||||
<div className='flex items-center border-none bg-white p-3 text-left'>
|
<div className='flex items-center border-none bg-white p-3 text-left'>
|
||||||
<div className='flex-1'>
|
<div className='flex-1'>
|
||||||
<Text as='div' variant='h4' className='mb-1 w-100% text-ut-burntorange'>
|
<Text as='div' variant='h4' className='text-ut-burntorange mb-1 w-100%'>
|
||||||
MAIN SCHEDULE:
|
MAIN SCHEDULE:
|
||||||
</Text>
|
</Text>
|
||||||
<div>
|
<div>
|
||||||
@@ -78,7 +74,7 @@ export default function Dropdown(props: Props) {
|
|||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Text className='text-2xl text-ut-burntorange font-normal'>
|
<Text className='text-ut-burntorange text-2xl font-normal'>
|
||||||
{expanded ? <DropdownArrowDown /> : <DropdownArrowUp />}
|
{expanded ? <DropdownArrowDown /> : <DropdownArrowUp />}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styles from './ExtensionRoot.module.scss';
|
||||||
|
|
||||||
import '@unocss/reset/tailwind-compat.css';
|
import '@unocss/reset/tailwind-compat.css';
|
||||||
import 'uno.css';
|
import 'uno.css';
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import styles from './ExtensionRoot.module.scss';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
testId?: string;
|
testId?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import type { Color } from '@views/styles/colors.module.scss';
|
|
||||||
import colors from '@views/styles/colors.module.scss';
|
|
||||||
import type { Size } from '@views/styles/fonts.module.scss';
|
|
||||||
import fonts from '@views/styles/fonts.module.scss';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import colors, { Color } from '@views/styles/colors.module.scss';
|
||||||
|
import fonts, { Size } from '@views/styles/fonts.module.scss';
|
||||||
import styles from './Icon.module.scss';
|
import styles from './Icon.module.scss';
|
||||||
import type { MaterialIconCode } from './MaterialIcons';
|
import { MaterialIconCode } from './MaterialIcons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2194,7 +2194,4 @@ const icons = [
|
|||||||
'zoom_out_map',
|
'zoom_out_map',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
/**
|
export type MaterialIconCode = typeof icons[number];
|
||||||
* Represents a type that corresponds to a material icon code.
|
|
||||||
*/
|
|
||||||
export type MaterialIconCode = (typeof icons)[number];
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Text from '../Text/Text';
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -11,35 +10,31 @@ interface Props {
|
|||||||
* A maybe reusable InfoCard component that follows the design system of the extension.
|
* A maybe reusable InfoCard component that follows the design system of the extension.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function InfoCard({ titleText, bodyText }: React.PropsWithChildren<Props>): JSX.Element {
|
export function InfoCard({
|
||||||
|
titleText,
|
||||||
|
bodyText
|
||||||
|
}: React.PropsWithChildren<Props>): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='w-50 flex flex-col items-start justify-center border rounded p-4'
|
className = 'w-50 flex flex-col items-start justify-center border rounded p-4'
|
||||||
style={{
|
style = {{
|
||||||
border: '1px solid #D6D2C4',
|
border: "1px solid #D6D2C4",
|
||||||
background: '#FFF', // White
|
background: "#FFF" // White
|
||||||
}}
|
}}>
|
||||||
>
|
<div className="flex flex-col items-start self-stretch gap-1.5">
|
||||||
<div className='flex flex-col items-start self-stretch gap-1.5'>
|
<Text variant = "h4" as = 'span'
|
||||||
<Text
|
style = {{
|
||||||
variant='h4'
|
color: '#F8971F', // Orange
|
||||||
as='span'
|
}}>
|
||||||
style={{
|
{titleText}
|
||||||
color: '#F8971F', // Orange
|
</Text>
|
||||||
}}
|
<Text variant = "small" as = 'span'
|
||||||
>
|
style = {{
|
||||||
{titleText}
|
color: '#333F48', // Black
|
||||||
</Text>
|
}}>
|
||||||
<Text
|
{bodyText}
|
||||||
variant='small'
|
</Text>
|
||||||
as='span'
|
</ div>
|
||||||
style={{
|
|
||||||
color: '#333F48', // Black
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{bodyText}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import { background } from '@shared/messages';
|
import { background } from '@shared/messages';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import type { PropsWithChildren } from 'react';
|
import React, { PropsWithChildren } from 'react';
|
||||||
import React from 'react';
|
import Text, { TextProps } from '../Text/Text';
|
||||||
|
|
||||||
import type { TextProps } from '../Text/Text';
|
|
||||||
import Text from '../Text/Text';
|
|
||||||
import styles from './Link.module.scss';
|
import styles from './Link.module.scss';
|
||||||
|
|
||||||
type Props = Omit<TextProps, 'span'> & {
|
type Props = Omit<TextProps, 'span'> & {
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import type { Course } from '@shared/types/Course';
|
import { Course, Status } from '@shared/types/Course';
|
||||||
import { Status } from '@shared/types/Course';
|
import { CourseColors, pickFontColor } from '@shared/util/colors';
|
||||||
import type { CourseColors } from '@shared/util/colors';
|
|
||||||
import { pickFontColor } from '@shared/util/colors';
|
|
||||||
import { StatusIcon } from '@shared/util/icons';
|
import { StatusIcon } from '@shared/util/icons';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import DragIndicatorIcon from '~icons/material-symbols/drag-indicator';
|
import DragIndicatorIcon from '~icons/material-symbols/drag-indicator';
|
||||||
|
|
||||||
import Text from '../Text/Text';
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import Text from '@views/components/common/Text/Text';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import DragIndicatorIcon from '~icons/material-symbols/drag-indicator';
|
import DragIndicatorIcon from '~icons/material-symbols/drag-indicator';
|
||||||
|
import Text from '../Text/Text';
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the ScheduleListItem component.
|
|
||||||
*/
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
@@ -22,11 +18,11 @@ export default function ScheduleListItem(props: Props) {
|
|||||||
console.log(props);
|
console.log(props);
|
||||||
return (
|
return (
|
||||||
<div style={{ ...props.style }} className='items-center'>
|
<div style={{ ...props.style }} className='items-center'>
|
||||||
<li className='w-100% flex cursor-pointer items-center self-stretch justify-left text-ut-burntorange'>
|
<li className='text-ut-burntorange w-100% flex cursor-pointer items-center self-stretch justify-left'>
|
||||||
<div className='group flex justify-center'>
|
<div className='group flex justify-center'>
|
||||||
<div
|
<div
|
||||||
className='flex cursor-move items-center self-stretch rounded rounded-r-0'
|
className='flex cursor-move items-center self-stretch rounded rounded-r-0'
|
||||||
{...dragHandleProps}
|
{...dragHandleProps}
|
||||||
>
|
>
|
||||||
<DragIndicatorIcon className='h-6 w-6 cursor-move text-zinc-300 btn-transition -ml-1.5 hover:text-zinc-400' />
|
<DragIndicatorIcon className='h-6 w-6 cursor-move text-zinc-300 btn-transition -ml-1.5 hover:text-zinc-400' />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user