Skip to content

Commit

Permalink
start work on roads
Browse files Browse the repository at this point in the history
  • Loading branch information
dtemkin1 committed Jan 6, 2025
1 parent 96c4aaf commit 18ff916
Show file tree
Hide file tree
Showing 9 changed files with 607 additions and 414 deletions.
9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@
"@solidjs/testing-library": "^0.8.10",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/user-event": "^14.5.2",
"@types/node": "^22.10.3",
"@types/node": "^22.10.5",
"jsdom": "^25.0.1",
"postcss": "^8.4.49",
"solid-devtools": "^0.33.0",
"typescript": "^5.7.2",
"typescript-eslint": "^8.19.0",
"typescript-eslint": "^8.19.1",
"vitest": "^2.1.8"
},
"bugs": {
Expand All @@ -65,8 +65,5 @@
"url": "git+https://github.com/sipb/courseroad3.git"
},
"license": "MIT",
"keywords": [
"mit",
"courseroad"
]
"keywords": ["mit", "courseroad"]
}
534 changes: 273 additions & 261 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

59 changes: 31 additions & 28 deletions src/components/About.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,52 @@
import type { Component } from "solid-js";

import { XIcon } from "lucide-solid";
import { Portal } from "solid-js/web";
import { Stack } from "styled-system/jsx";
import { Button } from "~/components/ui/button";
import { Dialog } from "~/components/ui/dialog";
import { IconButton } from "~/components/ui/icon-button";

const About: Component<Dialog.RootProps> = (props) => {
return (
<Dialog.Root {...props}>
<Dialog.Root lazyMount unmountOnExit {...props}>
<Dialog.Trigger
asChild={(triggerProps) => (
<Button variant="link" {...triggerProps()}>
About CourseRoad
</Button>
)}
/>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Stack gap="8" p="6">
<Stack gap="1">
<Dialog.Title>About CourseRoad</Dialog.Title>
<Dialog.Description>
CourseRoad description will go here...
</Dialog.Description>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Stack gap="8" p="6">
<Stack gap="1">
<Dialog.Title>About CourseRoad</Dialog.Title>
<Dialog.Description>
CourseRoad description will go here...
</Dialog.Description>
</Stack>
</Stack>
</Stack>
<Dialog.CloseTrigger
asChild={(closeTriggerProps) => (
<IconButton
{...closeTriggerProps()}
aria-label="Close Dialog"
variant="ghost"
size="sm"
position="absolute"
top="2"
right="2"
>
<XIcon />
</IconButton>
)}
/>
</Dialog.Content>
</Dialog.Positioner>
<Dialog.CloseTrigger
asChild={(closeTriggerProps) => (
<IconButton
{...closeTriggerProps()}
aria-label="Close Dialog"
variant="ghost"
size="sm"
position="absolute"
top="2"
right="2"
>
<XIcon />
</IconButton>
)}
/>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
);
};
Expand Down
3 changes: 3 additions & 0 deletions src/components/Auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ export type AuthRef = {
setNewRoads: (newRoads: string[]) => void;
save: (roadID: string) => void;
gettingUserData: boolean;
changeSemester: (year: number) => void;
}): void;
deleteRoad: (roadName: string) => void;
retrieveRoad: (roadID: string) => Promise<RoadResponse | undefined>;
newRoads: string[];
setNewRoads: (newRoads: string[]) => void;
save: (roadID: string) => void;
gettingUserData: boolean;
changeSemester: (year: number) => void;
};

const Auth: Component<{
Expand Down Expand Up @@ -862,6 +864,7 @@ const Auth: Component<{
gettingUserData: gettingUserData(),
setNewRoads: setNewRoadsRef,
save,
changeSemester,
});

