From ee1847c937e20ec2ce4cfb0c60930983b637e9b6 Mon Sep 17 00:00:00 2001 From: Axel Pettersson Date: Sun, 1 Oct 2023 17:29:52 +0200 Subject: [PATCH] Various improvements and member document support --- .../api/member/[id]/documents/[page]/route.ts | 22 +++ apps/web/app/cookie-policy/page.tsx | 2 +- apps/web/app/error.tsx | 4 +- apps/web/app/layout.tsx | 6 +- apps/web/app/ledamot/[id]/biography-entry.tsx | 4 +- apps/web/app/ledamot/[id]/biography.tsx | 2 +- apps/web/app/ledamot/[id]/documents.tsx | 63 ++++++++- apps/web/app/ledamot/[id]/statistics.tsx | 2 +- apps/web/app/ledamot/[id]/tabs.tsx | 2 +- apps/web/app/not-found.tsx | 2 +- apps/web/app/om-oss/page.tsx | 2 +- apps/web/app/page.tsx | 8 +- apps/web/app/parti/[party]/page.tsx | 2 +- .../standpunkter/[id]/party-standpoints.tsx | 29 ++-- apps/web/components/card.tsx | 19 --- apps/web/components/common/breadcrumbs.tsx | 2 +- apps/web/components/{ => common}/button.tsx | 0 apps/web/components/common/card.tsx | 52 +++++++ apps/web/components/common/pagination.tsx | 127 ++++++++++++++++++ apps/web/components/header/header.tsx | 2 +- .../components/{ => header}/theme-toggle.tsx | 0 .../api/documents/parsers/member-document.ts | 8 +- apps/web/lib/api/member/get-absence.ts | 2 +- .../lib/api/member/get-member-with-absence.ts | 4 +- apps/web/lib/api/member/parsers/absence.ts | 3 +- apps/web/lib/api/member/types.ts | 15 ++- apps/web/lib/api/parliament/types.ts | 3 +- apps/web/lib/committes.ts | 18 +++ apps/web/lib/navigation.tsx | 9 +- apps/web/lib/styles/committees.ts | 22 +++ apps/web/lib/styles/party.ts | 31 ++--- apps/web/tailwind.config.ts | 6 +- 32 files changed, 387 insertions(+), 86 deletions(-) create mode 100644 apps/web/app/api/member/[id]/documents/[page]/route.ts delete mode 100644 apps/web/components/card.tsx rename apps/web/components/{ => common}/button.tsx (100%) create mode 100644 apps/web/components/common/card.tsx create mode 100644 apps/web/components/common/pagination.tsx rename apps/web/components/{ => header}/theme-toggle.tsx (100%) diff --git a/apps/web/app/api/member/[id]/documents/[page]/route.ts b/apps/web/app/api/member/[id]/documents/[page]/route.ts new file mode 100644 index 000000000..b64c12c58 --- /dev/null +++ b/apps/web/app/api/member/[id]/documents/[page]/route.ts @@ -0,0 +1,22 @@ +import getMemberDocuments from "@lib/api/documents/get-member-documents"; + +interface Payload { + params: { + id: string; + page: string; + }; +} + +export async function GET( + _request: Request, + { params: { id, page } }: Payload, +) { + const pageInt = parseInt(page); + + if (Number.isNaN(pageInt)) { + return new Response("Invalid page", { status: 400 }); + } + + const memberDocuments = await getMemberDocuments({ id, page: pageInt }); + return Response.json(memberDocuments); +} diff --git a/apps/web/app/cookie-policy/page.tsx b/apps/web/app/cookie-policy/page.tsx index 57bb426a2..7ab09e23c 100644 --- a/apps/web/app/cookie-policy/page.tsx +++ b/apps/web/app/cookie-policy/page.tsx @@ -1,4 +1,4 @@ -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import Container from "@components/common/container"; import PageTitle from "@components/common/page-title"; import { CodeBracketIcon } from "@heroicons/react/24/solid"; diff --git a/apps/web/app/error.tsx b/apps/web/app/error.tsx index 253d8f1f5..2e3007c70 100644 --- a/apps/web/app/error.tsx +++ b/apps/web/app/error.tsx @@ -1,7 +1,7 @@ "use client"; -import { PrimaryButton } from "@components/button"; -import { Card } from "@components/card"; +import { PrimaryButton } from "@components/common/button"; +import { Card } from "@components/common/card"; import Container from "@components/common/container"; import PageTitle from "@components/common/page-title"; import { ExclamationCircleIcon } from "@heroicons/react/24/solid"; diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index 36b09ca0b..0bbddff8a 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -5,6 +5,7 @@ import Head from "./head"; import Footer from "./footer"; import Header from "@components/header/header"; import { ThemeProvider } from "@components/providers/theme-provider"; +import { twMerge } from "tailwind-merge"; const roboto = Roboto({ weight: ["300", "400", "500", "700"], @@ -18,7 +19,10 @@ export default function RootLayout({ children }: PropsWithChildren) {
diff --git a/apps/web/app/ledamot/[id]/biography-entry.tsx b/apps/web/app/ledamot/[id]/biography-entry.tsx index a5f790992..4de60b74e 100644 --- a/apps/web/app/ledamot/[id]/biography-entry.tsx +++ b/apps/web/app/ledamot/[id]/biography-entry.tsx @@ -25,9 +25,9 @@ export default function BiographyEntry({ information }: Props) { {information.code} -
+

{information.content} -

+

); } diff --git a/apps/web/app/ledamot/[id]/biography.tsx b/apps/web/app/ledamot/[id]/biography.tsx index 1aa7ee0bc..8af125f53 100644 --- a/apps/web/app/ledamot/[id]/biography.tsx +++ b/apps/web/app/ledamot/[id]/biography.tsx @@ -1,4 +1,4 @@ -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import type { Information } from "@lib/api/member/types"; import BiographyEntry from "./biography-entry"; diff --git a/apps/web/app/ledamot/[id]/documents.tsx b/apps/web/app/ledamot/[id]/documents.tsx index 66dd72f99..6b6c4393a 100644 --- a/apps/web/app/ledamot/[id]/documents.tsx +++ b/apps/web/app/ledamot/[id]/documents.tsx @@ -1,9 +1,32 @@ "use client"; -import type { MemberDocuments } from "@lib/api/member/types"; -import { useState } from "react"; +import { Card, CommitteeHeader } from "@components/common/card"; +import Pagination from "@components/common/pagination"; +import type { MemberDocument, MemberDocuments } from "@lib/api/member/types"; +import { routes } from "@lib/navigation"; +import Link from "next/link"; +import { useRef, useState } from "react"; -function Document() { - return
hej
; +interface DocumentProps { + document: MemberDocument; +} + +function Document({ document }: DocumentProps) { + return ( + + + +
+

+ {document.title} +

+

{document.altTitle}

+

+ {document.subtitle} +

+
+
+ + ); } interface Props { @@ -12,13 +35,39 @@ interface Props { } export default function Documents({ initialDocuments, memberId }: Props) { + const containerRef = useRef(null); + const [page, setPage] = useState(1); const [documents, setDocuments] = useState(initialDocuments.documents); + async function changePage(page: number) { + const response = await fetch( + `${window.location.origin}${routes.api.memberDocument(memberId, page)}`, + { next: { revalidate: 60 * 60 * 24 } }, + ); + const newDocuments: MemberDocuments = await response.json(); + setPage(page); + setDocuments(newDocuments.documents); + containerRef.current?.scrollIntoView(); + } + return ( - <> +
+ {documents.map((document) => ( -
{document.altTitle}
+ ))} - + +
); } diff --git a/apps/web/app/ledamot/[id]/statistics.tsx b/apps/web/app/ledamot/[id]/statistics.tsx index 3420dedbf..80cc51eee 100644 --- a/apps/web/app/ledamot/[id]/statistics.tsx +++ b/apps/web/app/ledamot/[id]/statistics.tsx @@ -1,4 +1,4 @@ -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import type { MemberDetailedResponse } from "@lib/api/member/types"; import { twMerge } from "tailwind-merge"; diff --git a/apps/web/app/ledamot/[id]/tabs.tsx b/apps/web/app/ledamot/[id]/tabs.tsx index f29cad6f8..18f1db074 100644 --- a/apps/web/app/ledamot/[id]/tabs.tsx +++ b/apps/web/app/ledamot/[id]/tabs.tsx @@ -1,6 +1,6 @@ "use client"; -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import type { MemberDocuments } from "@lib/api/member/types"; import { useState } from "react"; import Documents from "./documents"; diff --git a/apps/web/app/not-found.tsx b/apps/web/app/not-found.tsx index 8c1ba8c0d..3f7de4a95 100644 --- a/apps/web/app/not-found.tsx +++ b/apps/web/app/not-found.tsx @@ -1,4 +1,4 @@ -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import Container from "@components/common/container"; import PageTitle from "@components/common/page-title"; import { ExclamationCircleIcon } from "@heroicons/react/24/solid"; diff --git a/apps/web/app/om-oss/page.tsx b/apps/web/app/om-oss/page.tsx index 5ab591caf..1cfaf76a5 100644 --- a/apps/web/app/om-oss/page.tsx +++ b/apps/web/app/om-oss/page.tsx @@ -1,6 +1,6 @@ import { githubFrontend, githubProfile, linkedIn } from "@lib/socials"; import PageTitle from "@components/common/page-title"; -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import React from "react"; import { InformationCircleIcon } from "@heroicons/react/24/solid"; import ExternalLink from "@components/common/external-link"; diff --git a/apps/web/app/page.tsx b/apps/web/app/page.tsx index 09fadb736..3bd1220a5 100644 --- a/apps/web/app/page.tsx +++ b/apps/web/app/page.tsx @@ -1,9 +1,10 @@ -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import Typed from "@components/common/typed"; import Link from "next/link"; import { routes } from "@lib/navigation"; import PageTitle from "@components/common/page-title"; import Container from "@components/common/container"; +import { twMerge } from "tailwind-merge"; export const metadata = { title: "Partiguiden | Rösta rätt", @@ -53,7 +54,10 @@ export default function IndexPage() { {subject.name} diff --git a/apps/web/app/parti/[party]/page.tsx b/apps/web/app/parti/[party]/page.tsx index 84f8dc198..64093c622 100644 --- a/apps/web/app/parti/[party]/page.tsx +++ b/apps/web/app/parti/[party]/page.tsx @@ -1,4 +1,4 @@ -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import Container from "@components/common/container"; import { Divider } from "@components/common/divider"; import ExternalLink from "@components/common/external-link"; diff --git a/apps/web/app/standpunkter/[id]/party-standpoints.tsx b/apps/web/app/standpunkter/[id]/party-standpoints.tsx index 82272dbe9..8a3977907 100644 --- a/apps/web/app/standpunkter/[id]/party-standpoints.tsx +++ b/apps/web/app/standpunkter/[id]/party-standpoints.tsx @@ -1,13 +1,13 @@ "use client"; -import { Card } from "@components/card"; +import { Card } from "@components/common/card"; import { ChevronUpIcon } from "@heroicons/react/24/solid"; import { dateString } from "@lib/dates"; import { - backgroundHover, - borderBottom, - marker, - textColor, + partyBackgroundHover, + partyBorderBottom, + partyMarker, + partyTextColor, } from "@lib/styles/party"; import type { Standpoint } from "@partiguiden/party-data/types"; import type { Party } from "@partiguiden/party-data/types"; @@ -34,13 +34,14 @@ export default function PartyStandpoints({ <> {visible && ( @@ -49,7 +50,9 @@ export default function PartyStandpoints({

{standpoint.title}

{standpoint.opinions.length > 0 ? ( -