diff --git a/app/(content)/(gaming)/games/[gameid]/page.tsx b/app/(content)/(gaming)/games/[gameid]/page.tsx index f344c53c85ff3637f45f4a596e2ca8daa00e12ad..cfded75d474797deba9d4f224db42628a6c3ca83 100644 --- a/app/(content)/(gaming)/games/[gameid]/page.tsx +++ b/app/(content)/(gaming)/games/[gameid]/page.tsx @@ -2,6 +2,7 @@ import AddGameDropdown from "@/components/add-game-dropdown" import AddGameToFavList from "@/components/addGameToFavList" import { BackHeader } from "@/components/back-header" import { GlobalLayout } from "@/components/global-layout" +import { TryAgain } from "@/components/try-again" import { AspectRatio } from "@/components/ui/aspect-ratio" import { Button } from "@/components/ui/button" import { Card } from "@/components/ui/card" @@ -15,6 +16,9 @@ import Image from "next/image" // renders a single game detail page export default async function GameDetail({ params }: { params: { gameid: string } }) { const data: IGame[] = await getGame(parseInt(params.gameid)) + + if (!data[0]) return <TryAgain /> + // TODO put to backend const date = formatDate(data[0].first_release_date * 1000) @@ -26,7 +30,7 @@ export default async function GameDetail({ params }: { params: { gameid: string }) const companies = data[0].involved_companies.map((company) => { - if (company !== data[0].involved_companies[0]) { + if (company !== data[0]?.involved_companies[0]) { return `, ${company.company.name}` } return company.company.name @@ -45,7 +49,7 @@ export default async function GameDetail({ params }: { params: { gameid: string <div className="h-64 overflow-hidden"> <AspectRatio ratio={889 / 500}> <Image - src={data[0].screenshots[0].url} + src={data[0].screenshots[0]?.url ?? ""} alt={data[0].name} fill priority @@ -113,7 +117,7 @@ export default async function GameDetail({ params }: { params: { gameid: string <Card key={i} className="aspect-[264/374] relative block"> <Image src={screenshot.url} - alt={data[0].name} + alt={data[0]?.name ?? ""} fill priority className="object-cover rounded-lg" /> diff --git a/app/api/gweets/route.ts b/app/api/gweets/route.ts index 036b8d3f26a88aff9fdb34705c7bccae42cac518..fd57494aeb959838878403c370133c0a7f60375f 100644 --- a/app/api/gweets/route.ts +++ b/app/api/gweets/route.ts @@ -160,7 +160,7 @@ export async function GET(request: Request) { }, }) - const nextId = gweets.length < take ? undefined : gweets[gweets.length - 1].id + const nextId = gweets.length < take ? undefined : gweets[gweets.length - 1]?.id return NextResponse.json({ gweets, nextId }, { status: 200 }) } catch (error) { diff --git a/components/create-gweet/components/create-gweet.tsx b/components/create-gweet/components/create-gweet.tsx index 491c57b1e6f8ff072408abb933d2cbed510cff12..2788484cad964d1e7e038de583be1353f509653f 100644 --- a/components/create-gweet/components/create-gweet.tsx +++ b/components/create-gweet/components/create-gweet.tsx @@ -114,7 +114,7 @@ export const CreateGweet = ({ const err = error as z.ZodError return toast({ variant: "destructive", - description: err.issues[0].message, + description: err.issues[0]?.message, }) } @@ -133,16 +133,18 @@ export const CreateGweet = ({ const filePath = files[i] const reader = new FileReader() - reader.readAsDataURL(filePath) + if (filePath) { + reader.readAsDataURL(filePath) - reader.onload = () => { - newImages.push({ - url: reader.result, - file: filePath, - }) + reader.onload = () => { + newImages.push({ + url: reader.result, + file: filePath, + }) - if (newImages.length === files.length) { - setChosenImages([...chosenImages, ...newImages]) + if (newImages.length === files.length) { + setChosenImages([...chosenImages, ...newImages]) + } } } } diff --git a/components/icons.tsx b/components/icons.tsx index 4c26e62a29788efefa0d39f372ab75225caaf343..e21aac5ca87c45bc50d9bb0432a5da54bd72a368 100644 --- a/components/icons.tsx +++ b/components/icons.tsx @@ -40,13 +40,9 @@ import { type Icon as LucideIcon, } from "lucide-react" -export type IconsType = { - [key: string]: LucideIcon -} - export type Icon = LucideIcon -export const Icons: IconsType = { +export const Icons = { logo: ({ ...props }: LucideProps) => ( <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}> <path d="M20.5603 25.7199V34C20.5603 35.1046 19.6649 36 18.5603 36H12.2803C11.1757 36 10.2803 35.1046 10.2803 34V25.7199L15.5127 20.5L20.5603 25.7199Z" fill="#16161A" /> diff --git a/components/nav-sidebar.tsx b/components/nav-sidebar.tsx index b8f579a029ec8e3811f75d96b540622a023f136e..382419d20e85e63beb8a84c03435612193be7059 100644 --- a/components/nav-sidebar.tsx +++ b/components/nav-sidebar.tsx @@ -1,6 +1,6 @@ "use client" -import { Icons, IconsType } from "@/components/icons" +import { Icons } from "@/components/icons" import { buttonVariants } from "@/components/ui/button" import { cn } from "@/lib/utils" import { SidebarNavItem } from "@/types" @@ -21,7 +21,7 @@ export const Sidebar = ({ items, user }: { items: SidebarNavItem[], user: User | return ( <nav className="grid items-start gap-2"> {visibleItems.map((item, index) => { - const Icon = Icons[item.icon as keyof IconsType || "arrowRight"] + const Icon = Icons[item.icon || "arrowRight"] if (item.title === "My Profile") { item.href = `/${user?.username}` } diff --git a/components/profile/api/update-profile.ts b/components/profile/api/update-profile.ts index 31540051d7affc6643639d4f5eaca831ac99fffb..7fb9c7a923b88d6dab2a05b5df3fe71631b1d6fe 100644 --- a/components/profile/api/update-profile.ts +++ b/components/profile/api/update-profile.ts @@ -15,11 +15,13 @@ export const updateProfile = async ({ let imagefileprops: { fileUrl: string; fileKey: string } = { fileUrl: '', fileKey: '' } if (profile.banner.file) { - [bannerfileprops] = await uploadFiles({ files: [profile.banner.file], endpoint: 'mediaUploader' }) + [bannerfileprops = bannerfileprops ?? { fileUrl: '', fileKey: '' }] = + await uploadFiles({ files: [profile.banner.file], endpoint: 'mediaUploader' }) } if (profile.image.file) { - [imagefileprops] = await uploadFiles({ files: [profile.image.file], endpoint: 'imageUploader' }) + [imagefileprops = imagefileprops ?? { fileUrl: '', fileKey: '' }] = + await uploadFiles({ files: [profile.image.file], endpoint: 'imageUploader' }) } const data = await fetch(`/api/users/${userId}`, { diff --git a/components/profile/components/edit-profile-modal.tsx b/components/profile/components/edit-profile-modal.tsx index d77e18860bd1da6799bd836a9a516efd079ae50d..6039e781a8b2e4d8557b2f5c8c75dc1c8ffe9c36 100644 --- a/components/profile/components/edit-profile-modal.tsx +++ b/components/profile/components/edit-profile-modal.tsx @@ -127,7 +127,7 @@ export const EditProfileModal = ({ user }: { user: IUser }) => { setImageErrorMessage("") } catch (error: any) { const err = error as z.ZodError - setImageErrorMessage(err.issues[0].message) + setImageErrorMessage(err.issues[0]?.message || "Invalid image") return } diff --git a/jest.config.mjs b/jest.config.mjs index 7079cf9e9cbc60a00b78c174d0027a0baabf3246..4e300ffbfb6e86a75fc2793b565deca61097e895 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -1,4 +1,4 @@ -import nextJest from 'next/jest.js'; +import nextJest from 'next/jest.js' // Provide the path to your Next.js app to load next.config.js and .env files in your test environment const createJestConfig = nextJest({ dir: './' }) @@ -9,14 +9,14 @@ const clientTestConfig = { testPathIgnorePatterns: ["<rootDir>/node_modules/", "<rootDir>/__tests__/api/"], setupFilesAfterEnv: ["<rootDir>/jest.setup.js"], testEnvironment: "jest-environment-jsdom", -}; +} // Custom server config to be passed to Jest. const serverTestConfig = { displayName: "server", testMatch: ["**/__tests__/api/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"], testEnvironment: "jest-environment-node", -}; +} // Add any custom config to be passed to Jest /** @type {import('jest').Config} */ @@ -26,8 +26,8 @@ const config = { collectCoverageFrom: [ '**/app/api/**', '!**/node_modules/**', - '!**/vendor/**', - ] -}; + '!**/.*/**', + ], +} -export default config; \ No newline at end of file +export default config \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index bb235f49808b3540ed07b55e2eadcfba294aa9fb..9ac6fb759ec50c66b95b3ccc21d7c3b0c93ddd37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "project_ss23_gameunity", "version": "0.2.0", + "hasInstallScript": true, "dependencies": { "@auth/prisma-adapter": "^1.0.0", "@hookform/resolvers": "^3.1.1", diff --git a/package.json b/package.json index eb931eb3d1e176e824517ba9963cb63459dd2a89..453dfa6e70a2bfb4f0321f725a97d27496c824da 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,10 @@ "build": "next build", "start": "next start", "lint": "next lint", - "preview": "prisma generate && next build && next start", + "test": "jest --coverage", + "preview": "next build && next start", "vercel-build": "prisma generate && prisma migrate deploy && next build", - "test": "jest", - "coverage": "jest --coverage" + "postinstall": "prisma generate" }, "dependencies": { "@auth/prisma-adapter": "^1.0.0", @@ -79,4 +79,4 @@ "semver": "^7.5.3", "optionator": "^0.9.3" } -} +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 88c4dbac27487a5958bba8e191da2b3239fb3232..5fc1a977fc4d22412fcdb89724f67565a1cdb4f3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,42 +1,43 @@ { - "compilerOptions": { - "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": [ - "./*" - ] + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./*" + ] + }, + "strictNullChecks": true }, - "strictNullChecks": true - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts" - ], - "exclude": [ - "node_modules" - ] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } \ No newline at end of file