diff --git a/e2e/helper/positioning.ts b/e2e/helper/positioning.ts index 9825b04..83c2d70 100644 --- a/e2e/helper/positioning.ts +++ b/e2e/helper/positioning.ts @@ -1,6 +1,9 @@ import { Locator } from '@playwright/test' export async function isLeftOf(leftElement: Locator, rightElement: Locator) { + await leftElement.waitFor({ state: 'visible', timeout: 15000 }) + await rightElement.waitFor({ state: 'visible', timeout: 15000 }) + const leftBox = await leftElement.boundingBox() const rightBox = await rightElement.boundingBox() diff --git a/e2e/tests/layout/header.spec.ts b/e2e/tests/layout/header.spec.ts index 76bf990..c32556f 100644 --- a/e2e/tests/layout/header.spec.ts +++ b/e2e/tests/layout/header.spec.ts @@ -12,6 +12,10 @@ test.describe('Homepage', () => { test('should navigate to the profile page', async ({ page }) => { await page.getByRole('link', { name: /Profile/i }).click() + await page.waitForURL('/profile') + + await page.waitForLoadState('networkidle') + await playwrightExpect(page).toHaveURL('/profile') await playwrightExpect(page.getByRole('heading', { name: /Profile/i })).toBeVisible() }) diff --git a/e2e/tests/profile/profile-viewing.spec.ts b/e2e/tests/profile/profile-viewing.spec.ts index 38822b7..f282aa2 100644 --- a/e2e/tests/profile/profile-viewing.spec.ts +++ b/e2e/tests/profile/profile-viewing.spec.ts @@ -6,6 +6,7 @@ test.describe('User Profile Navigation', () => { test.beforeEach(async ({ page }) => { // TODO: Login as test user await page.goto('/profile') + await page.waitForLoadState('networkidle') }) test('profile displays details on left and character roster on right', async ({ page }) => { diff --git a/next.config.ts b/next.config.ts index 242473c..491d6ac 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,16 @@ import type { NextConfig } from "next" const nextConfig: NextConfig = { - /* config options here */ + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'ui-avatars.com', + port: '', + pathname: '/api/**' + } + ] + } }; export default nextConfig diff --git a/package.json b/package.json index 871cf0a..1b370ba 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "build": "next build", "start": "next start", "lint": "next lint", + "lint:fix": "next lint --fix", "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css}\"", "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css}\"", "test": "jest", diff --git a/src/app/layout.tsx b/src/app/layout.tsx index b4ebdb4..08fabb0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,7 +2,7 @@ import type { Metadata } from 'next' import { beau_rivage, geistSans, geistMono } from './fonts' import './globals.css' import Header from '../components/layout/Header/header' -import { DataProvider } from './providers/DataProvider' +import { AppDataProvider } from '@/app/providers' export const metadata: Metadata = { title: 'SilverGuild', @@ -19,7 +19,7 @@ export default function RootLayout({ - + {/* Hard set for testing purposes */}
@@ -28,7 +28,7 @@ export default function RootLayout({ {children}
- + ) diff --git a/src/app/profile/components/CharacterRosterCard.tsx b/src/app/profile/components/CharacterRosterCard.tsx index 8156017..3724c97 100644 --- a/src/app/profile/components/CharacterRosterCard.tsx +++ b/src/app/profile/components/CharacterRosterCard.tsx @@ -1,3 +1,4 @@ +import Image from 'next/image' import { Character } from '@/types/character' interface CharacterRosterCardProps { @@ -8,9 +9,11 @@ export default function CharacterRosterCard({ character }: CharacterRosterCardPr return (
- {character.name}
diff --git a/src/app/profile/components/ProfileDetails.tsx b/src/app/profile/components/ProfileDetails.tsx index 4129ff7..d5c22a0 100644 --- a/src/app/profile/components/ProfileDetails.tsx +++ b/src/app/profile/components/ProfileDetails.tsx @@ -1,3 +1,4 @@ +import Image from 'next/image' import { User } from '@/types/user' interface ProfileDetailsProps { @@ -6,21 +7,26 @@ interface ProfileDetailsProps { export default function ProfileDetails({ user }: ProfileDetailsProps) { return ( -
+
- {user.username}
-
-
Username:
-
{user.username}
+
+
+
Username:
+
{user.username}
-
Email:
-
{user.email}
-
+
Email:
+
{user.email}
+
+
) } diff --git a/src/app/providers/DataProvider.tsx b/src/app/providers/DataProvider.tsx index 5fb46ed..221f135 100644 --- a/src/app/providers/DataProvider.tsx +++ b/src/app/providers/DataProvider.tsx @@ -1,57 +1,13 @@ 'use client' -import { createContext, useContext, useState, useEffect, ReactNode } from 'react' -import { User } from '@/types/user' -import { Character } from '@/types/character' -import { mockUser, mockCharacters } from '@/mocks' -import { fetchUser } from '@/lib/api' - -interface DataContextType { - user: User | null - setUser: (user: User | null) => void - characters: Character[] - setCharacters: (characters: Character[]) => void - loading: boolean -} +import { createContext, useContext, ReactNode } from 'react' +import { DataContextType } from '@/types' const DataContext = createContext(null) -// Toggle this to switch between mock and real data -const USE_MOCK_DATA = true - -export function DataProvider({ children, userId }: { children: ReactNode; userId: number }) { - const [user, setUser] = useState(USE_MOCK_DATA ? mockUser : null) - const [characters, setCharacters] = useState(USE_MOCK_DATA ? mockCharacters : []) - const [loading, setLoading] = useState(false) - - useEffect(() => { - if (!USE_MOCK_DATA && !userId) { - return - } - - async function loadData() { - try { - setLoading(true) - - if (USE_MOCK_DATA) { - setUser(mockUser) - setCharacters(mockCharacters) - } else { - const userData = await fetchUser(userId) - setUser(userData) - } - } catch (error) { - console.error('Failed to load data:', error) - } finally { - setLoading(false) - } - } - - loadData() - }, [userId]) - +export function DataProvider({ children, value }: { children: ReactNode; value: DataContextType }) { return ( - + {children} ) diff --git a/src/app/providers/MockDataProvider.tsx b/src/app/providers/MockDataProvider.tsx new file mode 100644 index 0000000..20ac872 --- /dev/null +++ b/src/app/providers/MockDataProvider.tsx @@ -0,0 +1,26 @@ +'use client' + +import { useState, ReactNode } from 'react' +import { DataProvider } from '@/app/providers' +import { User, Character } from '@/types' +import {mockUser, mockCharacters } from '@/mocks' + +export function MockDataProvider({ children }: { children: ReactNode}) { + const [ user, setUser ] = useState(mockUser) + const [ characters, setCharacters ] = useState(mockCharacters) + + return ( + + {children} + + ) +} diff --git a/src/app/providers/RealDataProvider.tsx b/src/app/providers/RealDataProvider.tsx new file mode 100644 index 0000000..51dd92f --- /dev/null +++ b/src/app/providers/RealDataProvider.tsx @@ -0,0 +1,55 @@ +'use client' + +import { useState, ReactNode, useEffect } from 'react' +import { DataProvider } from '@/app/providers' +import { User, Character } from '@/types' +import { fetchUser, fetchUserCharacters } from '@/lib/api' + +export function RealDataProvider({ children, userId }: { children: ReactNode, userId?: number}) { + const [ user, setUser ] = useState(null) + const [ characters, setCharacters ] = useState([]) + const [ loading, setLoading ] = useState(true) + + useEffect(() =>{ + if(!userId) { + setLoading(false) + return + } + + async function loadData() { + try { + setLoading(true) + + const [ userData, characterData ] = await Promise.all([ + fetchUser(userId!), + fetchUserCharacters(userId!) + ]) + + setUser(userData) + setCharacters(characterData) + + } catch (error) { + console.error('Failed to load data:', error) + } finally { + setLoading(false) + } + } + + loadData() + }, [userId]) + + return ( + + {children} + + ) +} diff --git a/src/app/providers/helper/AppDataProvider.tsx b/src/app/providers/helper/AppDataProvider.tsx new file mode 100644 index 0000000..d06a3e4 --- /dev/null +++ b/src/app/providers/helper/AppDataProvider.tsx @@ -0,0 +1,20 @@ +'use client' + +import { ReactNode } from 'react' +import { MockDataProvider, RealDataProvider } from '@/app/providers' + +const USE_MOCK_DATA = true + +export function AppDataProvider({ + children, + userId +}: { + children: ReactNode, + userId?: number +}) { + if(USE_MOCK_DATA) { + return {children} + } + + return {children} +} \ No newline at end of file diff --git a/src/app/providers/index.ts b/src/app/providers/index.ts new file mode 100644 index 0000000..ee7d7b0 --- /dev/null +++ b/src/app/providers/index.ts @@ -0,0 +1,4 @@ +export { AppDataProvider } from './helper/AppDataProvider' +export { DataProvider, useData } from './DataProvider' +export { RealDataProvider } from './RealDataProvider' +export { MockDataProvider } from './MockDataProvider' \ No newline at end of file diff --git a/src/components/layout/Header/header.tsx b/src/components/layout/Header/header.tsx index 7150f90..3e71121 100644 --- a/src/components/layout/Header/header.tsx +++ b/src/components/layout/Header/header.tsx @@ -1,13 +1,13 @@ import Link from 'next/link' +import Image from 'next/image' export default function Header() { return (
- {/* eslint-disable-next-line @next/next/no-img-element */} - sg_logo + sg_logo