Skip to content

Commit

Permalink
Merge pull request #69 from hackerspace-ntnu/shift-schedule-page
Browse files Browse the repository at this point in the history
feat: Shift schedule page
  • Loading branch information
michaelbrusegard authored Nov 7, 2024
2 parents 4560e47 + 08d0705 commit 391d283
Show file tree
Hide file tree
Showing 17 changed files with 718 additions and 0 deletions.
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions lighthouserc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const config = {
'http://localhost:3000/en/news/1',
'http://localhost:3000/en/storage',
'http://localhost:3000/en/storage/shopping-cart',
'http://localhost:3000/en/shift-schedule',
],
startServerCommand: 'bun run start',
},
Expand Down
24 changes: 24 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"events": "Events",
"storage": "Storage",
"about": "About",
"shiftSchedule": "Shift Schedule",
"changeLocale": "Change language",
"toggleTheme": "Toggle theme",
"light": "Light",
Expand Down Expand Up @@ -132,5 +133,28 @@
"returnByDescription": "Select how long you would like to borrow the item for.",
"submit": "Submit"
}
},
"shiftSchedule": {
"title": "Shift Schedule",
"administratorMenu": {
"label": "Administrator Menu",
"open": "Open Administrator Menu",
"close": "Close Administrator Menu",
"clearShiftSchedule": "Clear shift schedule"
},
"scheduleTable": {
"time": "Time",
"day": "{day, select, monday {Monday} tuesday {Tuesday} wednesday {Wednesday} thursday {Thursday} other {Friday}}",
"scheduleCell": {
"onShift": "{count, plural, =0 {Closed} =1 {1 person on shift} other {# people on shift}}",
"scheduleCellDialog": {
"empty": "No one on shift",
"registerSection": {
"recurring": "Recurring",
"register": "Register"
}
}
}
}
}
}
24 changes: 24 additions & 0 deletions messages/no.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"events": "Hendelser",
"storage": "Lager",
"about": "Om oss",
"shiftSchedule": "Vaktliste",
"changeLocale": "Bytt språk",
"toggleTheme": "Bytt tema",
"light": "Lys",
Expand Down Expand Up @@ -132,5 +133,28 @@
"returnByDescription": "Velg hvor lenge du ønsker å låne gjenstanden(e)",
"submit": "Send"
}
},
"shiftSchedule": {
"title": "Vaktliste",
"administratorMenu": {
"label": "Administrator-meny",
"open": "Åpne Administrator-meny",
"close": "Lukk Administrator-meny",
"clearShiftSchedule": "Tøm vaktliste"
},
"scheduleTable": {
"time": "Tid",
"day": "{day, select, monday {Mandag} tuesday {Tirsdag} wednesday {Onsdag} thursday {Torsdag} other {Fredag}}",
"scheduleCell": {
"onShift": "{count, plural, =0 {Stengt} =1 {1 person på vakt} other {# personer på vakt}}",
"scheduleCellDialog": {
"empty": "Ingen på vakt",
"registerSection": {
"recurring": "Gjentagende",
"register": "Registrer"
}
}
}
}
}
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"@aws-sdk/client-s3": "^3.679.0",
"@lucia-auth/adapter-drizzle": "^1.1.0",
"@radix-ui/react-avatar": "^1.1.1",
"@radix-ui/react-checkbox": "^1.1.2",
"@radix-ui/react-collapsible": "^1.1.1",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.0",
Expand Down
23 changes: 23 additions & 0 deletions src/app/[locale]/(default)/shift-schedule/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { getTranslations, setRequestLocale } from 'next-intl/server';

type ShiftScheduleLayoutProps = {
children: React.ReactNode;
params: Promise<{ locale: string }>;
};

export default async function ShiftScheduleLayout({
params,
children,
}: ShiftScheduleLayoutProps) {
const { locale } = await params;

setRequestLocale(locale);
const t = await getTranslations('shiftSchedule');

return (
<>
<h1 className='text-center'>{t('title')}</h1>
{children}
</>
);
}
126 changes: 126 additions & 0 deletions src/app/[locale]/(default)/shift-schedule/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Skeleton } from '@/components/ui/Skeleton';
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/Table';
import { useFormatter, useTranslations } from 'next-intl';

