diff --git a/lighthouserc.cjs b/lighthouserc.cjs
index a60b47bb..9cdbd3bc 100644
--- a/lighthouserc.cjs
+++ b/lighthouserc.cjs
@@ -15,6 +15,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',
},
diff --git a/messages/en.json b/messages/en.json
index e50eb064..99dc38bb 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -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",
@@ -215,5 +216,10 @@
"api": {
"tooManyRequests": "Too many requests, please try again later",
"notAuthenticated": "Not authenticated"
+ },
+ "rules": {
+ "title": "Rules",
+ "forEveryone": "For everyone",
+ "internal": "Internal rules"
}
}
diff --git a/messages/no.json b/messages/no.json
index 8a17bd8e..61a0228b 100644
--- a/messages/no.json
+++ b/messages/no.json
@@ -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",
@@ -215,5 +216,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"
}
}
diff --git a/src/app/[locale]/(default)/rules/(main)/layout.tsx b/src/app/[locale]/(default)/rules/(main)/layout.tsx
new file mode 100644
index 00000000..a6912824
--- /dev/null
+++ b/src/app/[locale]/(default)/rules/(main)/layout.tsx
@@ -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 (
+ <>
+
{t('title')}
+ {children}
+ >
+ );
+}
diff --git a/src/app/[locale]/(default)/rules/(main)/loading.tsx b/src/app/[locale]/(default)/rules/(main)/loading.tsx
new file mode 100644
index 00000000..f430e757
--- /dev/null
+++ b/src/app/[locale]/(default)/rules/(main)/loading.tsx
@@ -0,0 +1,9 @@
+import { RuleCardListSkeleton } from '@/components/rules/RuleCardListSkeleton';
+
+export default function RulesSkeleton() {
+ return (
+
+
+
+ );
+}
diff --git a/src/app/[locale]/(default)/rules/(main)/page.tsx b/src/app/[locale]/(default)/rules/(main)/page.tsx
new file mode 100644
index 00000000..1e4eeb24
--- /dev/null
+++ b/src/app/[locale]/(default)/rules/(main)/page.tsx
@@ -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 (
+
+
+
+ {t('forEveryone')}
+
+ {notInternal.map((rule) => (
+
+ ))}
+
+
+
{t('internal')}
+ {internal.map((rule) => (
+
+ ))}
+
+
+ );
+}
diff --git a/src/app/[locale]/(default)/rules/[subset]/page.tsx b/src/app/[locale]/(default)/rules/[subset]/page.tsx
new file mode 100644
index 00000000..26d72b5a
--- /dev/null
+++ b/src/app/[locale]/(default)/rules/[subset]/page.tsx
@@ -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 {page.title}
;
+}
diff --git a/src/components/news/ArticleCard.tsx b/src/components/news/ArticleCard.tsx
index 32a5a719..a47a5ac9 100644
--- a/src/components/news/ArticleCard.tsx
+++ b/src/components/news/ArticleCard.tsx
@@ -34,7 +34,7 @@ function ArticleCard({
params: { article: id },
}}
>
-
+
+
+ {internal ? (
+
+ {t('internal')}
+
+ ) : (
+
+ )}
+
+ {title}
+
+
+
+ );
+}
+
+export { RuleCard };
diff --git a/src/components/rules/RuleCardListSkeleton.tsx b/src/components/rules/RuleCardListSkeleton.tsx
new file mode 100644
index 00000000..61e90da0
--- /dev/null
+++ b/src/components/rules/RuleCardListSkeleton.tsx
@@ -0,0 +1,14 @@
+import { RuleCardSkeleton } from '@/components/rules/RuleCardSkeleton';
+import { useId } from 'react';
+
+function RuleCardListSkeleton() {
+ return (
+
+ {Array.from({ length: 5 }).map(() => (
+
+ ))}
+
+ );
+}
+
+export { RuleCardListSkeleton };
diff --git a/src/components/rules/RuleCardSkeleton.tsx b/src/components/rules/RuleCardSkeleton.tsx
new file mode 100644
index 00000000..ad06cdf3
--- /dev/null
+++ b/src/components/rules/RuleCardSkeleton.tsx
@@ -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 (
+
+
+
+
+
+
+ );
+}
+
+export { RuleCardSkeleton };
diff --git a/src/lib/locale/index.ts b/src/lib/locale/index.ts
index 861cd5c9..c2cf3bed 100644
--- a/src/lib/locale/index.ts
+++ b/src/lib/locale/index.ts
@@ -70,6 +70,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',
diff --git a/src/mock-data/rules.ts b/src/mock-data/rules.ts
new file mode 100644
index 00000000..d34d1259
--- /dev/null
+++ b/src/mock-data/rules.ts
@@ -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 };