Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# should be updated accordingly.

# General
BASE_URL=http://localhost:3000
NEURON_BASE_URL=http://localhost:3000

# Drizzle
DATABASE_PASSWORD="password" # Generate from ./gen-pass.sh
Expand Down
2 changes: 1 addition & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# General
NODE_ENV=test
BASE_URL="http://localhost:3000"
NEURON_BASE_URL=http://localhost:3000

# Test Database (same host, different database name)
DATABASE_PASSWORD="0d9aQECGfwiKdFDL"
Expand Down
14 changes: 12 additions & 2 deletions src/app/(authorized)/classes/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
"use client";

import { ClassListView } from "@/components/classes/list/class-list-view";
import { PageLayout } from "@/components/page-layout";
import { parseAsString, useQueryState } from "nuqs";

export default function ClassesPage() {
const [classId, setClassId] = useQueryState("classId", parseAsString);

return (
<PageLayout>
<ClassListView />
<PageLayout
open={!!classId}
onOpenChange={(open) => {
if (!open) setClassId(null);
}}
>
<ClassListView classId={classId} setClassId={setClassId} />
</PageLayout>
);
}
22 changes: 17 additions & 5 deletions src/app/(authorized)/coverage/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,27 @@ import { Suspense } from "react";
import { CoveragePageProvider } from "@/components/coverage/list/coverage-page-context";
import { CoverageAside } from "@/components/coverage/list/coverage-aside";
import { SkeletonAside } from "@/components/ui/skeleton";
import { parseAsString, useQueryState } from "nuqs";

