diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 9ec34bc..7a02480 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,101 +1,46 @@ import { useState } from 'react'; -import heroImg from './assets/hero.png'; -import reactLogo from './assets/react.svg'; -import viteLogo from './assets/vite.svg'; -import './App.css'; +import { GameList } from './components/GameList/GameList'; +import { mockGames } from './mocks/games'; +/** + * Midlertidig forside: viser spillene med mockdata til GraphQL er klart. + * Favoritter og valgt visning ligger bare i minnet her og skal senere inn i state management. + */ function App() { - const [count, setCount] = useState(0); + const [favorites, setFavorites] = useState>(new Set()); + const [view, setView] = useState<'list' | 'grid'>('list'); - return ( - <> -
-
- - React logo - Vite logo -
-
-

Get started

-

- Edit src/App.tsx and save to test HMR -

-
- -
+ const toggleFavorite = (id: string) => { + setFavorites((prev) => { + const next = new Set(prev); + if (next.has(id)) next.delete(id); + else next.add(id); + return next; + }); + }; -
+ return ( +
+

Spill

+

Søkeresultater

-
-
- -

Documentation

-

Your questions, answered

- -
-
- -

Connect with us

-

Join the Vite community

- -
-
+ {/* Bytter mellom visning 1 (liste) og visning 2 (rutenett) */} +
+ + +
-
-
- + +
); } diff --git a/frontend/src/components/GameCard/GameCard.css b/frontend/src/components/GameCard/GameCard.css index 8566b78..781fc6f 100644 --- a/frontend/src/components/GameCard/GameCard.css +++ b/frontend/src/components/GameCard/GameCard.css @@ -2,7 +2,7 @@ .game-card { position: relative; display: grid; - grid-template-columns: 192px 1fr; + grid-template-columns: 150px 1fr; gap: 20px; padding: 20px 0; text-align: left; @@ -80,15 +80,15 @@ font-variant-numeric: tabular-nums; /* tallene står rett under hverandre i lista */ } -/* Tekstknapp med rett ramme, som [+ Favoritt] i skissen */ .game-card__favorite { - position: relative; + position: absolute; /* plasseres i forhold til .game-card, som har position: relative */ + top: 12px; /* samme som padding-toppen på raden */ + right: 0; z-index: 1; /* over den strukne lenken */ - margin-top: auto; - min-height: 44px; /* stort nok trykkmål */ - padding: 0 14px; + min-height: 32px; + padding: 0 10px; font: inherit; - font-size: 15px; + font-size: 14px; color: var(--text-h); background: none; border: 1px solid var(--text-h); @@ -96,6 +96,11 @@ cursor: pointer; } +/* Plass til knappen, så lange titler ikke havner under den */ +.game-card__body { + padding-right: 110px; +} + .game-card__favorite:hover { text-decoration: underline; } @@ -116,3 +121,51 @@ gap: 12px; } } + +/* ===== Visning 2: oppsummert rute (4 per rad) ===== */ +.game-card--grid { + grid-template-columns: 1fr; /* bildet over teksten */ + grid-template-rows: auto 1fr; /* teksten fyller resten av ruta */ + height: 100%; /* like høye ruter i samme rad */ + box-sizing: border-box; + gap: 10px; + padding: 0 0 14px; +} + +.game-card--grid .game-card__body { + gap: 2px; + padding-right: 0; /* knappen ligger ikke ved tittelen her */ +} + +/* Maks to linjer tittel, så rutene blir like høye */ +.game-card--grid .game-card__title { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + font-size: 16px; +} + +.game-card--grid .game-card__meta, +.game-card--grid .game-card__scores { + font-size: 14px; +} + +.game-card--grid .game-card__scores { + margin: auto 0 0; /* skyver rating ned til bunnen av ruta */ +} + +/* Favoritt nederst til høyre, på linje med rating */ +.game-card--grid .game-card__favorite { + top: auto; + bottom: 8px; +} + +/* Smale ruter (mobil): knappen under rating i stedet for ved siden av */ +@media (max-width: 640px) { + .game-card--grid .game-card__favorite { + position: relative; + bottom: auto; + margin-top: 6px; + } +} diff --git a/frontend/src/components/GameCard/GameCard.tsx b/frontend/src/components/GameCard/GameCard.tsx index b2deeb3..690148d 100644 --- a/frontend/src/components/GameCard/GameCard.tsx +++ b/frontend/src/components/GameCard/GameCard.tsx @@ -5,16 +5,20 @@ interface GameCardProps { game: GameSummary; isFavorite: boolean; onToggleFavorite: (id: string) => void; + /** 'list' = visning 1 (rad), 'grid' = visning 2 (oppsummert rute) */ + view?: 'list' | 'grid'; } //Viser ett spill i resultatlista. Lenken i tittelen dekker hele kortet (via CSS), så hele kortet er klikkbart, men skjermlesere hører bare én lenke per kort. -export function GameCard({ game, isFavorite, onToggleFavorite }: GameCardProps) { +export function GameCard({ game, isFavorite, onToggleFavorite, view = 'list' }: GameCardProps) { const year = game.released?.slice(0, 4) ?? null; - const meta = [year, game.genres.slice(0, 2).join(', ')].filter(Boolean).join(' · '); + const meta = [year, game.genres.slice(0, view === 'grid' ? 1 : 2).join(', ')] + .filter(Boolean) + .join(' · '); return ( -
+
{game.backgroundImage ? ( // alt="" fordi tittelen allerede beskriver kortet. Fast størrelse og lazy // loading hindrer at layouten hopper og sparer data ved lange lister. @@ -43,10 +47,12 @@ export function GameCard({ game, isFavorite, onToggleFavorite }: GameCardProps)
Rating
{game.rating != null ? `${game.rating.toFixed(1)} / 5` : 'Ingen'}
-
-
Metacritic
-
{game.metacritic ?? 'Ingen'}
-
+ {view === 'list' && ( +
+
Metacritic
+
{game.metacritic ?? 'Ingen'}
+
+ )}