Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rules page #60

Open
wants to merge 22 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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: 2 additions & 0 deletions lighthouserc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const config = {
'http://localhost:3000/en/storage',
'http://localhost:3000/en/storage/shopping-cart',
'http://localhost:3000/en/shift-schedule',
'http://localhost:3000/en/rules',
'http://localhost:3000/en/rules/1',
],
startServerCommand: 'bun run start',
},
Expand Down
6 changes: 6 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"shiftSchedule": "Shift Schedule",
"desktopNavMenu": "{open, select, true {Open} other {Close}} navigation menu",
"goToMatrix": "Go to matrix",
"rules": "Rules",
"changeLocale": "Change language",
"toggleTheme": "Toggle theme",
"light": "Light",
Expand Down Expand Up @@ -228,5 +229,10 @@
"api": {
"tooManyRequests": "Too many requests, please try again later",
"notAuthenticated": "Not authenticated"
},
"rules": {
"title": "Rules",
"forEveryone": "For everyone",
"internal": "Internal rules"
}
}
6 changes: 6 additions & 0 deletions messages/no.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"shiftSchedule": "Vaktliste",
"desktopNavMenu": "{open, select, true {Åpne} other {Lukk}} navigasjonsmeny",
"goToMatrix": "Dra til matrix",
"rules": "Rules",
"changeLocale": "Bytt språk",
"toggleTheme": "Bytt tema",
"light": "Lys",
Expand Down Expand Up @@ -228,5 +229,10 @@
"api": {
"tooManyRequests": "For mange forespørsler. Vennligst vent noen minutter og prøv igjen",
"notAuthenticated": "Ikke autentisert"
},
"rules": {
"title": "Regler",
"forEveryone": "For alle",
"internal": "Interne regler"
}
}
21 changes: 21 additions & 0 deletions src/app/[locale]/(default)/rules/(main)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { getTranslations, setRequestLocale } from 'next-intl/server';

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

export default async function RulesLayout({
children,
params,
}: RulesLayoutProps) {
const { locale } = await params;
setRequestLocale(locale);
const t = await getTranslations('rules');
return (
<>
<h1 className='text-center'>{t('title')}</h1>
{children}
</>
);
}
9 changes: 9 additions & 0 deletions src/app/[locale]/(default)/rules/(main)/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { RuleCardListSkeleton } from '@/components/rules/RuleCardListSkeleton';

export default function RulesSkeleton() {
return (
<div className='mt-1 mb-1'>
<RuleCardListSkeleton />
</div>
);
}
64 changes: 64 additions & 0 deletions src/app/[locale]/(default)/rules/(main)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { RuleCard } from '@/components/rules/RuleCard';
import { rulesMockdata as rules } from '@/mock-data/rules';
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('rules'),
};
}

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

setRequestLocale(locale);
const internal = rules.filter((rule) => rule.internal);
const notInternal = rules.filter((rule) => !rule.internal);
const t = await getTranslations('rules');
const isMember = false;

return (
<div className='flex shrink flex-wrap justify-center p-4 md:flex-nowrap md:space-x-5'>
<div className={isMember ? ' md:w-1/2' : 'mt-2 md:size-full'}>
<h2 className={isMember ? 'border-b-0 p-4 text-center' : 'hidden'}>
{t('forEveryone')}
</h2>
{notInternal.map((rule) => (
<RuleCard
className='mx-auto mb-3 flex max-w-2xl'
key={rule.id}
id={rule.id}
internal={rule.internal}
title={rule.title}
photoUrl={rule.photoUrl}
/>
))}
</div>
<div className={isMember ? 'w-full md:w-1/2' : 'hidden'}>
<h2 className='border-b-0 p-4 text-center'>{t('internal')}</h2>
{internal.map((rule) => (
<RuleCard
className='mb-3 flex h-16 max-w-2xl'
key={rule.id}
id={rule.id}
internal={rule.internal}
title={rule.title}
photoUrl={rule.photoUrl}
/>
))}
</div>
</div>
);
}
17 changes: 17 additions & 0 deletions src/app/[locale]/(default)/rules/[subset]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { rulesMockdata } from '@/mock-data/rules';
import { setRequestLocale } from 'next-intl/server';
import { notFound } from 'next/navigation';

export default async function RuleSubSetPage({
params,
}: {
params: Promise<{ locale: string; subset: string }>;
}) {
const { locale, subset } = await params;
setRequestLocale(locale);
const page = rulesMockdata.find(
(rule) => rule.id === Number.parseInt(subset),
);
if (!page) return notFound();
return <h1 className='text-center'>{page.title}</h1>;
}
2 changes: 1 addition & 1 deletion src/components/news/ArticleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function ArticleCard({
params: { article: id },
}}
>
<Card className='relative flex h-full min-h-32 w-full overflow-hidden'>
<Card className='relative flex min-h-32 w-full overflow-hidden'>
<InternalBadge internal={internal} />
<Image
className='rounded-lg object-cover object-center transition-transform duration-300 group-hover:scale-105'
Expand Down
51 changes: 51 additions & 0 deletions src/components/rules/RuleCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Badge } from '@/components/ui/Badge';
import { Button } from '@/components/ui/Button';
import { Card, CardTitle } from '@/components/ui/Card';
import { Link } from '@/components/ui/Link';
import { cx } from '@/lib/utils';
import { useTranslations } from 'next-intl';
import Image from 'next/image';

