From b55352dc641d7fa6b404d6e2eb1b19dd4cb36fd8 Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:28:37 +0100 Subject: [PATCH 01/12] chore: update next to version 15 --- package-lock.json | 167 ++++++++++++++++++++++++---------------------- package.json | 4 +- 2 files changed, 88 insertions(+), 83 deletions(-) diff --git a/package-lock.json b/package-lock.json index fd57a7b2..b918d077 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,8 @@ "jsonwebtoken": "^9.0.2", "jsqr": "^1.4.0", "luxon": "^3.5.0", - "next": "^14.2.5", - "next-auth": "^4.24.11", + "next": "^15.0.3", + "next-auth": "^4.24.7", "next-qrcode": "^2.5.1", "nodemailer": "^6.9.16", "react": "^18.3.1", @@ -693,9 +693,10 @@ } }, "node_modules/@next/env": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.14.tgz", - "integrity": "sha512-/0hWQfiaD5//LvGNgc8PjvyqV50vGK0cADYzaoOOGN8fxzBn3iAiaq3S0tCRnFBldq0LVveLcxCTi41ZoYgAgg==" + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.3.tgz", + "integrity": "sha512-t9Xy32pjNOvVn2AS+Utt6VmyrshbpfUMhIjFO60gI58deSo/KgLOp31XZ4O+kY/Is8WAGYwA5gR7kOb1eORDBA==", + "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { "version": "14.2.15", @@ -753,12 +754,13 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.14.tgz", - "integrity": "sha512-bsxbSAUodM1cjYeA4o6y7sp9wslvwjSkWw57t8DtC8Zig8aG8V6r+Yc05/9mDzLKcybb6EN85k1rJDnMKBd9Gw==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.3.tgz", + "integrity": "sha512-s3Q/NOorCsLYdCKvQlWU+a+GeAd3C8Rb3L1YnetsgwXzhc3UTWrtQpB/3eCjFOdGUj5QmXfRak12uocd1ZiiQw==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -768,12 +770,13 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.14.tgz", - "integrity": "sha512-cC9/I+0+SK5L1k9J8CInahduTVWGMXhQoXFeNvF0uNs3Bt1Ub0Azb8JzTU9vNCr0hnaMqiWu/Z0S1hfKc3+dww==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.3.tgz", + "integrity": "sha512-Zxl/TwyXVZPCFSf0u2BNj5sE0F2uR6iSKxWpq4Wlk/Sv9Ob6YCKByQTkV2y6BCic+fkabp9190hyrDdPA/dNrw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -783,12 +786,13 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.14.tgz", - "integrity": "sha512-RMLOdA2NU4O7w1PQ3Z9ft3PxD6Htl4uB2TJpocm+4jcllHySPkFaUIFacQ3Jekcg6w+LBaFvjSPthZHiPmiAUg==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.3.tgz", + "integrity": "sha512-T5+gg2EwpsY3OoaLxUIofmMb7ohAUlcNZW0fPQ6YAutaWJaxt1Z1h+8zdl4FRIOr5ABAAhXtBcpkZNwUcKI2fw==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -798,12 +802,13 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.14.tgz", - "integrity": "sha512-WgLOA4hT9EIP7jhlkPnvz49iSOMdZgDJVvbpb8WWzJv5wBD07M2wdJXLkDYIpZmCFfo/wPqFsFR4JS4V9KkQ2A==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.3.tgz", + "integrity": "sha512-WkAk6R60mwDjH4lG/JBpb2xHl2/0Vj0ZRu1TIzWuOYfQ9tt9NFsIinI1Epma77JVgy81F32X/AeD+B2cBu/YQA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -813,12 +818,13 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.14.tgz", - "integrity": "sha512-lbn7svjUps1kmCettV/R9oAvEW+eUI0lo0LJNFOXoQM5NGNxloAyFRNByYeZKL3+1bF5YE0h0irIJfzXBq9Y6w==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.3.tgz", + "integrity": "sha512-gWL/Cta1aPVqIGgDb6nxkqy06DkwJ9gAnKORdHWX1QBbSZZB+biFYPFti8aKIQL7otCE1pjyPaXpFzGeG2OS2w==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -828,12 +834,13 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.14.tgz", - "integrity": "sha512-7TcQCvLQ/hKfQRgjxMN4TZ2BRB0P7HwrGAYL+p+m3u3XcKTraUFerVbV3jkNZNwDeQDa8zdxkKkw2els/S5onQ==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.3.tgz", + "integrity": "sha512-QQEMwFd8r7C0GxQS62Zcdy6GKx999I/rTO2ubdXEe+MlZk9ZiinsrjwoiBL5/57tfyjikgh6GOU2WRQVUej3UA==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -843,27 +850,13 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.14.tgz", - "integrity": "sha512-8i0Ou5XjTLEje0oj0JiI0Xo9L/93ghFtAUYZ24jARSeTMXLUx8yFIdhS55mTExq5Tj4/dC2fJuaT4e3ySvXU1A==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.3.tgz", + "integrity": "sha512-9TEp47AAd/ms9fPNgtgnT7F3M1Hf7koIYYWCMQ9neOwjbVWJsHZxrFbI3iEDJ8rf1TDGpmHbKxXf2IFpAvheIQ==", "cpu": [ "arm64" ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.14.tgz", - "integrity": "sha512-2u2XcSaDEOj+96eXpyjHjtVPLhkAFw2nlaz83EPeuK4obF+HmtDJHqgR1dZB7Gb6V/d55FL26/lYVd0TwMgcOQ==", - "cpu": [ - "ia32" - ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -873,12 +866,13 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.14.tgz", - "integrity": "sha512-MZom+OvZ1NZxuRovKt1ApevjiUJTcU2PmdJKL66xUPaJeRywnbGGRWUlaAOwunD6dX+pm83vj979NTC8QXjGWg==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.3.tgz", + "integrity": "sha512-VNAz+HN4OGgvZs6MOoVfnn41kBzT+M+tB+OK4cww6DNyWS6wKaDpaAm/qLeOUbnMh0oVx1+mg0uoYARF69dJyA==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -1588,14 +1582,15 @@ "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", + "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", + "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, @@ -2469,7 +2464,8 @@ "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" }, "node_modules/cliui": { "version": "6.0.0", @@ -2603,15 +2599,16 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4011,7 +4008,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -5893,40 +5891,42 @@ "dev": true }, "node_modules/next": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.14.tgz", - "integrity": "sha512-Q1coZG17MW0Ly5x76shJ4dkC23woLAhhnDnw+DfTc7EpZSGuWrlsZ3bZaO8t6u1Yu8FVfhkqJE+U8GC7E0GLPQ==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/next/-/next-15.0.3.tgz", + "integrity": "sha512-ontCbCRKJUIoivAdGB34yCaOcPgYXr9AAkV/IwqFfWWTXEPUgLYkSkqBhIk9KK7gGmgjc64B+RdoeIDM13Irnw==", + "license": "MIT", "dependencies": { - "@next/env": "14.2.14", - "@swc/helpers": "0.5.5", + "@next/env": "15.0.3", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.13", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1" + "styled-jsx": "5.1.6" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=18.17.0" + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.14", - "@next/swc-darwin-x64": "14.2.14", - "@next/swc-linux-arm64-gnu": "14.2.14", - "@next/swc-linux-arm64-musl": "14.2.14", - "@next/swc-linux-x64-gnu": "14.2.14", - "@next/swc-linux-x64-musl": "14.2.14", - "@next/swc-win32-arm64-msvc": "14.2.14", - "@next/swc-win32-ia32-msvc": "14.2.14", - "@next/swc-win32-x64-msvc": "14.2.14" + "@next/swc-darwin-arm64": "15.0.3", + "@next/swc-darwin-x64": "15.0.3", + "@next/swc-linux-arm64-gnu": "15.0.3", + "@next/swc-linux-arm64-musl": "15.0.3", + "@next/swc-linux-x64-gnu": "15.0.3", + "@next/swc-linux-x64-musl": "15.0.3", + "@next/swc-win32-arm64-msvc": "15.0.3", + "@next/swc-win32-x64-msvc": "15.0.3", + "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-66855b96-20241106", + "react-dom": "^18.2.0 || 19.0.0-rc-66855b96-20241106", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -5936,15 +5936,19 @@ "@playwright/test": { "optional": true }, + "babel-plugin-react-compiler": { + "optional": true + }, "sass": { "optional": true } } }, "node_modules/next-auth": { - "version": "4.24.11", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.11.tgz", - "integrity": "sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==", + "version": "4.24.10", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.10.tgz", + "integrity": "sha512-8NGqiRO1GXBcVfV8tbbGcUgQkAGsX4GRzzXXea4lDikAsJtD5KiEY34bfhUOjHLvr6rT6afpcxw2H8EZqOV6aQ==", + "license": "ISC", "dependencies": { "@babel/runtime": "^7.20.13", "@panva/hkdf": "^1.0.2", @@ -7461,9 +7465,10 @@ } }, "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", "dependencies": { "client-only": "0.0.1" }, @@ -7471,7 +7476,7 @@ "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { diff --git a/package.json b/package.json index 400c15cd..dd637180 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,8 @@ "jsonwebtoken": "^9.0.2", "jsqr": "^1.4.0", "luxon": "^3.5.0", - "next": "^14.2.5", - "next-auth": "^4.24.11", + "next": "^15.0.3", + "next-auth": "^4.24.7", "next-qrcode": "^2.5.1", "nodemailer": "^6.9.16", "react": "^18.3.1", From da0e47612bb4cde870886141484aa3982d08d7ef Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Thu, 23 Jan 2025 20:19:49 +0100 Subject: [PATCH 02/12] fix: all searchParams made async for next 15 --- package-lock.json | 15 +++++++++++++++ src/app/(auth)/auth/reset-password/page.tsx | 14 ++++++++------ src/app/(auth)/register/page.tsx | 18 +++++++++--------- src/app/admin/admission/[admission]/page.tsx | 8 ++++---- src/app/admin/dots/page.tsx | 4 ++-- src/app/career/companies/page.tsx | 8 ++++---- src/app/events/archive/page.tsx | 4 ++-- src/app/events/page.tsx | 2 +- src/lib/query-params/QueryParam.ts | 2 +- src/lib/query-params/Types.ts | 2 +- src/lib/query-params/queryParams.ts | 2 ++ 11 files changed, 49 insertions(+), 30 deletions(-) diff --git a/package-lock.json b/package-lock.json index b918d077..7d107743 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8286,6 +8286,21 @@ "type": "github", "url": "https://github.com/sponsors/wooorm" } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.14", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.14.tgz", + "integrity": "sha512-2u2XcSaDEOj+96eXpyjHjtVPLhkAFw2nlaz83EPeuK4obF+HmtDJHqgR1dZB7Gb6V/d55FL26/lYVd0TwMgcOQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/src/app/(auth)/auth/reset-password/page.tsx b/src/app/(auth)/auth/reset-password/page.tsx index 976c50bf..5a7c01a4 100644 --- a/src/app/(auth)/auth/reset-password/page.tsx +++ b/src/app/(auth)/auth/reset-password/page.tsx @@ -1,18 +1,20 @@ import ResetPasswordForm from './resetpasswordForm' import { verifyResetPasswordTokenAction } from '@/actions/auth/resetPassword' +import { QueryParams } from '@/lib/query-params/queryParams' +import type { SearchParamsServerSide } from '@/lib/query-params/Types' -type PropTypes = { - searchParams: Record -} +type PropTypes = SearchParamsServerSide export default async function ResetPassword({ searchParams }: PropTypes) { - if (!searchParams.token || typeof searchParams.token !== 'string') { + const token = QueryParams.token.decode(await searchParams) + + if (!token) { return <>

