Skip to content

Commit 8ff49fe

Browse files
committed
Restructure project
1 parent 60badd1 commit 8ff49fe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2270
-1957
lines changed

.github/workflows/ci.yml

-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ jobs:
2525
- name: Lint
2626
run: pnpm lint
2727

28-
- name: Lint styles
29-
run: pnpm lint:css
30-
3128
- name: Typecheck
3229
run: pnpm typecheck
3330

apps/admin/.stylelintrc.json

-3
This file was deleted.

apps/admin/app/globals.css

+3-74
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,3 @@
1-
:root {
2-
/* Colors */
3-
--color-primary: #00796b;
4-
--color-text-primary: #0f172a;
5-
--color-background: #f8fafc;
6-
--color-elevated: #f1f5f9;
7-
8-
/* Status colors */
9-
--color-background-success: #f0fdf4;
10-
--color-text-success: #166534;
11-
--color-background-error: #fef2f2;
12-
--color-text-error: #991b1b;
13-
--color-background-warning: #fefce8;
14-
--color-text-warning: #854d0e;
15-
16-
/* Spacings */
17-
--spacing-1: 0.25rem;
18-
--spacing-2: 0.5rem;
19-
--spacing-3: 0.75rem;
20-
--spacing-4: 1rem;
21-
--spacing-5: 1.25rem;
22-
--spacing-6: 1.5rem;
23-
--spacing-7: 1.75rem;
24-
--spacing-8: 2rem;
25-
--spacing-9: 2.25rem;
26-
--spacing-10: 2.5rem;
27-
--spacing-11: 2.75rem;
28-
--spacing-12: 3rem;
29-
30-
/* Border radius */
31-
--border-radius-rounded: var(--spacing-1);
32-
33-
/* Shadows */
34-
--box-shadow-medium: rgb(0 0 0 / 15%) 1.95px 1.95px 2.6px;
35-
36-
/* Max widths */
37-
--max-width-header: 80rem;
38-
39-
/* Font sizes */
40-
--font-small: 0.875rem;
41-
--line-height-small: 1.25rem;
42-
}
43-
44-
@media (prefers-color-scheme: dark) {
45-
:root {
46-
--color-text-primary: #f8fafc;
47-
--color-background: #020617;
48-
--color-elevated: #0f172a;
49-
50-
/* Status colors */
51-
--color-background-success: #1e293b;
52-
--color-text-success: #4ade80;
53-
--color-background-error: #1e293b;
54-
--color-text-error: #f87171;
55-
--color-background-warning: #1e293b;
56-
--color-text-warning: #fde047;
57-
}
58-
}
59-
60-
button,
61-
input[type="submit"],
62-
input[type="reset"] {
63-
background: none;
64-
color: inherit;
65-
border: none;
66-
padding: 0;
67-
font: inherit;
68-
cursor: pointer;
69-
outline: inherit;
70-
}
71-
72-
a {
73-
text-decoration: none;
74-
}
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;

apps/admin/app/header.module.css

-21
This file was deleted.

apps/admin/app/header.tsx

+33-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,40 @@
11
"use client";
22
import { HEADER_LINKS } from "@lib/navigation";
3+
import type { Session } from "next-auth";
4+
import { useSession, signOut } from "next-auth/react";
35
import Link from "next/link";
46
import { usePathname } from "next/navigation";
5-
import styles from "./header.module.css";
7+
8+
function UserHeader({ session }: { session: Session }) {
9+
return (
10+
<>
11+
<div className="flex gap-3">
12+
<div className="hidden flex-col justify-between py-2 sm:flex">
13+
<span>{session.user?.name}</span>
14+
<span>{session.user?.email}</span>
15+
</div>
16+
<button
17+
className="my-2 rounded bg-primary p-3 text-white"
18+
onClick={() => signOut()}
19+
>
20+
Logga ut
21+
</button>
22+
</div>
23+
</>
24+
);
25+
}
626