type RuleCardProps = {
className?: string;
id: number;
internal: boolean;
title: string;
photoUrl: string;
};

function RuleCard({ className, id, internal, title, photoUrl }: RuleCardProps) {
const t = useTranslations('rules');

return (
<Link
className={cx('whitespace-normal font-normal', className)}
href={{
pathname: '/rules/[subset]',
params: { subset: id },
}}
aria-label={title}
>
<Card className='flex size-full transform overflow-hidden rounded-xl brightness-95 transition delay-150 duration-300 ease-in-out hover:scale-105 hover:border-primary hover:border-solid hover:shadow-lg hover:brightness-100 hover:dark:brightness-110'>
{internal ? (
<Badge className='flex w-1/3 items-center justify-center rounded-none text-lg hover:bg-primary '>
{t('internal')}
</Badge>
) : (
<Image
className='flex w-1/3 rounded-none'
src={`/${photoUrl}`}
alt={title}
width={150}
height={150}
/>
)}
<CardTitle className='flex w-2/3 items-center justify-center text-wrap text-center font-inter text-base ~lg:text-2xl ~sm:text-xl'>
{title}
</CardTitle>
</Card>
</Link>
);
}

export { RuleCard };
14 changes: 14 additions & 0 deletions src/components/rules/RuleCardListSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { RuleCardSkeleton } from '@/components/rules/RuleCardSkeleton';
import { useId } from 'react';

function RuleCardListSkeleton() {
return (
<div className='mt-5 flex size-full flex-col items-center justify-center'>
{Array.from({ length: 5 }).map(() => (
<RuleCardSkeleton key={useId()} />
))}
</div>
);
}

export { RuleCardListSkeleton };
17 changes: 17 additions & 0 deletions src/components/rules/RuleCardSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Button } from '@/components/ui/Button';
import { Card, CardTitle } from '@/components/ui/Card';
import { Skeleton } from '@/components/ui/Skeleton';
import { cx } from '@/lib/utils';

function RuleCardSkeleton() {
return (
<Card className='m-1.5 h-[68px] w-full max-w-[672px] shrink transform overflow-hidden rounded-xl md:h-[151px] '>
<Skeleton className='h-full w-1/3 rounded-none' />
<CardTitle className='flex h-full w-2/3 items-center justify-center'>
<Skeleton className='h-4 w-full max-w-24 rounded-full sm:max-w-48 md:h-7' />
</CardTitle>
</Card>
);
}

export { RuleCardSkeleton };
8 changes: 8 additions & 0 deletions src/lib/locale/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ const routing = defineRouting({
en: '/storage/shopping-cart',
no: '/lager/handlekurv',
},
'/rules': {
en: '/rules',
no: '/regler',
},
'/rules/[subset]': {
en: '/rules/[subset]',
no: '/regler/[subset]',
},
'/shift-schedule': {
en: '/shift-schedule',
no: '/vaktliste',
Expand Down
90 changes: 90 additions & 0 deletions src/mock-data/rules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const rulesMockdata = [
{
id: 1,
internal: true,
title: 'Regler for regler',
photoUrl: 'mock.jpg',
content:
'Reglene eksisterer av en grunn, overhold dem! • For din egen sikkerhet, andre sin sikkerhet og for at utstyr skal vare. • Regler håndheves av LabOps, Styret og Ledelsen • Si ifra hvis du ser regelbrudd. Ta ansvar. • Hvis du ikke vil si ifra selv, kan du gå via tillitsvalgt, som har taushetsplikt • Hvis reglene ikke følges, kan det føre til at man ikke får bruke utstyret, eller at man blir utestengt. • Regler kan foreslås endret og/eller fremlegges av hvem som helst, men godkjennes av styret.',
},
{
id: 2,
internal: true,
title: 'Etiske retningslinjer',
photoUrl: 'mock.jpg',
},
{
id: 3,
internal: false,
title: 'Regler for verkstedet',
photoUrl: 'mock.jpg',
},
{
id: 4,
internal: true,
title: 'Regler for vakt',
photoUrl: 'mock.jpg',
},
{
id: 5,
internal: false,
title: 'Regler for bruk av 3D-printer',
photoUrl: 'mock.jpg',
},
{
id: 6,
internal: true,
title: 'Regler for kaffemaskin',
photoUrl: 'mock.jpg',
},
{
id: 7,
internal: true,
title: 'Regler for utlån',
photoUrl: 'mock.jpg',
},
{
id: 8,
internal: true,
title: 'Regler for kurs',
photoUrl: 'mock.jpg',
},
{
id: 9,
internal: true,
title: 'Regler for arrangement',
photoUrl: 'mock.jpg',
},
{
id: 10,
internal: false,
title: 'Regler for VR briller',
photoUrl: 'mock.jpg',
},
{
id: 11,
internal: false,
title: 'Regler for verksted-PC',
photoUrl: 'mock.jpg',
},
{
id: 12,
internal: true,
title: 'Regler for kjøkkenet',
photoUrl: 'mock.jpg',
},
{
id: 13,
internal: false,
title: 'Regler for loddestasjon',
photoUrl: 'mock.jpg',
},
{
id: 14,
internal: true,
title: 'Regler for Drive',
photoUrl: 'mock.jpg',
},
];

export { rulesMockdata };
Loading