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
211 changes: 151 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,96 +1,187 @@
# T19-Project-1

Repository for team IT2810-H26-T19 in IT2810-H26.
**Live application:** [http://it2810-19.idi.ntnu.no/project1](http://it2810-19.idi.ntnu.no/project1)

## Project

A digital library where users browse reading material fetched live from the
[OpenLibrary REST API](https://openlibrary.org/developers/api) — one book at a time,
with navigation, subject filtering, sorting, and persistent favorites. Built as the
course project for IT2810 Web Development (NTNU).
A digital library where users browse books fetched live from the
[OpenLibrary REST API](https://openlibrary.org/developers/api). The application
presents one book at a time and was built as the course project for IT2810 Web
Development at NTNU.

The application supports:

- Previous/next navigation and a jump-to-book selector
- Subject filtering and several sorting choices
- Persistent favorites with a separate favorites view
- Loading, error, empty-result, and missing-data states
- Responsive layouts for desktop and smaller screens

## Tech stack

- [Vite](https://vite.dev/) + [React](https://react.dev/) + TypeScript
- [TanStack Query](https://tanstack.com/query) for REST data fetching
- [Vitest](https://vitest.dev/) + React Testing Library + [msw](https://mswjs.io/)
for testing (API requests are always mocked)
- ESLint + Prettier, plain CSS
- npm as package manager — the course environment guide recommends pnpm, but the
project spec explicitly names "Node og npm (og kompatible pakkeverktøy)", so npm
is kept for simplicity
- [TanStack Query](https://tanstack.com/query) for REST data fetching and caching
- [Vitest](https://vitest.dev/) + React Testing Library + [MSW](https://mswjs.io/)
for testing
- ESLint + Prettier
- Plain CSS with no third-party UI component library
- npm as package manager

## Implementation choices

The OpenLibrary search endpoint is called through `src/api/openLibrary.ts` and
used by the `useBooks` TanStack Query hook. The query key includes the selected
subject, so changing the subject fetches a new set of books. Navigation and
sorting use the books that have already been fetched and therefore do not
require additional API requests.

React state is used to keep track of which book is currently displayed and
which view is active. Data and event handlers are passed to components through
props. Custom hooks are used to separate logic for fetching books, storing user
preferences, and managing favorites from the UI components.

OpenLibrary data is normalized before it is displayed. Missing authors,
ratings, covers, and subjects are handled by the application. Invalid
publication years, such as `0`, are treated as missing instead of being shown
to the user.

## Persistence

The application uses both `sessionStorage` and `localStorage` for different
types of user choices:

- Subject and sort choices are stored under `t19.preferences` in
`sessionStorage`. They survive page reloads during the current browser
session, but reset when the session ends.
- Favorites are stored under `t19.favorites` in `localStorage`. They remain
available after closing and reopening the browser.

When stored values are missing or invalid, the application falls back to
default values instead of failing.

## Responsive design and accessibility

The interface uses plain CSS and media queries to adapt the book card, controls,
navigation, and favorites view to smaller screens.

The application uses semantic HTML elements such as `header`, `nav`, `main`,
`section`, `article`, and `footer`, together with native buttons and form
controls. Controls have accessible labels, ARIA attributes are used where
appropriate, book covers have alternative text, and keyboard focus is visible.

The main controls and navigation can also be operated using the keyboard.

## Testing

The test suite uses Vitest and React Testing Library. MSW intercepts
OpenLibrary requests during tests so the automated test suite does not depend
on the live API. Unhandled API requests cause the tests to fail.

The tests cover:

- Snapshot tests for rendered components
- Component props and state, including missing book data and cover failures
- User interaction for navigation, jumping, filtering, sorting, favorites,
and expanding subjects
- `sessionStorage` and `localStorage` persistence, including reload behavior
and invalid stored values
- Keyboard interaction, focus, labels, and accessible names
- Loading, API error, and no-results states
- API response normalization, including invalid publication years
- Request counts to check that navigation and local sorting do not cause
unnecessary REST API requests

## Getting started
### Manual testing

Requires Node.js 24.6+ and npm 11+.
Issue #30 documents a final manual check using the local production preview on
a desktop browser and a narrow mobile-sized viewport. The library flow,
keyboard use, visible focus, responsive layout, loading and error states, and
saved choices were checked, and no issues were found.

## Running the project locally

The project requires Node.js 24.6+ and npm 11+.

Install the dependencies:

```bash
npm install
```

Start the development server:

```bash
npm run dev
```

| Command | Description |
| ---------------------- | ----------------------------- |
| `npm run dev` | Start the dev server |
| `npm run build` | Type-check and build for prod |
| `npm run preview` | Preview the production build |
| `npm run lint` | Run ESLint |
| `npm test` | Run tests once |
| `npm run test:watch` | Run tests in watch mode |
| `npm run format` | Format code with Prettier |
| `npm run format:check` | Check formatting (used in CI) |
The main project commands are:

## Working in this repository
| Command | Description |
| ---------------------- | ----------------------------------- |
| `npm run dev` | Start the development server |
| `npm run build` | Type-check and build for production |
| `npm run lint` | Run ESLint |
| `npm test` | Run the test suite |
| `npm run format` | Format code with Prettier |
| `npm run format:check` | Check formatting |

`main` is protected — you cannot push to it directly. Work on a branch and
open a pull request:
## Working in this repository

```bash
git checkout -b my-feature
git push -u origin my-feature
```
The `main` branch is protected. Development is done on separate branches and
merged through pull requests.

Before a pull request can be merged:

1. **A member of IT2810-H26-T19 must approve it.** You cannot approve your own pull
request, and approvals from staff do not count — you review each other's
code.
2. **Every review comment must be marked resolved.** Reply to each one, fix it
or explain why not, then click _Resolve conversation_.
3. **Pushing new commits dismisses the approval**, so if you change something
after being approved, ask for another review. This is deliberate: what was
approved is what gets merged.
1. A member of IT2810-H26-T19 must approve it. Group members review each
other's code rather than approving their own pull requests.
2. Review comments must be resolved before merging.
3. New commits after approval dismiss the existing approval, so the updated
pull request must be reviewed again.

### Commits

Use [conventional commit](https://www.conventionalcommits.org/) messages and link
issues so they close automatically:
We use
[Conventional Commits](https://www.conventionalcommits.org/)
and reference issues in commits and pull requests where relevant.

```
Example:

```text
feat: add favorites toggle with localStorage (#42)
```

### Issues and labels
### Issues and milestones

Issues are organized under milestones from M1 Setup to M5 Delivery and use
labels for type, area, and priority. Issues with substantial AI assistance use
the `ai-assisted` label.

Issues are organized under milestones (M1 Setup → M5 Delivery) and labeled by type
(`type: feature|bug|docs|chore|test`), area (`area: ui|api|storage|styling|a11y`),
and priority. The schedule and current status live in [ROADMAP.md](ROADMAP.md).
Issues where substantial code was AI-generated carry the `ai-assisted` label; AI
usage is documented in the README as required by the course.
The project milestones and delivery status are documented in
[ROADMAP.md](ROADMAP.md).

## CI/CD

CI runs on our self-hosted runner on the group VM (see `docs/ci-runner.md`; the
NTNU GitHub Enterprise installation has no shared runners). Every pull request
runs formatting (Prettier), linting (ESLint), tests (Vitest), and the production
build — everything must pass with zero errors and warnings before merge.
Pushes to `main` additionally deploy the build to the Apache server on the VM, so
the prototype at http://it2810-19.idi.ntnu.no/project1 always reflects `main`.
CI runs on a self-hosted runner on the group VM. Pull requests targeting `main`
run Prettier, ESLint, Vitest, and the production build.

## Testing
Pushes to `main` run the same checks and, if they pass, deploy the production
build to Apache on the group VM. The deployed application is therefore updated
from the `main` branch.

See [docs/ci-runner.md](docs/ci-runner.md) and
[docs/deployment.md](docs/deployment.md) for more information.

## AI usage and reflection

AI tools were used as assistants during the project for understanding React
and TypeScript concepts, discussing implementation options, debugging,
suggesting tests, reviewing responsive and accessibility behavior, and
checking the project against the course requirements. Issues with substantial
AI assistance were marked with the `ai-assisted` label.

- Snapshot tests of rendered components
- Component tests covering props, state, and user interaction
- Tests never touch the network: msw intercepts every OpenLibrary request
(handlers in `src/test/handlers.ts`), and any unhandled request fails tests
loudly
The team still made the implementation decisions, reviewed suggestions, ran
tests, and adjusted the results before including changes in the project. AI
was useful for finding edge cases, explaining unfamiliar concepts, and
structuring tests. At the same time, suggestions could sometimes be more
extensive than necessary, so they had to be evaluated against the project
requirements and the existing codebase.
75 changes: 42 additions & 33 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,54 @@
# Roadmap — Project 1: Digital Library

Delivery: **Friday 18 September 2026** (medstudentvurdering by 25/9).

Issues are grouped under milestones. Day-to-day workflow status lives on the
[Kanban board](https://git.ntnu.no/orgs/IT2810-H26/projects/7) (Backlog → Ready →
In progress → In review → Done); issues also carry `status:*` labels.
[Kanban board](https://git.ntnu.no/orgs/IT2810-H26/projects/7)
(Backlog → Ready → In progress → In review → Done); issues also use status
labels.

## Milestones

| Milestone | Due | Scope |
| -------------------------- | -------- | ------------------------------------------------------------------------- |
| M1 — Setup | done | Template, tooling, CI, types + API client (#1#4) |
| M2 — Core app | Wed 10/9 | BookCard, useBooks, navigation, jump list |
| M3 — Persistence & choices | Fri 12/9 | Subject filter, sorting (sessionStorage), favorites (localStorage) |
| M4 — Quality | Tue 15/9 | Responsive CSS, accessibility, Vitest suite, manual browser/device checks |
| M5 — Delivery | Thu 17/9 | Apache deployment, README, delivery artifacts (#5) |

## Status (updated 8/9)

- M1 — **done**: PR #3 (template + CI/CD + docs) and PR #15 (#4 types + API client)
merged; #1, #2, #4, #6 closed
- Infrastructure — **live**: self-hosted runner on it2810-19 (systemd service,
survives reboots); CI/CD verified end-to-end — pushes to `main` pass quality
gates and deploy to Apache automatically
- M2 — in review: PR #17 (useBooks + App integration) and PR #18 (BookJumpList),
both CI-green; #13 NavigationControls in progress (evenkkl); #12 stays open
until navigation and jump list are wired into the app
- M3 — issues #19#22 created and Ready (assignments on the board); testing is an
acceptance criterion in each
- #5 — delivery artifacts (timeliste, VM, FeedbackFruits) — open
| Milestone | Due | Status and scope |
| -------------------------- | ------ | ------------------------------------------------------------------------------ |
| M1 — Setup | 4 Sep | Complete: template, tooling, CI, types, API client, and runner |
| M2 — Core app | 10 Sep | Complete: BookCard, data fetching, navigation, and jump list |
| M3 — Persistence & choices | 12 Sep | Complete: subject filtering, sorting, preferences, and favorites |
| M4 — Quality | 15 Sep | Complete: responsive design, accessibility, automated tests, and manual checks |
| M5 — Delivery | 17 Sep | Complete: final fixes, documentation, deployment, and delivery preparation |

## Final status

- M1–M5 are complete.
- The functional requirements are implemented, including navigation, subject
filtering, sorting, persistent preferences, and favorites.
- Responsive design, accessibility, automated tests, and manual checks were
completed as part of M4.
- CI runs on the self-hosted runner for pull requests and pushes to `main`.
Successful pushes to `main` deploy the production build to Apache on the
group VM.
- Final fixes, documentation, deployment, and delivery preparation were
completed as part of M5.

The individual peer assessment in FeedbackFruits takes place after submission
and is due by 25/9.

## Workflow

1. Pick an issue from the current milestone (unassigned, `status: blocked` means wait)
2. Branch: `feat/<issue>-short-name` from `main`
3. Conventional commits referencing the issue
4. PR → teammate review → all conversations resolved → merge
5. Issue auto-closes; PR gets `status: in-review` while waiting
1. Pick an issue from the current milestone.
2. Create a branch from `main`, using names such as
`feat/<issue>-short-name` or `fix/<issue>-short-name`.
3. Use conventional commits and reference the relevant issue.
4. Open a pull request for teammate review.
5. Resolve review conversations and merge after approval.
6. Close the corresponding issue when the work is complete.

## Delivery checklist

## Delivery checklist (18/9)
Delivery is tracked in issue #5 and includes:

Tracked in #5: code + docs on git.ntnu.no, prototype on the group VM (Apache,
[deployment guide](docs/deployment.md) — live at
http://it2810-19.idi.ntnu.no/project1), individual time log for Blackboard,
FeedbackFruits participation.
- Code and documentation on git.ntnu.no
- Working prototype on the group VM using Apache
- [Deployment documentation](docs/deployment.md)
- Individual time log for Blackboard
- FeedbackFruits participation
Loading