727
function NavigationLinks() {
828
const pathname = usePathname();
929

1030
return (
11-
<ol className={styles["navigation-links-wrapper"]}>
31+
<ol className="my-2 flex gap-2">
1232
{HEADER_LINKS.map(({ href, name }) => (
1333
<li key={href}>
1434
<Link
1535
href={href}
1636
aria-current={href === pathname ? "page" : "false"}
17-
className={styles["navigation-link"]}
37+
className="inline-block rounded-lg bg-primary p-2 text-white aria-current-false:opacity-70 aria-current-false:hover:opacity-90"
1838
>
1939
{name}
2040
</Link>
@@ -24,10 +44,17 @@ function NavigationLinks() {
2444
);
2545
}
2646

27-
export default function Header() {
47+
export function Header() {
48+
const session = useSession();
49+
2850
return (
29-
<nav className={styles["navigation-wrapper"]}>
30-
<NavigationLinks />
51+
<nav className=" bg-elevated-light shadow-lg dark:bg-elevated-dark">
52+
<div className="mx-auto flex max-w-7xl items-center justify-between px-4">
53+
<NavigationLinks />
54+
{session.status === "authenticated" && (
55+
<UserHeader session={session.data} />
56+
)}
57+
</div>
3158
</nav>
3259
);
3360
}

apps/admin/app/layout.module.css

-5
This file was deleted.

apps/admin/app/layout.tsx

+18-13
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,34 @@
1+
import type { PropsWithChildren } from "react";
2+
import { Suspense } from "react";
3+
import NextAuthProvider from "./(auth)/next-auth-provider";
4+
import { Header } from "./(header)/header";
15
import "./globals.css";
2-
import Header from "./header";
3-
import styles from "./layout.module.css";
6+
import type { Metadata } from "next";
47
import { Lato } from "next/font/google";
5-
import StatusContextProvider from "./status";
8+
import Loading from "./loading";
9+
import StatusContextProvider from "./(status)/status-context";
610

711
const lato = Lato({
812
subsets: ["latin"],
913
weight: ["100", "300", "400", "700"],
1014
});
1115

12-
export const metadata = {
16+
export const metadata: Metadata = {
1317
title: "Partiguiden Admin",
18+
description: "Admin portal for Partiguiden",
1419
};
1520

16-
export default function RootLayout({
17-
children,
18-
}: {
19-
children: React.ReactNode;
20-
}) {
21+
export default function RootLayout({ children }: PropsWithChildren) {
2122
return (
22-
<html lang="en">
23-
<body className={`${lato.className} ${styles["body-main"]}`}>
23+
<html lang="sv">
24+
<body
25+
className={`${lato.className} flex min-h-screen flex-col bg-background-light text-foreground-light dark:bg-background-dark dark:text-foreground-dark`}
26+
>
2427
<StatusContextProvider>
25-
<Header />
26-
{children}
28+
<NextAuthProvider>
29+
<Header />
30+
<Suspense fallback={<Loading />}>{children}</Suspense>
31+
</NextAuthProvider>
2732
</StatusContextProvider>
2833
</body>
2934
</html>

apps/admin/app/loading.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import LoadingSpinner from "@components/icons/loading-spinner";
2+
3+
export default function Loading() {
4+
return <LoadingSpinner className="mx-auto mt-5 h-44 w-44 text-primary" />;
5+
}

apps/admin/app/page.module.css

-9
This file was deleted.

apps/admin/app/page.tsx

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
"use client";
22

3-
import styles from "./page.module.css";
3+
import Image from "next/image";
44

55
export default function Home() {
6-
return <main className={styles["main-container"]}>Admin</main>;
6+
return (
7+
<main className="mx-3 flex flex-1 flex-col items-center justify-center gap-3">
8+
<Image
9+
src="/partiguiden_logo_primary.png"
10+
alt="Partiguiden logo"
11+
width="890"
12+
height="140"
13+
/>
14+
</main>
15+
);
716
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"use server";
2+
import { PAGES } from "@lib/navigation";
3+
import { revalidatePath } from "next/cache";
4+
import { zStandpoint } from "../types";
5+
import prisma from "@lib/prisma";
6+
import handleServerError from "@lib/handleServerError";
7+
8+
export default async function createStandpoint(formData: FormData) {
9+
try {
10+
const json = Object.fromEntries(formData.entries());
11+
const data = zStandpoint.parse({
12+
...json,
13+
content: formData.getAll("content"),
14+
});
15+
16+
await prisma.standpoint.create({
17+
data,
18+
});
19+
20+
revalidatePath(PAGES.standpoints.href);
21+
} catch (error) {
22+
return handleServerError(error);
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"use server";
2+
import handleServerError from "@lib/handleServerError";
3+
import { PAGES } from "@lib/navigation";
4+
import prisma from "@lib/prisma";
5+
import { revalidatePath } from "next/cache";
6+
7+
export default async function deleteStandpoint(link: string) {
8+
try {
9+
await prisma.standpoint.delete({
10+
where: {
11+
link,
12+
},
13+
});
14+
revalidatePath(PAGES.standpoints.href);
15+
} catch (error) {
16+
return handleServerError(error);
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"use server";
2+
import { PAGES } from "@lib/navigation";
3+
import prisma from "@lib/prisma";
4+
import { revalidatePath } from "next/cache";
5+
import { zStandpoint } from "../types";
6+
import type { Standpoint } from "@prisma/client";
7+
import handleServerError from "@lib/handleServerError";
8+
9+
export default async function editStandpoint(
10+
standpointsPrisma: Standpoint,
11+
formData: FormData,
12+
) {
13+
try {
14+
const json = Object.fromEntries(formData.entries());
15+
const data = zStandpoint.parse({
16+
...json,
17+
content: formData.getAll("content"),
18+
});
19+
await prisma.standpoint.update({
20+
where: {
21+
link: standpointsPrisma.link,
22+
},
23+
data,
24+
});
25+
26+
revalidatePath(PAGES.standpoints.href);
27+
} catch (error) {
28+
return handleServerError(error);
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"use server";
2+
import { PAGES } from "@lib/navigation";
3+
import prisma from "@lib/prisma";
4+
import { revalidatePath } from "next/cache";
5+
import type { Standpoint } from "@prisma/client";
6+
import handleServerError from "@lib/handleServerError";
7+
8+
export default async function updateSubject(
9+
standpointsPrisma: Standpoint,
10+
newSubject: string,
11+
) {
12+
try {
13+
await prisma.standpoint.update({
14+
where: {
15+
link: standpointsPrisma.link,
16+
},
17+
data: {
18+
subjectName: newSubject,
19+
},
20+
});
21+
revalidatePath(PAGES.standpoints.href);
22+
} catch (error) {
23+
return handleServerError(error);
24+
}
25+
}

0 commit comments

Comments
 (0)