Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/assets/listings/drill.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/assets/listings/handsaw.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/listings/paint-roller.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/listings/spade.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
144 changes: 144 additions & 0 deletions src/data/mockListings.ts
Original file line number Diff line number Diff line change
@@ -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,
},
];
28 changes: 28 additions & 0 deletions src/types/listing.ts
Original file line number Diff line number Diff line change
@@ -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;
}
28 changes: 28 additions & 0 deletions src/utils/listingFormat.ts
Original file line number Diff line number Diff line change
@@ -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<ToolCategory, string> = {
powerTools: 'Elektroverktøy',
handTools: 'Håndverktøy',
garden: 'Hage',
painting: 'Maling og overflate',
measuring: 'Måleverktøy',
cleaning: 'Rengjøring',
};

export const conditionLabels: Record<ToolCondition, string> = {
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`;
}