diff --git a/README.md b/README.md index 30f34a3..80cdb81 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ Prosjektet er live på: [http://it2810-02.idi.ntnu.no/project1/](http://it2810-0 ## Beskrivelse -_Skriv en beskrivelse her_ +BetterBoxd er en webapp for å utforske filmer. Data hentes fortløpende fra The Movie Database (TMDB) sitt REST-API +Forsiden viser en hero-karusell med trending filmer, og seksjoner for populære og nye filmer. Søkefeltet i menyen søker mens du skriver. Søkeresultatene kan sorteres (popularitet, vurdering, utgivelsesdato, alfabetisk) og filtreres på en minimumsvurdering. Hvert filmkort kan åpnes i en detaljvisning, og markeres som favoritt med hjerteknappen. Favorittene samles på en egen side. ## Table of Contents @@ -284,6 +285,18 @@ Grunnen til at den finnes er at MovieList eller har måttet håndtere lasting og Overskriften rendres bare hvis title faktisk har innhold. Banner-seksjonen øverst sendes inn uten tittel, og uten den sjekken ville den laget en tom `

`. Det er ikke bare stygt da tomme overskrifter havner i overskriftoversikten en skjermleser navigerer etter, og da står det bare "overskrifter" uten noe mer. +###### SortFilterBar.tsx + +En liten, selvutviklet komponent (ingen tredjepartsbibliotek for UI, i tråd med kravet) med en nedtrekksmeny for sortering og en range-slider for minimumsvurdering. Komponenten er "dum" — den mottar verdier og callbacks som props, og eier ingen egen state selv. + +##### FavoriteButton.tsx + FavoriteButton.css + +Hjerteknappen som markerer en film som favoritt. Eier ingen state selv, men får isFavorite og onToggleFavorite inn som props, slik at samme knapp kan brukes både på filmkortet og i detaljvisning. + +###### MovieDetails.tsx + MovieDetails.css + +Detaljvisningen som legger seg over siden når man åpner en film. Viser backdrop, tittel, utgivelsesdato, vurdering, sammendrag og skuespillere, og henter skuespillerne via `useMovieCredits` på samme måte som kortet — så cachen deles og det blir ikke et nytt kall. + #### hooks ###### useMovieCredits.ts @@ -297,20 +310,40 @@ En generisk, gjenbrukbar hook som fungerer som `useState`, men som leser fra og ###### useMediaQuery.ts Vil returnere true eller false for en media query, i mine tilfeller var dette ved bruk av (max-width:700px), som lar meg si at hvis noen åpner ned en brudde under 700px så rendre den riktige menyen. useState passer her på at riktig verdi settes før første render, slik at det ikke skal vises feil visning først. useEffect henger på via window.matchMedia, og return funksjonen fjerner lytteren igjen. uten det hoper lytterne seg opp for hver rendring. - Da desktop og mobil har ulik DOM struktur trenger vi dette både i JSX og CSS og ikke bar ei CSS. I desktop som sagt tidligere ligger undermenyen i HOME og på mobil ligger alle fire knappene flatt på bunnen ved siden av hverandre. Dette vil ikke CSS kunne gjøre. + +##### useFavorites.ts + +Holder lista over favoritt-id-er og lagrer den i localStorage under nøkkelen favorites-movies. Kun id-ene lagres og ikke hele filmobjektet. Dette er fordi at den skal ikke mellomlagre API-data og lagrede filmer kunne blitt utdatert. Lista leses ved første render og en `useEffect` skriver tilbake når den endrer seg. + +###### useDebouncedValue.ts + +En generisk hook som forsinker en verdi til den har vært uendret i et gitt antall millisekunder. Brukes på søketeksten med 400ms. Hvis denne ikke hadde blitt brukt hadde man sendt et API-kall for hver bokstav man trykker inn. Dette gjør at man kun sender et API-kall, ikke flere. + +###### useMovies.ts + +Samler alle filmspørringene mot TMDB.øke-spørringen har `enabled: query.trim().length > 0`, slik at et tomt felt ikke gir kall i det hele tatt.Hvert oppslag har sin egen `queryKey` (`['movies', 'detail', id]`), slik at cachen gjenbrukes når man bytter mellom visninger i stedet for at det hentes på nytt. + #### layout -#### types +Layout-komponentene setter sammen seksjoner og bestemmer hva som vises i hovedområdet. `App.tsx` velger mellom dem ut fra tilstand, slik at `App` slipper å inneholde tre ulike JSX-trær. -###### sortAndFilterMovies.ts +###### MainLayout.tsx +Forsiden: hero-karusell med trending filmer, og seksjoner for populære og nye filmer. -En ren funksjon uten side-effekter som tar inn en liste med filmer, sorteringsvalg og minimumsvurdering, og returnerer en ny, filtrert og sortert liste. Fordi funksjonen er ren (samme input gir alltid samme output, og den endrer ikke noe utenfor seg selv), er den enkel å enhetsteste isolert med Vitest, uten å måtte mocke React eller komponenter. +###### SearchLayout.tsx +Vises så snart søkefeltet har innhold. Rendrer `SortFilterBar` over søkeresultatene og kjører `sortAndFilterMovies` på treffene før de sendes til `MovieList`. -###### SortFilterBar.tsx +###### FavoritesLayout.tsx +Favorittsiden. Får `favoriteIds` inn og henter filmene på nytt via +`useFavoriteMovies`. Viser "Du har ingen favoritter ennå." når lista er tom, i stedet for en blank side. -En liten, selvutviklet komponent (ingen tredjepartsbibliotek for UI, i tråd med kravet) med en nedtrekksmeny for sortering og en range-slider for minimumsvurdering. Komponenten er "dum" — den mottar verdier og callbacks som props, og eier ingen egen state selv. +#### utils + +###### sortAndFilterMovies.ts + +En ren funksjon uten side-effekter som tar inn en liste med filmer, sorteringsvalg og minimumsvurdering, og returnerer en ny, filtrert og sortert liste. Fordi funksjonen er ren (samme input gir alltid samme output, og den endrer ikke noe utenfor seg selv), er den enkel å enhetsteste isolert med Vitest, uten å måtte mocke React eller komponenter. # Vet ikke hvor dette bør stå @@ -339,7 +372,7 @@ Kjente begrensninger/mulige forbedringer - Range-slideren for minimumsvurdering kunne fått `aria-valuetext` for bedre skjermleserstøtte (f.eks. "minst 7 av 10" i stedet for kun tallet). - sessionStorage-nøklene (`sortBy`, `minRating`) er generiske. Ved videre utvikling av appen kan det være lurt å prefikse dem (f.eks. `movieApp:sortBy`) for å unngå navnekollisjon med annen bruk av sessionStorage. -## Responsivt design og tilgjengelighet +## Responsivt design Sidelayouten er flexbasert. Hovedinnholdet har flex: 2 1 0 og sidekolonnene har fast bredde, slik at innholdet får mest plass uten at menyen blir uleselig bred på store skjermer. min-width: 0 på hovedinnholdet er nødvendig fordi flex-elementer ellers nekter å bli smalere enn innholdet sitt, noe som ga horisontal scrolling ved lange filmtitler. @@ -349,14 +382,26 @@ hjemindikatoren på nyere iPhone. Fordi position: fixed tar elementet ut av doku Detaljvisningen bruker max-height i dvh og ikke vh på mobil. Vanlig vh regner som om adresselinja i mobilnettleseren ikke finnes, så bunnen av kortet havner utenfor skjermen. -På tilgjengelighet... +## Tilgjengelighet -### Kjente begrensninger +Prinsippet gjennom appen er at alt som kan klikkes på også skal kunnes nå ved tastatur og gi mening for en nettleser. I praksis betyr det at interaktive elementer er +ekte `