Skip to content
Merged
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
111 changes: 96 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,111 @@
# Project 1T30-Project-1
# Prosjekt 1 - Pokédex (T30)

A small Pokédex built with React, TypeScript and Vite for the course IT2810 at NTNU. The app fetches pokemon on the fly from [PokeAPI](https://pokeapi.co) and lets you browse them one at a time, filter and sort the selection, and mark favorites that are remembered between visits.

## Links

Repo: [https://git.ntnu.no/IT2810-H26/T30-Project-1]
- Repo: <https://git.ntnu.no/IT2810-H26/T30-Project-1>
- Website: <http://it2810-30.idi.ntnu.no/project1> (needs NTNU network or VPN)

Webiste: [http://it2810-30.idi.ntnu.no/project1]
## Features

- View one pokemon at a time with sprite, types, height, weight, abilities and base stats
- Step back and forth with Prev/Next, type an id directly, or click a pokemon in the list to jump to it
- Filter by type, sort by id ascending or descending, or show favorites only. The choices survive a reload
- Mark a pokemon as favorite with the heart button. Favorites survive closing the browser and are listed in their own panel
- Responsive layout for desktop, phones in portrait and phones in landscape

## Docs
## Getting started

Requirements: Node.js 24.6 or newer and npm 11 or newer (see `engines` in `package.json`).

```bash
git clone https://git.ntnu.no/IT2810-H26/T30-Project-1.git
cd T30-Project-1
npm install
npm run dev
```

Open the localhost address printed in the terminal. Other useful commands:

| Command | What it does |
| ------------------- | ------------------------------------ |
| `npm run dev` | Start the dev server with hot reload |
| `npm run build` | Type check and build to `dist/` |
| `npm run preview` | Serve the last build locally |
| `npm run test` | Run the Vitest test suite |
| `npm run lint-full` | Lint the whole project with ESLint |
| `npm run format` | Format the project with Prettier |

Prettier and ESLint also run automatically on staged files when you commit (husky + lint-staged).

## How to use the app

1. The card in the middle shows the current pokemon. Use **Prev** and **Next** to move one step, or type a number in the id field to jump straight to that pokemon.
2. The list below the card shows the pokemon around the current one. Click any of them to select it.
3. Open the **Filter** panel to pick a type, change the sort order or show only favorites. Prev/Next and the list then only move between pokemon that match. **Reset** clears the filters.
4. Click the heart to add or remove the current pokemon from your favorites. The favorites panel lists them and you can click one to jump to it.

## Project structure

```
src/
api/ fetch functions for PokeAPI
models/ filters and favorites, read/write to web storage
controllers/ filtering, navigation and the React hooks
components/ one folder per component with its css and tests
utils/ shared test data and a TanStack Query test wrapper
docs/ architecture diagram, test overview and worksheet
```

## Design choices

Read docs in [/docs](/docs/README.md)
- **PokeAPI** (https://pokeapi.co) is the data source. It is open, needs no API key and gives a lot of data per pokemon, so it was easy to build a card, a list and filters on top of it.
- **MVC folder structure.** `src/models/` owns everything that touches web storage, `src/controllers/` owns fetching, filtering and navigation logic (plus the React hooks), and `src/components/` are the views. The views only get props and callbacks, they never read storage or call the API themselves.
- **All requests go through TanStack Query.** The pokemon card is fetched with `useQuery` keyed on the pokemon id, so going back and forth between pokemon you already looked at does not hit the API again. Favorites are fetched the same way keyed on the list of favorite ids.
- **Filtered navigation asks the type endpoint first.** When a type filter is active we fetch `/type/{name}` once to get the ids of that type and only step through those, instead of fetching pokemon one by one until one matches. This keeps the number of API calls down.
- **Two kinds of web storage.** Favorites are stored in `localStorage` so they survive closing the browser. Filter and sort choices are stored in `sessionStorage` so they survive a reload but reset when the tab is closed. Both are validated when read, so broken or old data just falls back to defaults instead of crashing the app.
- **Sorting is by id only.** Sorting by name would need every pokemon fetched up front to know the names, which goes against fetching data on the fly, so we left it out.
- **Plain CSS and own components.** No UI library. Filters use `fieldset`/`legend` with labelled inputs, the favorite and list buttons use `aria-pressed`, loading and error messages use `role="status"` and `role="alert"`, and media queries adapt the layout to narrow screens and to phones in landscape.

## Useful commands
## Testing

> These are generated in ./package.json `scripts` tag. Leaving them here as a cheatsheet.
### Automated

- `npm run dev` - Runs the project in memory, view it from localhost address in stdout
- `npm run lint-full` - Scans project for syntax errors, potential bugs, or stylistic inconsistencies.
- `npm run build` - Compiles TS to JS, remove dead code, bundle source files, etc. Moves the compiled resources to ./dist/
- `npm run preview` - Runs the previous build to let you test the build before pushing it to web-server or CDN.
Tests are written with Vitest, jsdom and Testing Library. Every component, hook, model and the API module has its own test file, and most components also have a snapshot test. The API is mocked with `vi.mock`/`vi.spyOn` so no test ever calls PokeAPI. Run them with:

> The previous commands we're generated automatically when project was created. What follows is custom behaviour.
```bash
npm run test
```

### Manual

The app was tested manually on the devices and browsers the group had available:

| Device | Browser |
| ------ | ------- |
| Mac | Safari |
| Mac | Chrome |
| iPhone | Safari |
| iPhone | Chrome |

## Deployment

The app is served from Apache on the group's virtual machine under `/project1`. `base` in `vite.config.ts` points there so the built asset paths are correct. To deploy:

```bash
npm run build
```

Then copy the contents of `dist/` to the `project1` directory in Apache's document root on the VM.

## Use of AI

Cursor's autofill was used a bit while coding, while ChatGPT was used to go back and forth on ideas and choices.

## Docs

- `npm run test` - Runs vitest test sets.
- `npm run format` - -Runs prettier to format project (also runs on `git commit`)
- `npm run lint` - Lints only staged changes (`git status`)
More details, the architecture diagram and the worksheet are in [/docs](/docs/README.md).

## Dependencies

Expand Down