return (
Expand Down
208 changes: 162 additions & 46 deletions src/components/Road.tsx
Original file line number Diff line number Diff line change
@@ -1,71 +1,187 @@
import { cookieStorage, makePersisted } from "@solid-primitives/storage";
import type { Component } from "solid-js";
import { For, createSignal } from "solid-js";
import { For, Index, Show, createMemo, createSignal } from "solid-js";

import { ChevronDownIcon } from "lucide-solid";
import { useAccordion } from "@ark-ui/solid";
import {
BanIcon,
CheckIcon,
ChevronDownIcon,
ChevronsUpDownIcon,
XIcon,
} from "lucide-solid";
import { Stack } from "styled-system/jsx";
import Semester from "~/components/Semester";
import { Accordion } from "~/components/ui/accordion";
import { Button } from "~/components/ui/button";
import { Dialog } from "~/components/ui/dialog";
import { IconButton } from "~/components/ui/icon-button";
import { Select, createListCollection } from "~/components/ui/select";
import { Switch } from "~/components/ui/switch";

import { useCourseDataContext } from "~/context/create";
import type { SimplifiedSelectedSubjects } from "~/context/types";

const Road: Component<{
selectedSubjects: Array<SimplifiedSelectedSubjects[0]>;
roadID: string;
addingFromCard: boolean;
dragSemesterNum: number;
changeYear: (year: number) => void;
}> = (props) => {
const defaultOpen = [
false,
true,
false,
true,
true,
false,
true,
true,
false,
true,
true,
false,
true,
];
const [store, { getUserYear, setHideIAP }] = useCourseDataContext();

const defaultOpenValues = defaultOpen
.reduce(
(out, bool, index) => (bool ? out.concat(index) : out),
[] as number[],
)
.map((index) => index.toString());
const defaultOpen = ["1", "3", "4", "6", "7", "9", "10", "12"];
const numSemesters = 16;

const [visibleList, setVisibleList] = createSignal(
(numSemesters >= 13
? defaultOpen.concat([true, false, true])
: defaultOpen
).reduce(
(out, bool, index) => (bool ? out.concat(index) : out),
[] as number[],
const [visibleList, setVisibleList] = makePersisted(
createSignal(
numSemesters >= 13 ? defaultOpen.concat(["13", "15"]) : defaultOpen,
),
{
storage: store.cookiesAllowed
? cookieStorage.withOptions({ path: "/" })
: undefined,
name: `visibleList${props.roadID}`,
},
);
const [openRoadSettings, setOpenRoadSettings] = createSignal(false);
const [numSems, setNumSems] = createSignal(numSemesters);

const year = createMemo(() => getUserYear());
const hideIAP = createMemo(() => store.hideIAP);

const accordion = useAccordion({
value: visibleList(),
onValueChange: (e) => setVisibleList(e.value),
multiple: true,
});
const yearCollection = createListCollection({
items: [
{ value: "0", label: "First Year/Freshman" },
{ value: "1", label: "Sophomore" },
{ value: "2", label: "Junior" },
{ value: "3", label: "Senior" },
{ value: "4", label: "Super Senior" },
],
});

return (
<Accordion.Root multiple defaultValue={defaultOpenValues}>
<For each={[...Array(numSems()).keys()]}>
{(index) => (
<Accordion.Item value={index.toString()}>
<Accordion.ItemTrigger>
{index}
<Accordion.ItemIndicator>
<ChevronDownIcon />
</Accordion.ItemIndicator>
</Accordion.ItemTrigger>
<Accordion.ItemContent>
Classes go here for semester {index} in road {props.roadID}
</Accordion.ItemContent>
</Accordion.Item>
<Accordion.RootProvider lazyMount unmountOnExit value={accordion}>
<Index each={[...Array(numSems()).keys()]}>
{(item) => (
<Semester
index={item()}
selectedSubjects={props.selectedSubjects}
semesterSubjects={props.selectedSubjects[item()]}
roadID={props.roadID}
isOpen={visibleList().includes(`${item()}`)}
hideIap={hideIAP()}
openRoadSettingsDialog={() => setOpenRoadSettings(true)}
/>
)}
</For>
</Accordion.Root>
</Index>
<Show when={props.addingFromCard}>
<IconButton display="fixed" bottom="2rem" right="2rem">
<BanIcon />
</IconButton>
</Show>
<Dialog.Root
lazyMount
unmountOnExit
open={openRoadSettings()}
onOpenChange={(e) => setOpenRoadSettings(e.open)}
>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Stack gap="8" p="6">
<Dialog.Title>Road Settings</Dialog.Title>

<Select.Root
positioning={{ sameWidth: true }}
width="2xs"
collection={yearCollection}
value={[`${year()}`]}
onValueChange={(e) =>
props.changeYear(Number.parseInt(e.value[0]))
}
>
<Select.Label>I am a...</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Year" />
<ChevronsUpDownIcon />
</Select.Trigger>
</Select.Control>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<For each={yearCollection.items}>
{(item) => (
<Select.Item item={item}>
<Select.ItemText>{item.label}</Select.ItemText>
<Select.ItemIndicator>
<CheckIcon />
</Select.ItemIndicator>
</Select.Item>
)}
</For>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Select.Root>

<Switch
checked={hideIAP()}
onCheckedChange={(e) => setHideIAP(e.checked)}
>
Hide IAP
</Switch>

<Stack
gap="3"
direction="row"
width="full"
justifyContent="flex-end"
>
<Button
variant="outline"
onClick={() => {
setOpenRoadSettings(false);
}}
>
Cancel
</Button>
<Button
onClick={() => {
props.changeYear(year());
setOpenRoadSettings(false);
}}
>
Submit
</Button>
</Stack>
</Stack>
<Dialog.CloseTrigger
asChild={(closeTriggerProps) => (
<IconButton
{...closeTriggerProps()}
aria-label="Close Dialog"
variant="ghost"
size="sm"
position="absolute"
top="2"
right="2"
>
<XIcon />
</IconButton>
)}
/>
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>
</Accordion.RootProvider>
);
};

Expand Down
Loading

0 comments on commit 18ff916

Please sign in to comment.