export default function CoveragePage() {
const [coverageId, setCoverageId] = useQueryState(
"coverageId",
parseAsString,
);

return (
<PageLayout>
<CoveragePageProvider>
<PageLayout
open={!!coverageId}
onOpenChange={(open) => {
if (!open) setCoverageId(null);
}}
>
<CoveragePageProvider
coverageId={coverageId}
setCoverageId={setCoverageId}
>
<PageLayoutAside>
<Suspense fallback={<SkeletonAside />}>
<CoverageAside />
</Suspense>
<CoverageAside />
</PageLayoutAside>

<PageLayoutHeader hideShadow border="always">
Expand Down
16 changes: 10 additions & 6 deletions src/app/(authorized)/schedule/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import { SchedulePageControls } from "@/components/schedule/schedule-page-controls";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { cn } from "@/lib/utils";
import { parseAsStringEnum, useQueryState } from "nuqs";
import { parseAsString, parseAsStringEnum, useQueryState } from "nuqs";
import { Activity, Suspense } from "react";
import { SchedulePageProvider } from "../../../components/schedule/schedule-page-context";
import { ShiftDetailsAside } from "../../../components/schedule/shift-details-aside";
Expand All @@ -29,11 +29,17 @@ export default function SchedulePage() {
.withDefault("list")
.withOptions({ clearOnDefault: false }),
);
const [shiftId, setShiftId] = useQueryState("shiftId", parseAsString);

return (
<PageLayout>
<PageLayout
open={!!shiftId}
onOpenChange={(open) => {
if (!open) setShiftId(null);
}}
>
<FullCalendarProvider>
<SchedulePageProvider>
<SchedulePageProvider shiftId={shiftId} setShiftId={setShiftId}>
<PageLayoutHeader hideShadow border="always">
<PageLayoutHeaderContent className="items-center">
<PageLayoutHeaderTitle>Schedule</PageLayoutHeaderTitle>
Expand All @@ -58,9 +64,7 @@ export default function SchedulePage() {
</PageLayoutHeader>

<PageLayoutAside>
<Suspense fallback={<SkeletonAside />}>
<ShiftDetailsAside />
</Suspense>
<ShiftDetailsAside />
</PageLayoutAside>

<PageLayoutContent className="flex-1">
Expand Down
1 change: 1 addition & 0 deletions src/app/(authorized)/schedule/schedule-calendar-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function ScheduleCalendarView() {

return (
<FullCalendar
initialDate={selectedDate}
eventClick={handleEventClick}
events={scheduleShifts.map((shift) => ({
id: shift.id,
Expand Down
11 changes: 2 additions & 9 deletions src/components/classes/list/class-details-aside.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { DeleteClassButton } from "../primitives/delete-class-button";
import { PublishClassButton } from "../primitives/publish-class-button";
import { StarClassButton } from "../primitives/star-class-button";
import { UserList } from "@/components/users/user-list";
import { SkeletonAside } from "@/components/ui/skeleton";

export function ClassDetailsAside() {
const { selectedClassId, closeAside } = useClassesPage();
Expand All @@ -42,18 +43,10 @@ export function ClassDetailsAside() {
{ classId: selectedClassId ?? "" },
{
enabled: !!selectedClassId,
suspense: !!selectedClassId,
meta: { suppressToast: true },
},
);

// Close aside if no shiftId is selected
useEffect(() => {
if (!selectedClassId) {
closeAside();
}
}, [selectedClassId, closeAside]);

const scheduleViews = useMemo(() => {
return (classData?.schedules ?? []).map((s) => ({
id: s.id,
Expand All @@ -75,7 +68,7 @@ export function ClassDetailsAside() {
}, [classData?.schedules]);

if (isLoadingClassData || !classData) {
return <></>;
return <SkeletonAside />;
}

return (
Expand Down
42 changes: 28 additions & 14 deletions src/components/classes/list/class-list-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
PageLayoutHeader,
PageLayoutHeaderContent,
PageLayoutHeaderTitle,
usePageAside,
} from "@/components/page-layout";
import { ClassList } from "./content/class-list";
import { ClassListSkeleton } from "./class-list-skeleton";
Expand Down Expand Up @@ -57,10 +56,13 @@ export function useClassesPage() {
return ctx;
}

export function ClassListView() {
const { setOpen } = usePageAside();
type ClassListViewProps = {
classId: string | null;
setClassId: (id: string | null) => Promise<URLSearchParams>;
};

export function ClassListView({ classId, setClassId }: ClassListViewProps) {
const contentScrollRef = useRef<HTMLDivElement>(null);
const [selectedClassId, setSelectedClassId] = useState<string | null>(null);
const [selectedTermId, setSelectedTermId] = useState<string | null>(null);
const [queryTerm, setQueryTerm] = useQueryState(
"term",
Expand All @@ -69,16 +71,28 @@ export function ClassListView() {

const openAsideFor = useCallback(
(id: string) => {
setSelectedClassId(id);
setOpen(true);
setClassId(id);
},
[setOpen, setSelectedClassId],
[setClassId],
);

const closeAside = useCallback(() => {
setSelectedClassId(null);
setOpen(false);
}, [setOpen, setSelectedClassId]);
setClassId(null);
}, [setClassId]);

// When a classId is present (e.g. from URL), fetch the class and navigate
// to its term so the list shows the correct term's classes.
const { data: linkedClass } = clientApi.class.byId.useQuery(
{ classId: classId ?? "" },
{ enabled: !!classId },
);

useEffect(() => {
if (linkedClass?.termId && linkedClass.termId !== selectedTermId) {
setSelectedTermId(linkedClass.termId);
void setQueryTerm(linkedClass.termId);
}
}, [linkedClass?.termId, selectedTermId, setQueryTerm]);

const canCreateTerm = usePermission({ permission: { terms: ["create"] } });

Expand Down Expand Up @@ -139,22 +153,22 @@ export function ClassListView() {

const contextValue = useMemo(
() => ({
selectedClassId,
selectedClassId: classId,
selectedTermId,
queryTerm,
hasTerms,
setSelectedClassId,
setSelectedClassId: setClassId,
setSelectedTermId: handleSelectTerm,
openAsideFor,
closeAside,
contentScrollRef,
}),
[
selectedClassId,
classId,
selectedTermId,
queryTerm,
hasTerms,
setSelectedClassId,
setClassId,
handleSelectTerm,
openAsideFor,
closeAside,
Expand Down
Loading