diff --git a/README.md b/README.md
index 6e5364a..f7286ca 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,38 @@ ESLint finner feil i koden, mens Prettier bestemmer formateringen.
ESLint-regler som ellers ville kollidert med Prettier. Byggfiler,
avhengigheter og `package-lock.json` formateres ikke.
+## Datamodell og mockdata
+
+Alle annonser følger typen `Listing` i `src/types/listing.ts`:
+
+| Felt | Innhold |
+| ------------- | ---------------------------------------------------------- |
+| `id` | Stabil ID, for eksempel `listing-001` |
+| `title` | Kort tittel |
+| `category` | Fast nøkkel, for eksempel `powerTools` |
+| `description` | Fritekst |
+| `area` | Område i Trondheim, for eksempel «Moholt» |
+| `dailyPrice` | Pris i hele kroner per døgn. `0` betyr gratis utlån |
+| `condition` | `likeNew`, `good` eller `worn` |
+| `accessories` | Liste med tilbehør. Tom liste når ingenting følger med |
+| `imageUrl` | Adresse til bilde, eller `null` når annonsen mangler bilde |
+
+Kategori og tilstand lagres som engelske nøkler slik at de senere kan bli
+GraphQL-enums. `src/utils/listingFormat.ts` gir de norske visningsnavnene og
+`formatDailyPrice`, som viser `150 kr/døgn` eller `Gratis utlån`. Bruk disse i
+stedet for å formatere på nytt i hver komponent. Når `imageUrl` er `null`, skal
+visningen vise en nøytral plassholder.
+
+`src/data/mockListings.ts` har 10 oppdiktede eksempelannonser. De er ikke ekte
+tilbud og inneholder ingen personopplysninger. Illustrasjonene i
+`src/assets/listings/` er laget for prosjektet. Ekstern datakilde er ikke
+valgt.
+
+Senere skal annonsene hentes fra en egen GraphQL-backend med database
+(planlagt, ikke laget). Komponenter bør derfor få annonser gjennom props i
+stedet for å importere mockdataene direkte. Da kan datakilden byttes uten at
+visningene må skrives om.
+
## Working in this repository
`main` is protected — you cannot push to it directly. Work on a branch and
diff --git a/src/assets/listings/drill.svg b/src/assets/listings/drill.svg
new file mode 100644
index 0000000..6441bbc
--- /dev/null
+++ b/src/assets/listings/drill.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/assets/listings/handsaw.svg b/src/assets/listings/handsaw.svg
new file mode 100644
index 0000000..23f0400
--- /dev/null
+++ b/src/assets/listings/handsaw.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/assets/listings/paint-roller.svg b/src/assets/listings/paint-roller.svg
new file mode 100644
index 0000000..6d78fe5
--- /dev/null
+++ b/src/assets/listings/paint-roller.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/assets/listings/spade.svg b/src/assets/listings/spade.svg
new file mode 100644
index 0000000..fe5cec8
--- /dev/null
+++ b/src/assets/listings/spade.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/data/mockListings.ts b/src/data/mockListings.ts
new file mode 100644
index 0000000..be58e37
--- /dev/null
+++ b/src/data/mockListings.ts
@@ -0,0 +1,144 @@
+/**
+ * Oppdiktede eksempelannonser for prototypen. Ingen av annonsene er ekte
+ * tilbud, og ingen personopplysninger er brukt. Illustrasjonene er laget for
+ * prosjektet.
+ *
+ * Dataene er valgt for å dekke ulike tilfeller i visningene: gratis og betalt
+ * utlån, korte og lange titler, tomt tilbehør og annonser uten bilde.
+ *
+ * Datakilden erstattes senere av GraphQL-backenden. Komponenter bør derfor få
+ * annonser gjennom props i stedet for å importere denne filen direkte.
+ */
+
+import drillImage from '../assets/listings/drill.svg';
+import handsawImage from '../assets/listings/handsaw.svg';
+import paintRollerImage from '../assets/listings/paint-roller.svg';
+import spadeImage from '../assets/listings/spade.svg';
+import type { Listing } from '../types/listing.ts';
+
+export const mockListings: Listing[] = [
+ {
+ id: 'listing-001',
+ title: 'Drill',
+ category: 'powerTools',
+ description:
+ 'Batteridrill som passer til å skru opp hyller og montere møbler.',
+ area: 'Moholt',
+ dailyPrice: 100,
+ condition: 'good',
+ accessories: ['2 batterier', 'Lader', 'Bitssett'],
+ imageUrl: drillImage,
+ },
+ {
+ id: 'listing-002',
+ title: 'Slagdrill med borsett for betong og murvegger',
+ category: 'powerTools',
+ description:
+ 'Kraftig slagdrill for boring i betong, mur og tegl. Egner seg til å henge opp tunge hyller, TV-braketter og kjøkkenskap. Borsett fra 6 til 12 mm følger med. Bruk hørselvern ved lengre arbeid.',
+ area: 'Lade',
+ dailyPrice: 150,
+ condition: 'likeNew',
+ accessories: ['Borsett for betong', 'Koffert', 'Dybdestopper'],
+ imageUrl: drillImage,
+ },
+ {
+ id: 'listing-003',
+ title: 'Fogsvans',
+ category: 'handTools',
+ description: 'Vanlig håndsag for tre. Bladet er skarpt.',
+ area: 'Gløshaugen',
+ dailyPrice: 0,
+ condition: 'good',
+ accessories: [],
+ imageUrl: handsawImage,
+ },
+ {
+ id: 'listing-004',
+ title: 'Verktøykasse med hammer, skrutrekkere og tenger',
+ category: 'handTools',
+ description:
+ 'Grunnleggende verktøy for småreparasjoner i hybelen. Kassen har hammer, flere skrutrekkere, nebbtang, kombinasjonstang og målebånd.',
+ area: 'Singsaker',
+ dailyPrice: 50,
+ condition: 'worn',
+ accessories: ['Målebånd', 'Unbrakonøkler'],
+ imageUrl: null,
+ },
+ {
+ id: 'listing-005',
+ title: 'Spade',
+ category: 'garden',
+ description: 'Solid spade til hagearbeid og planting.',
+ area: 'Byåsen',
+ dailyPrice: 0,
+ condition: 'worn',
+ accessories: [],
+ imageUrl: spadeImage,
+ },
+ {
+ id: 'listing-006',
+ title: 'Hagespade og rive',
+ category: 'garden',
+ description:
+ 'Spade og rive som lånes ut sammen. Fint til å gjøre klar et lite bed eller rake løv om høsten.',
+ area: 'Tiller',
+ dailyPrice: 40,
+ condition: 'good',
+ accessories: ['Rive', 'Arbeidshansker'],
+ imageUrl: spadeImage,
+ },
+ {
+ id: 'listing-007',
+ title: 'Malerrulle og brett',
+ category: 'painting',
+ description:
+ 'Rulle og malebrett for vegger. Rullene er vasket og klare til bruk.',
+ area: 'Møllenberg',
+ dailyPrice: 0,
+ condition: 'likeNew',
+ accessories: ['2 ruller', 'Malebrett', 'Teleskopskaft'],
+ imageUrl: paintRollerImage,
+ },
+ {
+ id: 'listing-008',
+ title:
+ 'Komplett malersett til en liten leilighet: ruller, pensler, dekkplast og tape',
+ category: 'painting',
+ description:
+ 'Alt du trenger for å male om en hybel eller en liten leilighet, bortsett fra maling. Settet har ruller i to størrelser, pensler til kanter, dekkplast til gulv og møbler og maskeringstape. Rengjør ruller og pensler før levering.',
+ area: 'Midtbyen',
+ dailyPrice: 120,
+ condition: 'good',
+ accessories: [
+ 'Ruller i to størrelser',
+ '3 pensler',
+ 'Dekkplast',
+ 'Maskeringstape',
+ ],
+ imageUrl: paintRollerImage,
+ },
+ {
+ id: 'listing-009',
+ title: 'Laservater',
+ category: 'measuring',
+ description:
+ 'Krysslaser for å henge bilder og hyller rett. Rekker omtrent 15 meter innendørs.',
+ area: 'Heimdal',
+ dailyPrice: 80,
+ condition: 'likeNew',
+ accessories: ['Stativ', 'Batterier'],
+ imageUrl: null,
+ },
+ {
+ id: 'listing-010',
+ title: 'Tepperenser',
+ category: 'cleaning',
+ description:
+ 'Rensemaskin for tepper og møbeltrekk. Nyttig ved utflytting. Rensemiddel følger ikke med.',
+ area: 'Nardo',
+ dailyPrice: 250,
+ condition: 'good',
+ accessories: ['Slange', '2 munnstykker'],
+ imageUrl: null,
+ },
+];
diff --git a/src/types/listing.ts b/src/types/listing.ts
new file mode 100644
index 0000000..b8c5abb
--- /dev/null
+++ b/src/types/listing.ts
@@ -0,0 +1,28 @@
+/**
+ * Felles datatype for en verktøyannonse.
+ *
+ * Kategori og tilstand er faste engelske nøkler slik at de senere kan bli
+ * GraphQL-enums. Norske visningsnavn ligger i utils/listingFormat.ts.
+ */
+
+export type ToolCategory =
+ 'powerTools' | 'handTools' | 'garden' | 'painting' | 'measuring' | 'cleaning';
+
+export type ToolCondition = 'likeNew' | 'good' | 'worn';
+
+export interface Listing {
+ /** Stabil ID. Brukes i URL-er og som React-nøkkel. */
+ id: string;
+ title: string;
+ category: ToolCategory;
+ description: string;
+ /** Bydel eller område i Trondheim, for eksempel «Moholt». */
+ area: string;
+ /** Pris i hele kroner per døgn. 0 betyr gratis utlån. */
+ dailyPrice: number;
+ condition: ToolCondition;
+ /** Tilbehør som følger med. Tom liste når ingenting følger med. */
+ accessories: string[];
+ /** Adresse til bilde av verktøyet, eller null når annonsen mangler bilde. */
+ imageUrl: string | null;
+}
diff --git a/src/utils/listingFormat.ts b/src/utils/listingFormat.ts
new file mode 100644
index 0000000..6150896
--- /dev/null
+++ b/src/utils/listingFormat.ts
@@ -0,0 +1,28 @@
+import type { ToolCategory, ToolCondition } from '../types/listing.ts';
+
+// Record krever en etikett for hver nøkkel, så TypeScript sier fra hvis en
+// ny kategori eller tilstand legges til uten visningsnavn.
+export const categoryLabels: Record = {
+ powerTools: 'Elektroverktøy',
+ handTools: 'Håndverktøy',
+ garden: 'Hage',
+ painting: 'Maling og overflate',
+ measuring: 'Måleverktøy',
+ cleaning: 'Rengjøring',
+};
+
+export const conditionLabels: Record = {
+ likeNew: 'Som ny',
+ good: 'God stand',
+ worn: 'Godt brukt',
+};
+
+const priceFormatter = new Intl.NumberFormat('nb-NO');
+
+/** Viser døgnpris som «150 kr/døgn», eller «Gratis utlån» når prisen er 0. */
+export function formatDailyPrice(dailyPrice: number): string {
+ if (dailyPrice === 0) {
+ return 'Gratis utlån';
+ }
+ return `${priceFormatter.format(dailyPrice)} kr/døgn`;
+}