export default function ShiftScheduleLayout() {
const t = useTranslations('shiftSchedule.scheduleTable');
const format = useFormatter();

const days = [
'monday',
'tuesday',
'wednesday',
'thursday',
'friday',
] as const;
const timeslots = ['first', 'second', 'third', 'fourth'] as const;

function getDateTimeRange(timeslot: string) {
let firstDate: Date;
let secondDate: Date;

switch (timeslot) {
case timeslots[0]:
firstDate = new Date(0, 0, 0, 10, 15, 0, 0);
secondDate = new Date(0, 0, 0, 12, 7, 0, 0);
break;

case timeslots[1]:
firstDate = new Date(0, 0, 0, 12, 7, 0, 0);
secondDate = new Date(0, 0, 0, 14, 7, 0, 0);
break;

case timeslots[2]:
firstDate = new Date(0, 0, 0, 14, 7, 0, 0);
secondDate = new Date(0, 0, 0, 16, 7, 0, 0);
break;

case timeslots[3]:
firstDate = new Date(0, 0, 0, 16, 7, 0, 0);
secondDate = new Date(0, 0, 0, 18, 0, 0, 0);
break;

default:
firstDate = new Date();
secondDate = new Date();
}

return format.dateTimeRange(firstDate, secondDate, {
hour: '2-digit',
minute: '2-digit',
hour12: false,
});
}

return (
<>
{/* Table shown on small screens */}
<div className='sm:hidden [&>div]:mt-8'>
{days.map((day) => (
<Table key={day}>
<TableHeader>
<TableRow>
<TableHead className='w-2/5'>{t('time')}</TableHead>
<TableHead className='w-3/5 border-x'>
{t('day', { day: day })}
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{timeslots.map((timeslot) => (
<TableRow key={timeslot}>
<TableCell className='border-y'>
{getDateTimeRange(timeslot)}
</TableCell>
<TableCell key={day} className='h-20 min-w-52 border p-1.5'>
<Skeleton className='size-full' />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
))}
<Table>
<TableCaption>[skill icons legend]</TableCaption>
</Table>
</div>

{/* Table shown on all other screens */}
<Table className='mt-8 hidden sm:table'>
<TableHeader>
<TableRow>
<TableHead className='w-1/6'>{t('time')}</TableHead>
{days.map((day) => (
<TableHead key={day} className='w-1/6 border-x'>
{t('day', { day: day })}
</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{timeslots.map((timeslot) => (
<TableRow key={timeslot}>
<TableCell className='min-w-32 border-y'>
{getDateTimeRange(timeslot)}
</TableCell>
{days.map((day) => (
<TableCell key={day} className='h-20 min-w-52 border p-1.5'>
<Skeleton className='size-full' />
</TableCell>
))}
</TableRow>
))}
</TableBody>
<TableCaption className='h-12'>[skill icons legend]</TableCaption>
</Table>
</>
);
}
42 changes: 42 additions & 0 deletions src/app/[locale]/(default)/shift-schedule/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { AdministratorMenu } from '@/components/shift-schedule/AdministratorMenu';
import { ScheduleTable } from '@/components/shift-schedule/ScheduleTable';
import { shiftScheduleMockData } from '@/mock-data/shiftSchedule';
import { getTranslations, setRequestLocale } from 'next-intl/server';

export async function generateMetadata({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: 'layout' });

return {
title: t('shiftSchedule'),
};
}

export default async function ShiftSchedulePage({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;

setRequestLocale(locale);
const t = await getTranslations('shiftSchedule');

return (
<>
<AdministratorMenu
t={{
label: t('administratorMenu.label'),
open: t('administratorMenu.open'),
close: t('administratorMenu.close'),
clearShiftSchedule: t('administratorMenu.clearShiftSchedule'),
}}
/>
<ScheduleTable week={shiftScheduleMockData} />
</>
);
}
52 changes: 52 additions & 0 deletions src/components/shift-schedule/AdministratorMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use client';

import { Button } from '@/components/ui/Button';
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from '@/components/ui/Collapsible';
import { ChevronDownIcon, ChevronUpIcon, Trash2Icon } from 'lucide-react';
import { useState } from 'react';

type AdministratorMenuProps = {
t: {
label: string;
open: string;
close: string;
clearShiftSchedule: string;
};
};

function AdministratorMenu({ t }: AdministratorMenuProps) {
const [isOpen, setIsOpen] = useState(false);

return (
<Collapsible
open={isOpen}
onOpenChange={setIsOpen}
className='mx-auto xs:mx-8 mt-8 rounded border p-3'
>
<div className='mx-1 flex justify-between'>
<span className='my-auto font-semibold text-xl'>{t.label}</span>
<CollapsibleTrigger asChild>
<Button variant='ghost' aria-label={isOpen ? t.close : t.open}>
{isOpen ? (
<ChevronUpIcon aria-hidden='true' className='size-4' />
) : (
<ChevronDownIcon aria-hidden='true' className='size-4' />
)}
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent className='mt-2'>
<Button variant='link' className='flex gap-3 text-destructive'>
<Trash2Icon />
{t.clearShiftSchedule}
</Button>
</CollapsibleContent>
</Collapsible>
);
}

export { AdministratorMenu };
23 changes: 23 additions & 0 deletions src/components/shift-schedule/RegisterShift.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Button } from '@/components/ui/Button';
import { Checkbox } from '@/components/ui/Checkbox';
import { Label } from '@/components/ui/Label';
import { cx } from '@/lib/utils';
import { useTranslations } from 'next-intl';

function RegisterShift({ className }: { className?: string }) {
const t = useTranslations(
'shiftSchedule.scheduleTable.scheduleCell.scheduleCellDialog.registerSection',
);

return (
<div className={cx(className, 'space-y-3')}>
<section className='flex gap-2'>
<Label htmlFor='recurring'>{t('recurring')}: </Label>
<Checkbox id='recurring' />
</section>
<Button className='float-right'>{t('register')}</Button>
</div>
);
}

export { RegisterShift };
Loading

0 comments on commit 391d283

Please sign in to comment.