Ops

Token mangler

} - const verify = await verifyResetPasswordTokenAction(searchParams.token) + const verify = await verifyResetPasswordTokenAction(token) if (!verify.success) { const errorMessage = verify.error?.map(e => e.message).join('\n') ?? 'JWT er ugyldig' @@ -23,5 +25,5 @@ export default async function ResetPassword({ searchParams }: PropTypes) { } - return + return } diff --git a/src/app/(auth)/register/page.tsx b/src/app/(auth)/register/page.tsx index bb5af77d..ae39bb00 100644 --- a/src/app/(auth)/register/page.tsx +++ b/src/app/(auth)/register/page.tsx @@ -4,14 +4,11 @@ import { getUser } from '@/auth/getUser' import { verifyUserEmailAction } from '@/actions/users/update' import { readUser } from '@/services/users/read' import { safeServerCall } from '@/actions/safeServerCall' +import { QueryParams } from '@/lib/query-params/queryParams' import { notFound, redirect } from 'next/navigation' +import type { SearchParamsServerSide } from '@/lib/query-params/Types' -type PropTypes = { - searchParams: { - token?: string, - callbackUrl?: string, - } -} +type PropTypes = SearchParamsServerSide export default async function Register({ searchParams }: PropTypes) { const { user, authorized } = await getUser({ @@ -22,8 +19,11 @@ export default async function Register({ searchParams }: PropTypes) { let userId = user?.id let shouldLogOut = false - if (typeof searchParams.token === 'string') { - const verify = await verifyUserEmailAction(searchParams.token) + const token = QueryParams.token.decode(await searchParams) + const callbackUrl = QueryParams.callbackUrl.decode(await searchParams) + + if (token) { + const verify = await verifyUserEmailAction(token) if (!verify.success) { redirect('./register') } @@ -43,7 +43,7 @@ export default async function Register({ searchParams }: PropTypes) { } if (updatedUser.data.acceptedTerms) { - redirect(searchParams.callbackUrl ?? '/users/me') + redirect(callbackUrl ?? '/users/me') } if (!updatedUser.data.emailVerified) { diff --git a/src/app/admin/admission/[admission]/page.tsx b/src/app/admin/admission/[admission]/page.tsx index 16ad7034..bd7b3ba0 100644 --- a/src/app/admin/admission/[admission]/page.tsx +++ b/src/app/admin/admission/[admission]/page.tsx @@ -8,16 +8,16 @@ import { type Admission as AdmissionType } from '@prisma/client' import { notFound } from 'next/navigation' type PropTypes = { - params: { + params: Promise<{ admission: AdmissionType - } + }> } export default async function AdmissionTrials({ params }: PropTypes) { - if (!AdmissionsArray.includes(params.admission)) { + if (!AdmissionsArray.includes((await params).admission)) { notFound() } - const admission = params.admission + const admission = (await params).admission const publicKey = await readOmegaJWTPublicKey() diff --git a/src/app/admin/dots/page.tsx b/src/app/admin/dots/page.tsx index c8b0ef23..27a2bee3 100644 --- a/src/app/admin/dots/page.tsx +++ b/src/app/admin/dots/page.tsx @@ -11,8 +11,8 @@ import type { SearchParamsServerSide } from '@/lib/query-params/Types' type PropTypes = SearchParamsServerSide export default async function Dots({ searchParams }: PropTypes) { - const onlyActive = QueryParams.onlyActive.decode(searchParams) ?? false - const userId = QueryParams.userId.decode(searchParams) + const onlyActive = QueryParams.onlyActive.decode(await searchParams) ?? false + const userId = QueryParams.userId.decode(await searchParams) return (
diff --git a/src/app/career/companies/page.tsx b/src/app/career/companies/page.tsx index ee164266..91e4d302 100644 --- a/src/app/career/companies/page.tsx +++ b/src/app/career/companies/page.tsx @@ -17,10 +17,10 @@ type PropTypes = SearchParamsServerSide export default async function page({ searchParams }: PropTypes) { const pageSize = 10 satisfies PageSizeCompany - const name = QueryParams.companyName.decode(searchParams) ?? undefined - // TODO: Decide how getting session in pages should be done. Are we going away form useUser/getUser? + const name = QueryParams.companyName.decode(await searchParams) ?? undefined + const session = await Session.fromNextAuth() - const res = await readCompanyPageAction({ + const res = await readCompanyPageAction.bind(null, { paging: { page: { page: 0, @@ -31,7 +31,7 @@ export default async function page({ searchParams }: PropTypes) { name }, }, - }) + })() const serverRenderedData = res.success ? res.data : [] return ( diff --git a/src/app/events/archive/page.tsx b/src/app/events/archive/page.tsx index 035fd26e..b2394ffc 100644 --- a/src/app/events/archive/page.tsx +++ b/src/app/events/archive/page.tsx @@ -14,7 +14,7 @@ type PropTypes = SearchParamsServerSide export default async function EventArchive({ searchParams }: PropTypes) { - const selectedTagNames = QueryParams.eventTags.decode(searchParams) + const selectedTagNames = QueryParams.eventTags.decode(await searchParams) const eventTagsResponse = await readEventTagsAction() if (!eventTagsResponse.success) { throw new Error('Failed to read current events') @@ -47,7 +47,7 @@ export default async function EventArchive({ + }} details={{ tags: QueryParams.eventTags.decode(await searchParams) }}> diff --git a/src/app/events/page.tsx b/src/app/events/page.tsx index 33dee593..5feb9851 100644 --- a/src/app/events/page.tsx +++ b/src/app/events/page.tsx @@ -17,7 +17,7 @@ type PropTypes = SearchParamsServerSide export default async function Events({ searchParams }: PropTypes) { - const tagNames = QueryParams.eventTags.decode(searchParams) + const tagNames = QueryParams.eventTags.decode(await searchParams) const currentEventsResponse = await readCurrentEventsAction({ tags: tagNames }) const eventTagsResponse = await readEventTagsAction() diff --git a/src/lib/query-params/QueryParam.ts b/src/lib/query-params/QueryParam.ts index dd0d2dec..20e30a3a 100644 --- a/src/lib/query-params/QueryParam.ts +++ b/src/lib/query-params/QueryParam.ts @@ -12,7 +12,7 @@ export abstract class QueryParam { return `${this.name}=${encodeURIComponent(this.encode(value))}` } abstract decodeValue(value: string | string[] | undefined): Type | null - public decode(searchParams: SearchParamsServerSide['searchParams']): Type | null { + public decode(searchParams: Awaited): Type | null { if (!searchParams) { return null } diff --git a/src/lib/query-params/Types.ts b/src/lib/query-params/Types.ts index ea0b916c..f75ad7f1 100644 --- a/src/lib/query-params/Types.ts +++ b/src/lib/query-params/Types.ts @@ -1,3 +1,3 @@ export type SearchParamsServerSide = { - searchParams?: { [key: string]: string | string[] | undefined } + searchParams?: Promise<{ [key: string]: string | string[] | undefined }> } diff --git a/src/lib/query-params/queryParams.ts b/src/lib/query-params/queryParams.ts index 10af5079..b5b2f54b 100644 --- a/src/lib/query-params/queryParams.ts +++ b/src/lib/query-params/queryParams.ts @@ -5,6 +5,8 @@ export const QueryParams = { onlyActive: new BooleanQueryParam('only-active'), userId: new NumberQueryParam('user-id'), companyName: new StringQueryParam('company-name'), + token: new StringQueryParam('token'), + callbackUrl: new StringQueryParam('callbackUrl'), } as const satisfies Record> export type QueryParamNames = typeof QueryParams[keyof typeof QueryParams]['name'] From af10a6a14f4962447d6ff1af4d26e3297476a1e1 Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:35:30 +0100 Subject: [PATCH 03/12] fix: all params made async in page and layout --- src/app/admin/api-keys/[name]/page.tsx | 6 +++--- src/app/admin/cms/[...path]/page.tsx | 8 ++++---- src/app/admin/groups/[id]/page.tsx | 6 +++--- src/app/admin/mail/[filter]/[id]/page.tsx | 18 +++++++++--------- .../notification-channels/[currentId]/page.tsx | 13 +++++++------ src/app/admin/schools/[shortname]/page.tsx | 6 +++--- src/app/api/apiHandler.ts | 12 ++++++------ src/app/articles/[category]/[name]/page.tsx | 8 ++++---- src/app/articles/[category]/layout.tsx | 6 +++--- src/app/articles/[category]/page.tsx | 6 +++--- .../career/jobads/[...orderAndName]/page.tsx | 11 ++++++----- src/app/committees/[shortName]/about/page.tsx | 6 +++--- src/app/committees/[shortName]/getCommittee.ts | 2 +- src/app/committees/[shortName]/layout.tsx | 6 +++--- src/app/committees/[shortName]/page.tsx | 6 +++--- src/app/events/[order]/[name]/page.tsx | 9 +++++---- src/app/images/collections/[id]/page.tsx | 6 +++--- src/app/lockers/[id]/page.tsx | 8 ++++---- src/app/news/[...orderAndName]/page.tsx | 10 +++++----- src/app/ombul/[...yearAndName]/page.tsx | 10 +++++----- src/app/screens/[name]/page.tsx | 6 +++--- .../[username]/(user-admin)/dots/page.tsx | 12 +++++++++--- .../(user-admin)/getProfileForAdmin.ts | 16 +++++++--------- .../users/[username]/(user-admin)/layout.tsx | 4 ++-- .../(user-admin)/notifications/page.tsx | 7 ++++--- .../(user-admin)/permissions/page.tsx | 7 ++++--- .../[username]/(user-admin)/settings/page.tsx | 7 ++++--- src/app/users/[username]/page.tsx | 12 ++++++------ 28 files changed, 122 insertions(+), 112 deletions(-) diff --git a/src/app/admin/api-keys/[name]/page.tsx b/src/app/admin/api-keys/[name]/page.tsx index 8683a2ec..e72cf799 100644 --- a/src/app/admin/api-keys/[name]/page.tsx +++ b/src/app/admin/api-keys/[name]/page.tsx @@ -11,13 +11,13 @@ import { destroyApiKeyAction } from '@/actions/api-keys/destroy' import Date from '@/app/_components/Date/Date' type PropTypes = { - params: { + params: Promise<{ name: string - } + }> } export default async function ApiKeyAdmin({ params }: PropTypes) { - const res = await readApiKeyAction(decodeURIComponent(params.name)) + const res = await readApiKeyAction(decodeURIComponent((await params).name)) if (!res.success) throw new Error(res.error?.length ? res.error[0].message : 'En feil har oppstått') const apiKey = res.data diff --git a/src/app/admin/cms/[...path]/page.tsx b/src/app/admin/cms/[...path]/page.tsx index 27cb02a4..bb66a4ad 100644 --- a/src/app/admin/cms/[...path]/page.tsx +++ b/src/app/admin/cms/[...path]/page.tsx @@ -1,11 +1,11 @@ type PropTypes = { - params: { + params: Promise<{ path: string[], - }, + }>, } -export default function EditPath({ params }: PropTypes) { - const path = params.path.join('/') +export default async function EditPath({ params }: PropTypes) { + const path = (await params).path.join('/') //check that path exists. return <>Edit: {path} } diff --git a/src/app/admin/groups/[id]/page.tsx b/src/app/admin/groups/[id]/page.tsx index d4104bdf..3450d6fe 100644 --- a/src/app/admin/groups/[id]/page.tsx +++ b/src/app/admin/groups/[id]/page.tsx @@ -9,13 +9,13 @@ import { readGroupExpandedAction } from '@/actions/groups/read' import Link from 'next/link' type PropTypes = { - params: { + params: Promise<{ id: string - } + }> } export default async function GroupAdmin({ params }: PropTypes) { - const groupRes = await readGroupExpandedAction(parseInt(params.id, 10)) + const groupRes = await readGroupExpandedAction(parseInt((await params).id, 10)) if (!groupRes.success) throw new Error('Failed to load group') const group = groupRes.data diff --git a/src/app/admin/mail/[filter]/[id]/page.tsx b/src/app/admin/mail/[filter]/[id]/page.tsx index 15d071ed..a71472b8 100644 --- a/src/app/admin/mail/[filter]/[id]/page.tsx +++ b/src/app/admin/mail/[filter]/[id]/page.tsx @@ -13,24 +13,24 @@ import PageWrapper from '@/components/PageWrapper/PageWrapper' import { notFound } from 'next/navigation' import type { MailListTypes } from '@/services/mail/Types' -export default async function MailFlowPage({ - params -}: { - params: { +type PropTypes = { + params: Promise<{ filter: string, id: string, - } -}) { - if (!MailListTypeArray.includes(params.filter as MailListTypes)) { + }> +} + +export default async function MailFlowPage({ params }: PropTypes) { + if (!MailListTypeArray.includes((await params).filter as MailListTypes)) { notFound() } - const id = Number(params.id) + const id = Number((await params).id) if (!id || id <= 0) { notFound() } - const filter = params.filter as MailListTypes + const filter = (await params).filter as MailListTypes const [results, mailOptions] = await Promise.all([ readMailFlowAction(filter, id), diff --git a/src/app/admin/notification-channels/[currentId]/page.tsx b/src/app/admin/notification-channels/[currentId]/page.tsx index 278449f0..25709481 100644 --- a/src/app/admin/notification-channels/[currentId]/page.tsx +++ b/src/app/admin/notification-channels/[currentId]/page.tsx @@ -4,12 +4,13 @@ import { readNotificationChannelsAction } from '@/actions/notifications/channel/ import { readMailAliasesAction } from '@/actions/mail/alias/read' import { notFound } from 'next/navigation' - -export default async function Channels({ params }: { - params: { +type PropTypes = { + params: Promise<{ currentId: string - } -}) { + }> +} + +export default async function Channels({ params }: PropTypes) { const [channels, mailAliases] = await Promise.all([ readNotificationChannelsAction(), readMailAliasesAction(), @@ -20,7 +21,7 @@ export default async function Channels({ params }: { notFound() } - const currentId = Number(params.currentId) + const currentId = Number((await params).currentId) const selected = channels.data.find(c => c.id === currentId) if (!selected) { diff --git a/src/app/admin/schools/[shortname]/page.tsx b/src/app/admin/schools/[shortname]/page.tsx index 04788f7d..ee58be7b 100644 --- a/src/app/admin/schools/[shortname]/page.tsx +++ b/src/app/admin/schools/[shortname]/page.tsx @@ -7,13 +7,13 @@ import PageWrapper from '@/components/PageWrapper/PageWrapper' import School from '@/components/School/School' type PropTypes = { - params: { + params: Promise<{ shortname: string - } + }> } export default async function SchoolAdmin({ params }: PropTypes) { - const shortname = decodeURIComponent(params.shortname) + const shortname = decodeURIComponent((await params).shortname) const res = await readSchoolAction(shortname) if (!res.success) throw new Error(res.error?.length ? res.error[0].message : 'Unknown error') diff --git a/src/app/api/apiHandler.ts b/src/app/api/apiHandler.ts index 78ec21c6..5997e76b 100644 --- a/src/app/api/apiHandler.ts +++ b/src/app/api/apiHandler.ts @@ -44,7 +44,7 @@ export function apiHandler< DataValidation extends ValidationTypeUnknown | undefined = undefined, >({ serviceMethod, params }: APIHandler) { // TODO: I think I will rewrite this to be easier to read - return async (req: Request, { params: rawParams }: { params: RawParams }) => + return async (req: Request, { params: rawParams }: { params: Promise }) => await apiHandlerGeneric(req, async session => { if (serviceMethod.dataValidation) { try { @@ -53,20 +53,20 @@ export function apiHandler< const parse = serviceMethod.dataValidation.typeValidate(rawdata) if (!parse.success) throw new ServerError('BAD PARAMETERS', parse.error.errors) return serviceMethod.newClient().executeUnsafe({ - params: params ? params(rawParams) : undefined, + params: params ? params(await rawParams) : undefined, data: parse.data, session, }) - } catch (e) { - if (e instanceof SyntaxError) { + } catch (error) { + if (error instanceof SyntaxError) { throw new ServerError('BAD DATA', 'The API only accepts valid json data.') } - throw e + throw error } } return serviceMethod.newClient().executeUnsafe({ - params: params ? params(rawParams) : undefined, + params: params ? params(await rawParams) : undefined, data: undefined, session, }) diff --git a/src/app/articles/[category]/[name]/page.tsx b/src/app/articles/[category]/[name]/page.tsx index ab0a446c..b4b8a4e7 100644 --- a/src/app/articles/[category]/[name]/page.tsx +++ b/src/app/articles/[category]/[name]/page.tsx @@ -4,16 +4,16 @@ import { readArticleAction } from '@/cms/articles/read' import { notFound } from 'next/navigation' type PropTypes = { - params: { + params: Promise<{ category: string name: string - }, + }>, } export default async function ArticleCategorArticley({ params }: PropTypes) { //This fixes æ, ø, å and spaces in the url - const name = decodeURIComponent(params.name) - const category = decodeURIComponent(params.category) + const name = decodeURIComponent((await params).name) + const category = decodeURIComponent((await params).category) const res = await readArticleAction({ name, category diff --git a/src/app/articles/[category]/layout.tsx b/src/app/articles/[category]/layout.tsx index ecdb6160..3337753c 100644 --- a/src/app/articles/[category]/layout.tsx +++ b/src/app/articles/[category]/layout.tsx @@ -5,14 +5,14 @@ import { notFound } from 'next/navigation' import type { ReactNode } from 'react' type PropTypes = { - params: { + params: Promise<{ category: string - } + }>, children: ReactNode, } export default async function ArticleCategoryLayout({ params, children }: PropTypes) { - const categoryName = decodeURIComponent(params.category) + const categoryName = decodeURIComponent((await params).category) const res = await readArticleCategoryAction(categoryName) if (!res.success) return notFound() const category = res.data diff --git a/src/app/articles/[category]/page.tsx b/src/app/articles/[category]/page.tsx index 0bf46d79..23bdc909 100644 --- a/src/app/articles/[category]/page.tsx +++ b/src/app/articles/[category]/page.tsx @@ -1,13 +1,13 @@ import styles from './page.module.scss' type PropTypes = { - params: { + params: Promise<{ category: string - }, + }>, } export default async function ArticleCategory({ params }: PropTypes) { - const category = decodeURIComponent(params.category) + const category = decodeURIComponent((await params).category) return (

{category.toUpperCase()}

diff --git a/src/app/career/jobads/[...orderAndName]/page.tsx b/src/app/career/jobads/[...orderAndName]/page.tsx index daeffd9e..e2bbff79 100644 --- a/src/app/career/jobads/[...orderAndName]/page.tsx +++ b/src/app/career/jobads/[...orderAndName]/page.tsx @@ -21,19 +21,20 @@ import { } from '@fortawesome/free-solid-svg-icons' type PropTypes = { - params: { + params: Promise<{ orderAndName: string[] - } + }> } export default async function JobAd({ params }: PropTypes) { - if (params.orderAndName.length !== 2) notFound() - const order = parseInt(decodeURIComponent(params.orderAndName[0]), 10) - const name = decodeURIComponent(params.orderAndName[1]) + if ((await params).orderAndName.length !== 2) notFound() + const order = parseInt(decodeURIComponent((await params).orderAndName[0]), 10) + const name = decodeURIComponent((await params).orderAndName[1]) const session = await Session.fromNextAuth() const jobAdRes = await readJobAdAction({ idOrName: { articleName: name, order } }) if (!jobAdRes.success) { + //TODO: Handle error in idiomatic way if (jobAdRes.errorCode === 'NOT FOUND') notFound() throw new Error('Failed to read jobAd') } diff --git a/src/app/committees/[shortName]/about/page.tsx b/src/app/committees/[shortName]/about/page.tsx index 40d8b7a0..817e7127 100644 --- a/src/app/committees/[shortName]/about/page.tsx +++ b/src/app/committees/[shortName]/about/page.tsx @@ -3,13 +3,13 @@ import { readCommitteeArticleAction } from '@/actions/groups/committees/read' import Article from '@/components/Cms/Article/Article' export type PropTypes = { - params: { + params: Promise<{ shortName: string - } + }> } export default async function committeeArticle({ params }: PropTypes) { - const committeeArticleRes = await readCommitteeArticleAction(params.shortName) + const committeeArticleRes = await readCommitteeArticleAction((await params).shortName) if (!committeeArticleRes.success) throw new Error('Kunne ikke hente komitéartikkel') const article = committeeArticleRes.data diff --git a/src/app/committees/[shortName]/getCommittee.ts b/src/app/committees/[shortName]/getCommittee.ts index bde98a07..d38c24ba 100644 --- a/src/app/committees/[shortName]/getCommittee.ts +++ b/src/app/committees/[shortName]/getCommittee.ts @@ -8,7 +8,7 @@ import type { PropTypes } from './page' * @returns */ export default async function getCommittee(params: PropTypes['params']) { - const name = decodeURIComponent(params.shortName) + const name = decodeURIComponent((await params).shortName) const res = await readCommitteeAction({ shortName: name }) if (!res.success) notFound() return res.data diff --git a/src/app/committees/[shortName]/layout.tsx b/src/app/committees/[shortName]/layout.tsx index 848ee28d..cb6e49bc 100644 --- a/src/app/committees/[shortName]/layout.tsx +++ b/src/app/committees/[shortName]/layout.tsx @@ -8,9 +8,9 @@ import CommitteeImage from '@/components/CommitteeImage/CommitteeImage' import type { ReactNode } from 'react' export type PropTypes = { - params: { + params: Promise<{ shortName: string - }, + }>, children: ReactNode } @@ -35,7 +35,7 @@ export default async function Committee({ params, children }: PropTypes) { { children }
diff --git a/src/app/committees/[shortName]/page.tsx b/src/app/committees/[shortName]/page.tsx index 0a26596f..31006262 100644 --- a/src/app/committees/[shortName]/page.tsx +++ b/src/app/committees/[shortName]/page.tsx @@ -3,13 +3,13 @@ import { readCommitteeParagraphAction } from '@/actions/groups/committees/read' import CmsParagraph from '@/components/Cms/CmsParagraph/CmsParagraph' export type PropTypes = { - params: { + params: Promise<{ shortName: string - } + }> } export default async function Committee({ params }: PropTypes) { - const paragraphRes = await readCommitteeParagraphAction(params.shortName) + const paragraphRes = await readCommitteeParagraphAction((await params).shortName) if (!paragraphRes.success) throw new Error('Kunne ikke hente komitéparagraph') const paragraph = paragraphRes.data diff --git a/src/app/events/[order]/[name]/page.tsx b/src/app/events/[order]/[name]/page.tsx index bf0e63e8..45e7d642 100644 --- a/src/app/events/[order]/[name]/page.tsx +++ b/src/app/events/[order]/[name]/page.tsx @@ -17,19 +17,20 @@ import { faCalendar, faExclamation, faUsers } from '@fortawesome/free-solid-svg- import Link from 'next/link' type PropTypes = { - params: { + params: Promise<{ order: string, name: string - } + }> } export default async function Event({ params }: PropTypes) { const eventRes = await readEventAction({ - name: decodeURIComponent(params.name), - order: parseInt(params.order, 10) + name: decodeURIComponent((await params).name), + order: parseInt((await params).order, 10) }) const tagsRes = await readEventTagsAction() if (!eventRes.success || !tagsRes.success) { + //TODO: Handle error in idiomatic way throw new Error('Failed to read event') } const event = eventRes.data diff --git a/src/app/images/collections/[id]/page.tsx b/src/app/images/collections/[id]/page.tsx index c1ba6bbc..dfcf60a1 100644 --- a/src/app/images/collections/[id]/page.tsx +++ b/src/app/images/collections/[id]/page.tsx @@ -10,15 +10,15 @@ import { notFound } from 'next/navigation' import type { PageSizeImage } from '@/contexts/paging/ImagePaging' type PropTypes = { - params: { + params: Promise<{ id: string - } + }> } export default async function Collection({ params }: PropTypes) { const pageSize: PageSizeImage = 30 - const readCollection = await readImageCollectionAction(Number(params.id)) + const readCollection = await readImageCollectionAction(Number((await params).id)) if (!readCollection.success) notFound() //TODO: replace with better error page if error is UNAUTHORIZED. const collection = readCollection.data diff --git a/src/app/lockers/[id]/page.tsx b/src/app/lockers/[id]/page.tsx index b554ca2b..81d81547 100644 --- a/src/app/lockers/[id]/page.tsx +++ b/src/app/lockers/[id]/page.tsx @@ -9,9 +9,9 @@ import { checkGroupValidity, inferGroupName, readGroupsOfUser } from '@/services type PropTypes = { - params: { + params: Promise<{ id: string - } + }> } export default async function Locker({ params }: PropTypes) { @@ -22,7 +22,7 @@ export default async function Locker({ params }: PropTypes) { }) if (!authorized) return Error(status) - const lockerId = parseInt(params.id, 10) + const lockerId = parseInt((await params).id, 10) const locker = await readLockerAction(lockerId) if (!locker.success) { @@ -58,7 +58,7 @@ export default async function Locker({ params }: PropTypes) { return (
-

Skap nr. {params.id}

+

Skap nr. {(await params).id}

{locker.data.building} {locker.data.floor}. etasje

{ isReserved diff --git a/src/app/news/[...orderAndName]/page.tsx b/src/app/news/[...orderAndName]/page.tsx index 8fb67570..e2f43358 100644 --- a/src/app/news/[...orderAndName]/page.tsx +++ b/src/app/news/[...orderAndName]/page.tsx @@ -7,15 +7,15 @@ import SlideInOnView from '@/components/SlideInOnView/SlideInOnView' import { notFound } from 'next/navigation' type PropTypes = { - params: { + params: Promise<{ orderAndName: string[] - } + }> } export default async function NewsArticle({ params }: PropTypes) { - const order = parseInt(decodeURIComponent(params.orderAndName[0]), 10) - const name = decodeURIComponent(params.orderAndName[1]) - if (!order || !name || params.orderAndName.length > 2) notFound() + const order = parseInt(decodeURIComponent((await params).orderAndName[0]), 10) + const name = decodeURIComponent((await params).orderAndName[1]) + if (!order || !name || (await params).orderAndName.length > 2) notFound() const res = await readNewsAction({ articleName: name, order, diff --git a/src/app/ombul/[...yearAndName]/page.tsx b/src/app/ombul/[...yearAndName]/page.tsx index 0da29930..85658fb2 100644 --- a/src/app/ombul/[...yearAndName]/page.tsx +++ b/src/app/ombul/[...yearAndName]/page.tsx @@ -12,9 +12,9 @@ import Link from 'next/link' import { notFound } from 'next/navigation' type PropTypes = { - params: { + params: Promise<{ yearAndName: string[] - } + }> } export default async function Ombul({ params }: PropTypes) { @@ -23,9 +23,9 @@ export default async function Ombul({ params }: PropTypes) { shouldRedirect: true, }) - const year = parseInt(decodeURIComponent(params.yearAndName[0]), 10) - const name = decodeURIComponent(params.yearAndName[1]) - if (!year || !name || params.yearAndName.length > 2) notFound() + const year = parseInt(decodeURIComponent((await params).yearAndName[0]), 10) + const name = decodeURIComponent((await params).yearAndName[1]) + if (!year || !name || (await params).yearAndName.length > 2) notFound() const ombulRes = await readOmbulAction({ name, year diff --git a/src/app/screens/[name]/page.tsx b/src/app/screens/[name]/page.tsx index 2aea2022..11c82fe0 100644 --- a/src/app/screens/[name]/page.tsx +++ b/src/app/screens/[name]/page.tsx @@ -1,13 +1,13 @@ import styles from './page.module.scss' type PropTypes = { - params: { + params: Promise<{ name: string - } + }> } export default async function screen({ params }: PropTypes) { - decodeURIComponent(params.name) + decodeURIComponent((await params).name) return (
diff --git a/src/app/users/[username]/(user-admin)/dots/page.tsx b/src/app/users/[username]/(user-admin)/dots/page.tsx index 8bea697b..2267e6b2 100644 --- a/src/app/users/[username]/(user-admin)/dots/page.tsx +++ b/src/app/users/[username]/(user-admin)/dots/page.tsx @@ -2,11 +2,17 @@ import styles from './page.module.scss' import { readDotWrappersForUserAction } from '@/actions/dots/read' import { unwrapActionReturn } from '@/app/redirectToErrorPage' -import { getProfileForAdmin, type PropTypes } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' +import { getProfileForAdmin } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' import Date from '@/components/Date/Date' -export default async function UserDotAdmin(params: PropTypes) { - const { profile } = await getProfileForAdmin(params, 'dots') +type PropTypes = { + params: Promise<{ + username: string + }> +} + +export default async function UserDotAdmin({ params }: PropTypes) { + const { profile } = await getProfileForAdmin(await params, 'dots') const dotWrappers = unwrapActionReturn( await readDotWrappersForUserAction({ userId: profile.user.id }) ) diff --git a/src/app/users/[username]/(user-admin)/getProfileForAdmin.ts b/src/app/users/[username]/(user-admin)/getProfileForAdmin.ts index fc22bcc2..7a985297 100644 --- a/src/app/users/[username]/(user-admin)/getProfileForAdmin.ts +++ b/src/app/users/[username]/(user-admin)/getProfileForAdmin.ts @@ -3,10 +3,8 @@ import { Session } from '@/auth/Session' import { userProfileUpdateAuther } from '@/services/users/authers' import { notFound, redirect } from 'next/navigation' -export type PropTypes = { - params: { - username: string - } +type Params = { + username: string } /** @@ -16,17 +14,17 @@ export type PropTypes = { * @param adminPage - The page that the user is being seen on. Used to rediret if the user is not authorized currently. * @returns - The profile being seen and the session of the current user. */ -export async function getProfileForAdmin({ params }: PropTypes, adminPage: string) { +export async function getProfileForAdmin({ username }: Params, adminPage: string) { const session = await Session.fromNextAuth() - if (params.username === 'me') { + if (username === 'me') { if (!session.user) return notFound() redirect(`/users/${session.user.username}/${adminPage}`) //This throws. } userProfileUpdateAuther - .dynamicFields({ username: params.username }) + .dynamicFields({ username }) .auth(session) - .requireAuthorized({ returnUrlIfFail: `/users/${params.username}/${adminPage}` }) - const profileRes = await readUserProfileAction(params.username) + .requireAuthorized({ returnUrlIfFail: `/users/${username}/${adminPage}` }) + const profileRes = await readUserProfileAction(username) if (!profileRes.success) return notFound() const profile = profileRes.data return { profile, session } diff --git a/src/app/users/[username]/(user-admin)/layout.tsx b/src/app/users/[username]/(user-admin)/layout.tsx index c17abe6e..0738c28b 100644 --- a/src/app/users/[username]/(user-admin)/layout.tsx +++ b/src/app/users/[username]/(user-admin)/layout.tsx @@ -7,11 +7,11 @@ import PageWrapper from '@/components/PageWrapper/PageWrapper' import { notFound } from 'next/navigation' import Link from 'next/link' import type { ReactNode } from 'react' -import type { PropTypes } from './getProfileForAdmin' +import type { PropTypes } from '@/app/users/[username]/page' export default async function UserAdmin({ children, params }: PropTypes & { children: ReactNode }) { const session = await Session.fromNextAuth() - let username = params.username + let username = (await params).username if (username === 'me') { if (!session.user) return notFound() username = session.user.username diff --git a/src/app/users/[username]/(user-admin)/notifications/page.tsx b/src/app/users/[username]/(user-admin)/notifications/page.tsx index 792660c2..d03f048f 100644 --- a/src/app/users/[username]/(user-admin)/notifications/page.tsx +++ b/src/app/users/[username]/(user-admin)/notifications/page.tsx @@ -2,10 +2,11 @@ import NotificationSettings from './notificationSettings' import { readNotificationChannelsAction } from '@/actions/notifications/channel/read' import { readSubscriptionsAction } from '@/actions/notifications/subscription/read' -import { getProfileForAdmin, type PropTypes } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' +import { getProfileForAdmin } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' +import type { PropTypes } from '@/app/users/[username]/page' -export default async function Notififcations(props: PropTypes) { - const { profile } = await getProfileForAdmin(props, 'notifications') +export default async function Notififcations({ params }: PropTypes) { + const { profile } = await getProfileForAdmin(await params, 'notifications') // TODO: Make mobile friendly const [channels, subscriptions] = await Promise.all([ diff --git a/src/app/users/[username]/(user-admin)/permissions/page.tsx b/src/app/users/[username]/(user-admin)/permissions/page.tsx index 74cfe1da..4454e5ae 100644 --- a/src/app/users/[username]/(user-admin)/permissions/page.tsx +++ b/src/app/users/[username]/(user-admin)/permissions/page.tsx @@ -1,10 +1,11 @@ import styles from './page.module.scss' import Permission from '@/components/Permission/Permission' -import { getProfileForAdmin, type PropTypes } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' +import { getProfileForAdmin } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' import { v4 as uuid } from 'uuid' +import type { PropTypes } from '@/app/users/[username]/page' -export default async function UserSettings(props: PropTypes) { - const { profile } = await getProfileForAdmin(props, 'permissions') +export default async function UserSettings({ params }: PropTypes) { + const { profile } = await getProfileForAdmin(await params, 'permissions') return (
diff --git a/src/app/users/[username]/(user-admin)/settings/page.tsx b/src/app/users/[username]/(user-admin)/settings/page.tsx index b48a4ae9..b2b9ab91 100644 --- a/src/app/users/[username]/(user-admin)/settings/page.tsx +++ b/src/app/users/[username]/(user-admin)/settings/page.tsx @@ -1,9 +1,10 @@ import RegisterStudentCardButton from './RegisterStudentCardButton' -import { getProfileForAdmin, type PropTypes } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' +import { getProfileForAdmin } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' +import type { PropTypes } from '@/app/users/[username]/page' import Image from '@/components/Image/Image' -export default async function UserSettings(props: PropTypes) { - const { profile } = await getProfileForAdmin(props, 'settings') +export default async function UserSettings({ params }: PropTypes) { + const { profile } = await getProfileForAdmin(await params, 'settings') return (
diff --git a/src/app/users/[username]/page.tsx b/src/app/users/[username]/page.tsx index 41604960..e65800bc 100644 --- a/src/app/users/[username]/page.tsx +++ b/src/app/users/[username]/page.tsx @@ -15,19 +15,19 @@ import { v4 as uuid } from 'uuid' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faQrcode } from '@fortawesome/free-solid-svg-icons' -type PropTypes = { - params: { +export type PropTypes = { + params: Promise<{ username: string - }, + }>, } export default async function User({ params }: PropTypes) { const session = await Session.fromNextAuth() - if (params.username === 'me') { + if ((await params).username === 'me') { if (!session.user) return notFound() redirect(`/users/${session.user.username}`) //This throws. } - const profileRes = await readUserProfileAction(params.username) + const profileRes = await readUserProfileAction((await params).username) if (!profileRes.success) return notFound() const profile = profileRes.data @@ -52,7 +52,7 @@ export default async function User({ params }: PropTypes) { { username: profile.user.username } ).auth(session) - const showOmegaId = session.user?.username === params.username + const showOmegaId = session.user?.username === (await params).username return (
From f7003f40346a115821d5e40de878417850540986 Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:43:05 +0100 Subject: [PATCH 04/12] chore: changes spiHandler so params are awaited inside the abstraction to avoid boilerplate in api-routes --- src/app/users/[username]/(user-admin)/settings/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/users/[username]/(user-admin)/settings/page.tsx b/src/app/users/[username]/(user-admin)/settings/page.tsx index b2b9ab91..ffefa3d4 100644 --- a/src/app/users/[username]/(user-admin)/settings/page.tsx +++ b/src/app/users/[username]/(user-admin)/settings/page.tsx @@ -1,7 +1,7 @@ import RegisterStudentCardButton from './RegisterStudentCardButton' import { getProfileForAdmin } from '@/app/users/[username]/(user-admin)/getProfileForAdmin' -import type { PropTypes } from '@/app/users/[username]/page' import Image from '@/components/Image/Image' +import type { PropTypes } from '@/app/users/[username]/page' export default async function UserSettings({ params }: PropTypes) { const { profile } = await getProfileForAdmin(await params, 'settings') From d40d00f459a7a549d2f9a1fb14ecd3e6527dcedc Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Fri, 24 Jan 2025 13:27:27 +0100 Subject: [PATCH 05/12] chore: update next-auth to 4.24.11 --- package-lock.json | 24 +++++------------------- package.json | 2 +- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7d107743..3591fc66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "jsqr": "^1.4.0", "luxon": "^3.5.0", "next": "^15.0.3", - "next-auth": "^4.24.7", + "next-auth": "^4.24.11", "next-qrcode": "^2.5.1", "nodemailer": "^6.9.16", "react": "^18.3.1", @@ -2608,6 +2608,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5945,9 +5946,9 @@ } }, "node_modules/next-auth": { - "version": "4.24.10", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.10.tgz", - "integrity": "sha512-8NGqiRO1GXBcVfV8tbbGcUgQkAGsX4GRzzXXea4lDikAsJtD5KiEY34bfhUOjHLvr6rT6afpcxw2H8EZqOV6aQ==", + "version": "4.24.11", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.11.tgz", + "integrity": "sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==", "license": "ISC", "dependencies": { "@babel/runtime": "^7.20.13", @@ -8286,21 +8287,6 @@ "type": "github", "url": "https://github.com/sponsors/wooorm" } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.14", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.14.tgz", - "integrity": "sha512-2u2XcSaDEOj+96eXpyjHjtVPLhkAFw2nlaz83EPeuK4obF+HmtDJHqgR1dZB7Gb6V/d55FL26/lYVd0TwMgcOQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } } } } diff --git a/package.json b/package.json index dd637180..6e7d07b2 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "jsqr": "^1.4.0", "luxon": "^3.5.0", "next": "^15.0.3", - "next-auth": "^4.24.7", + "next-auth": "^4.24.11", "next-qrcode": "^2.5.1", "nodemailer": "^6.9.16", "react": "^18.3.1", From edde355e6217d0e45b2f72eef88e07b0e5817e45 Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Fri, 31 Jan 2025 10:08:09 +0100 Subject: [PATCH 06/12] chore: changes shop pages to use new next 15 params api --- docs | 2 +- src/app/admin/product/[productId]/page.tsx | 14 +++++++------- src/app/admin/shop/[shop]/page.tsx | 12 +++++++----- src/app/admin/shop/page.tsx | 2 +- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs b/docs index 3cc94e53..97b8ef60 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 3cc94e532274ee194ac05edb33b76980e415b3dd +Subproject commit 97b8ef607aa78cc38d04c030fabd8d55806cd1df diff --git a/src/app/admin/product/[productId]/page.tsx b/src/app/admin/product/[productId]/page.tsx index 9921ca3d..9cd5b293 100644 --- a/src/app/admin/product/[productId]/page.tsx +++ b/src/app/admin/product/[productId]/page.tsx @@ -7,14 +7,14 @@ import { v4 as uuid } from 'uuid' import Link from 'next/link' import { displayPrice } from '@/lib/money/convert' -export default async function ProductPage({ - params -}: { - params: { +type PropTypes = { + params: Promise<{ productId: number - } -}) { - const product = unwrapActionReturn(await readProductAction({ productId: Number(params.productId) })) + }> +} + +export default async function ProductPage({ params }: PropTypes) { + const product = unwrapActionReturn(await readProductAction({ productId: Number((await params).productId) })) return +} + +export default async function Shop({ params }: PropTypes) { + const shopId = parseInt((await params).shop, 10) if (isNaN(shopId)) notFound() const shopData = unwrapActionReturn(await readShopAction({ diff --git a/src/app/admin/shop/page.tsx b/src/app/admin/shop/page.tsx index bc7bc75b..74879a49 100644 --- a/src/app/admin/shop/page.tsx +++ b/src/app/admin/shop/page.tsx @@ -10,7 +10,7 @@ import Link from 'next/link' import { v4 as uuid } from 'uuid' -export default async function Shop() { +export default async function Shops() { const shops = unwrapActionReturn(await readShopsAction()) return Date: Thu, 6 Feb 2025 13:31:34 +0100 Subject: [PATCH 07/12] fix: form input elements using uuid causing hydration error --- src/app/_components/UI/Checkbox.tsx | 20 ++++++++++++-------- src/app/_components/UI/FileInput.tsx | 1 - src/app/_components/UI/TextInput.tsx | 13 +++++++++---- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/app/_components/UI/Checkbox.tsx b/src/app/_components/UI/Checkbox.tsx index 4ad1b151..b38791b0 100644 --- a/src/app/_components/UI/Checkbox.tsx +++ b/src/app/_components/UI/Checkbox.tsx @@ -1,35 +1,39 @@ import styles from './Checkbox.module.scss' -import { v4 as uuid } from 'uuid' import type { InputHTMLAttributes, ReactNode } from 'react' -type PropTypes = Omit, 'type'> & { +type PropTypes = Omit, 'type' | 'name' | 'id'> & { label?: string children?: ReactNode -} +} & ({ + id: string + name?: string | undefined +} | { + name: string + id?: string | undefined +}) /** - * * @param label - The label shown to user (optional) * @param children - If given, the children will be clickable as part of checkbox * @returns */ function Checkbox({ label, children, ...props }: PropTypes) { - props.id ??= `id_input_${uuid()}` + const inputId = props.id ?? props.name return (
{ children ? ( ) : ( <> - - {label && } + + {label && } ) } diff --git a/src/app/_components/UI/FileInput.tsx b/src/app/_components/UI/FileInput.tsx index e5f8fa1c..3d7e476f 100644 --- a/src/app/_components/UI/FileInput.tsx +++ b/src/app/_components/UI/FileInput.tsx @@ -1,5 +1,4 @@ 'use client' - import styles from './FileInput.module.scss' import { useState } from 'react' import { v4 as uuid } from 'uuid' diff --git a/src/app/_components/UI/TextInput.tsx b/src/app/_components/UI/TextInput.tsx index 701b43ec..28b6693b 100644 --- a/src/app/_components/UI/TextInput.tsx +++ b/src/app/_components/UI/TextInput.tsx @@ -1,16 +1,21 @@ import styles from './TextInput.module.scss' -import { v4 as uuid } from 'uuid' import type { InputHTMLAttributes } from 'react' -export type PropTypes = Omit, 'type'> & { +export type PropTypes = Omit, 'type' | 'name' | 'id'> & { label: string, type?: 'text' | 'password', color?: 'primary' | 'secondary' | 'red' | 'black' | 'white', -} +} & ({ + id: string, + name?: string | undefined, +} | { + name: string, + id?: string | undefined, +}) export default function TextInput({ label = 'default', type = 'text', color = 'black', className, ...props }: PropTypes) { - props.id ??= `id_input_${uuid()}` + props.id ??= `id_input_${props.name}` return (
From 9bfc8837f23f46765108fbaf8bf407a5f0ff5a33 Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:40:03 +0100 Subject: [PATCH 08/12] fix: move Select component to use defaultValue rather than setting selected in option to remove error --- src/app/_components/UI/Select.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/_components/UI/Select.tsx b/src/app/_components/UI/Select.tsx index 8ffa0029..57c1211a 100644 --- a/src/app/_components/UI/Select.tsx +++ b/src/app/_components/UI/Select.tsx @@ -28,11 +28,10 @@ export function SelectConstructor(valueConver }: PropTypes) { const id = uuid() - const optionElements = options.map( - (option) => @@ -45,6 +44,7 @@ export function SelectConstructor(valueConver {...props} id={id} name={name} + defaultValue={defaultValue} { ...(value ? { value } : { defaultValue }) } From 395cb539d4140475244fca6622a6b74710b61e43 Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:46:37 +0100 Subject: [PATCH 09/12] fix: unique key prop on SlideSidebar in admin layout --- src/app/admin/SlideSidebar.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/admin/SlideSidebar.tsx b/src/app/admin/SlideSidebar.tsx index 4c3be515..8ff02d1c 100644 --- a/src/app/admin/SlideSidebar.tsx +++ b/src/app/admin/SlideSidebar.tsx @@ -1,7 +1,7 @@ 'use client' import styles from './SlideSidebar.module.scss' import useOnNavigation from '@/hooks/useOnNavigation' -import { useRef, useState } from 'react' +import { Fragment, useRef, useState } from 'react' import Link from 'next/link' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { @@ -249,7 +249,7 @@ export default function SlideSidebar({ currentPath, children }: PropTypes) { From 61781ab45dbca390d9fb82f8b39f8d92685e6d65 Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:48:56 +0100 Subject: [PATCH 10/12] fix: needed in of page for study-programmes admin page --- src/app/admin/study-programmes/page.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/app/admin/study-programmes/page.tsx b/src/app/admin/study-programmes/page.tsx index 5d548da1..2ff77a5b 100644 --- a/src/app/admin/study-programmes/page.tsx +++ b/src/app/admin/study-programmes/page.tsx @@ -38,13 +38,15 @@ export default async function StudyProgrammes() { > - {canEdit && } - - - - - - + + {canEdit && } + + + + + + +
RedigerNavnKodeInstitutt kodeStart årLengde på studietDel av Omega
RedigerNavnKodeInstitutt kodeStart årLengde på studietDel av Omega
From a53f3b18665cbfbbe1f8d36d778d78761d47b24b Mon Sep 17 00:00:00 2001 From: JohanHjelsethStorstad <82723971+JohanHjelsethStorstad@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:55:07 +0100 Subject: [PATCH 11/12] style: autofix linter --- src/app/_components/UI/Select.tsx | 2 +- src/app/admin/product/[productId]/page.tsx | 2 +- src/prisma/prismaservice/src/seed.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/_components/UI/Select.tsx b/src/app/_components/UI/Select.tsx index 57c1211a..ccd8196e 100644 --- a/src/app/_components/UI/Select.tsx +++ b/src/app/_components/UI/Select.tsx @@ -28,7 +28,7 @@ export function SelectConstructor(valueConver }: PropTypes) { const id = uuid() - const optionElements = options.map(option => + const optionElements = options.map(option =>