From 9752ede10907923fd387ade91e03589c36d54cd0 Mon Sep 17 00:00:00 2001 From: Joshua Coles Date: Tue, 13 Feb 2024 22:06:58 +0000 Subject: [PATCH] An unsatisfying solution to the problem --- next.config.js | 6 --- package.json | 1 + pnpm-lock.yaml | 21 +++++++++ src/app/api/route.ts | 78 +++++++++++++++++++++++++++++++++ src/app/sem1-revision/page.tsx | 30 ++----------- src/app/sem2/page.tsx | 31 ++----------- src/components/OverviewPage.tsx | 41 ++++++++++------- src/components/PageWrapper.tsx | 11 +++++ src/data/fetchWithSQL.ts | 23 +++++++++- 9 files changed, 162 insertions(+), 80 deletions(-) create mode 100644 src/app/api/route.ts create mode 100644 src/components/PageWrapper.tsx diff --git a/next.config.js b/next.config.js index 6a31649..5c6d779 100644 --- a/next.config.js +++ b/next.config.js @@ -1,12 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { output: 'standalone', - rewrites: async () => [ - { - source: '/api/:path*', - destination: 'https://revision.joshuacoles.me/api/:path*', - }, - ], } module.exports = nextConfig diff --git a/package.json b/package.json index 4dece32..a720e28 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "react-dom": "^18.2.0", "react-tooltip": "^5.26.1", "reaviz": "^15.7.0", + "swr": "^2.2.4", "zod": "^3.22.4" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfd8de5..e2d8599 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,6 +50,9 @@ dependencies: reaviz: specifier: ^15.7.0 version: 15.7.0(@types/react@18.2.55)(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0) + swr: + specifier: ^2.2.4 + version: 2.2.4(react@18.2.0) zod: specifier: ^3.22.4 version: 3.22.4 @@ -5808,6 +5811,16 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + /swr@2.2.4(react@18.2.0): + resolution: {integrity: sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + dependencies: + client-only: 0.0.1 + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true @@ -6161,6 +6174,14 @@ packages: use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.55)(react@18.2.0) dev: false + /use-sync-external-store@1.2.0(react@18.2.0): + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} diff --git a/src/app/api/route.ts b/src/app/api/route.ts new file mode 100644 index 0000000..4a2f5a9 --- /dev/null +++ b/src/app/api/route.ts @@ -0,0 +1,78 @@ +import {NextRequest} from "next/server"; +import {getData, OverviewConfig} from "@/data/fetchWithSQL"; + +export const semester1Revision: OverviewConfig = { + title: 'Semester 1 Revision', + periodKey: 'y5-s1-revision', + goalHours: 4, + subjects: [ + { + projectId: 195482340, + }, + { + title: 'Measure Theory', + projectId: 195519024, + }, + { + title: 'Quantum Mechanics', + projectId: 195518593, + }, + { + projectId: 195754611, + } + ], + timePeriod: { + start: "2023-12-15T00:00:00.000Z", + end: "2024-01-25T00:00:00.000Z" + } +} + +export const semester2: OverviewConfig = { + title: 'Semester 2', + periodKey: 'y5-s2', + goalHours: 7.5, + subjects: [ + { + projectId: 195754611, + }, + { + projectId: 199383703, + }, + { + projectId: 199383691, + }, + { + projectId: 198859760, + }, + { + projectId: 199383698, + }, + ], + timePeriod: { + start: "2024-02-03T00:00:00.000Z", + end: "2024-05-10T00:00:00.000Z" + } +} + +export type PeriodKey = keyof typeof periodMap; +const periodMap = { + 'y5-s1-revision': semester1Revision, + 'y5-s2': semester2, +} + +export async function GET(request: NextRequest): Promise { + const period = request.nextUrl.searchParams.get('period'); + + if (period == null) { + return new Response('No period provided', {status: 400}); + } + + if (!periodMap.hasOwnProperty(period)) { + return new Response('Invalid period', {status: 400}); + } + + const config = periodMap[period as keyof typeof periodMap]; + const data = await getData(config); + + return Response.json(data) +} diff --git a/src/app/sem1-revision/page.tsx b/src/app/sem1-revision/page.tsx index da35ccc..991739f 100644 --- a/src/app/sem1-revision/page.tsx +++ b/src/app/sem1-revision/page.tsx @@ -1,30 +1,6 @@ -import OverviewPage, {OverviewConfig} from "@/components/OverviewPage"; - -const semester1Revision: OverviewConfig = { - title: 'Semester 1 Revision', - goalHours: 4, - subjects: [ - { - projectId: 195482340, - }, - { - title: 'Measure Theory', - projectId: 195519024, - }, - { - title: 'Quantum Mechanics', - projectId: 195518593, - }, - { - projectId: 195754611, - } - ], - timePeriod: { - start: "2023-12-15T00:00:00.000Z", - end: "2024-01-25T00:00:00.000Z" - } -} +import {semester1Revision} from "@/app/api/route"; +import OverviewPageWrapper from "@/components/PageWrapper"; export default function Home() { - return + return } diff --git a/src/app/sem2/page.tsx b/src/app/sem2/page.tsx index 18e3bdf..3f9e529 100644 --- a/src/app/sem2/page.tsx +++ b/src/app/sem2/page.tsx @@ -1,31 +1,6 @@ -import OverviewPage, {OverviewConfig} from "@/components/OverviewPage"; - -const semester2: OverviewConfig = { - title: 'Semester 2', - goalHours: 7.5, - subjects: [ - { - projectId: 195754611, - }, - { - projectId: 199383703, - }, - { - projectId: 199383691, - }, - { - projectId: 198859760, - }, - { - projectId: 199383698, - }, - ], - timePeriod: { - start: "2024-02-03T00:00:00.000Z", - end: "2024-05-10T00:00:00.000Z" - } -} +import {semester2} from "@/app/api/route"; +import OverviewPageWrapper from "@/components/PageWrapper"; export default function Home() { - return + return } diff --git a/src/components/OverviewPage.tsx b/src/components/OverviewPage.tsx index 134fc79..a744c1f 100644 --- a/src/components/OverviewPage.tsx +++ b/src/components/OverviewPage.tsx @@ -1,28 +1,35 @@ +"use client"; + import {SubjectComparisonCard} from "@/components/cards/subjectComparisonCard"; import {CalendarOverviewCard} from "@/components/cards/calendarOverviewCard"; import {SubjectOverviewCard} from "@/components/cards/subjectOverviewCard"; -import {getDataSQL} from "@/data/fetchWithSQL"; +import {PeriodKey} from "@/app/api/route"; +import useSWR from "swr"; +import {Data} from "@/data/fetchData"; +import {OverviewConfig} from "@/data/fetchWithSQL"; -export interface OverviewConfig { - title: string, +function useData(periodKey: PeriodKey, initialData: Data = { + projects: [], + timeEntries: [], +}): Data { + const {data} = useSWR(periodKey, async () => { + const res = await fetch(`/api?period=${periodKey}`); + const json = await res.json(); + return json as Data; + }); - subjects: { - title?: string, - projectId: number, - }[], - - goalHours: number, - - timePeriod: { - start: string, - end: string - }, + return data ?? initialData; } -export default async function OverviewPage({config}: { - config: OverviewConfig + +export default function OverviewPage({ + config, + initialData + }: { + config: OverviewConfig, + initialData?: Data, }) { - const data = await getDataSQL(config); + const data = useData(config.periodKey, initialData); return (
diff --git a/src/components/PageWrapper.tsx b/src/components/PageWrapper.tsx new file mode 100644 index 0000000..77b6f9a --- /dev/null +++ b/src/components/PageWrapper.tsx @@ -0,0 +1,11 @@ +"use server"; + +import {getData, OverviewConfig} from "@/data/fetchWithSQL"; +import OverviewPage from "@/components/OverviewPage"; + +export default async function OverviewPageWrapper({config}: { + config: OverviewConfig +}) { + const data = await getData(config); + return ; +} diff --git a/src/data/fetchWithSQL.ts b/src/data/fetchWithSQL.ts index 0ad6d7c..84b38e8 100644 --- a/src/data/fetchWithSQL.ts +++ b/src/data/fetchWithSQL.ts @@ -1,9 +1,26 @@ -import {OverviewConfig} from "@/components/OverviewPage"; import {Data} from "@/data/fetchData"; import {db} from "@/data/database"; import * as dFns from "date-fns"; +import {PeriodKey} from "@/app/api/route"; -export async function getDataSQL(config: OverviewConfig): Promise { +export interface OverviewConfig { + title: string, + periodKey: PeriodKey, + + subjects: { + title?: string, + projectId: number, + }[], + + goalHours: number, + + timePeriod: { + start: string, + end: string + }, +} + +export async function getData(config: OverviewConfig): Promise { // If we're in build-time, we don't have access to the database if (!db) { return { @@ -12,6 +29,8 @@ export async function getDataSQL(config: OverviewConfig): Promise { } } + console.log('fetching data from SQL') + let projectIds = config.subjects.map((subject) => subject.projectId.toString()); const projects = await db.selectFrom('project')