Skip to content
Open
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
173 changes: 173 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# CLAUDE.md — AI Assistant Guide for `ferienhaus`

## Project Overview

**BarrierefRei Reisen** is a single-page React application for finding and comparing accessible vacation homes in Germany. The entire interface is in German. The app is frontend-only with no backend, API, or database — all data is static.

**Stack:** React 19 · Vite 7 · Plain CSS · ESLint 9 · ES Modules

---

## Development Commands

```bash
npm run dev # Start dev server with hot module replacement (http://localhost:5173)
npm run build # Production build (outputs to dist/)
npm run preview # Preview production build locally
npm run lint # Run ESLint checks
```

There are **no tests** configured. To add tests, install Vitest or Jest.

---

## Repository Structure

```
ferienhaus/
├── index.html # HTML entry point, mounts #root
├── vite.config.js # Vite config with React plugin
├── eslint.config.js # ESLint flat config (v9 style)
├── package.json # Dependencies & scripts
├── public/ # Static assets served as-is
└── src/
├── main.jsx # Renders <App /> into #root
├── App.jsx # Root component — state, layout, filtering logic
├── App.css # All application styles (~814 lines)
├── index.css # Global resets, CSS variables, base typography
├── assets/ # Static assets imported by components
├── components/
│ ├── FilterPanel.jsx # Sidebar: price/guests/type/accessibility filters
│ ├── HausCard.jsx # Card for a single vacation home listing
│ └── CompareTable.jsx # Modal overlay comparing up to 3 selected homes
└── data/
└── ferienhauser.js # Static data: ACCESSIBILITY_FEATURES + ferienhauser array
```

---

## Architecture & Data Flow

### State (all in `App.jsx`)

| State var | Type | Purpose |
|---------------|------------|-------------------------------------------------|
| `filter` | object | Current filter: `{features[], maxPreis, minPersonen, typ}` |
| `sortBy` | string | `"bewertung"` \| `"preis-asc"` \| `"preis-desc"` \| `"merkmale"` |
| `compareIds` | number[] | IDs of homes selected for comparison (max 3) |
| `showCompare` | boolean | Whether the comparison modal is visible |
| `sidebarOpen` | boolean | Mobile sidebar toggle |

Filtering and sorting are performed with `useMemo` in `App.jsx` — no external state library.

### Data Shape

Each vacation home object in `ferienhauser.js`:
```js
{
id: number,
name: string,
region: string,
bundesland: string, // German federal state
typ: "Haus" | "Chalet" | "Bungalow" | "Villa" | "Cottage" | "Apartment",
personen: number, // max guest capacity
schlafzimmer: number, // bedroom count
preisProNacht: number, // price per night in EUR
bewertung: number, // star rating (1–5)
anzahlBewertungen: number, // number of reviews
bild: string, // emoji used as image placeholder
beschreibung: string, // German description
accessibility: string[], // keys from ACCESSIBILITY_FEATURES
adresse: string,
}
```

Accessibility feature keys (defined in `ACCESSIBILITY_FEATURES`):
- **mobility:** `rollstuhlgerecht`, `rampe`, `aufzug`, `breiteSchieren`, `erdgeschoss`
- **bathroom:** `bodengleicheDusche`, `haltegriffe`
- **kitchen:** `behindertengerechteKueche`
- **outdoor:** `parkplatz`, `pool`, `strandnah`
- **sensory:** `sehbehinderung`, `hoerbehinderung`
- **general:** `haustiere`

---

## Key Conventions

### Language
All UI text, labels, and data are in **German**. Keep new UI text in German.

### JavaScript / JSX
- ES Modules (`"type": "module"` in package.json) — always use `import`/`export`
- React function components with hooks only — no class components
- No TypeScript (type declaration packages are present but not used)
- `useMemo` for expensive derived state; `useState` for local UI state
- ESLint flat config (v9): avoid unused imports and variables

### CSS
- All styles in `App.css` (component styles) and `index.css` (global resets)
- CSS custom properties defined in `:root` in `index.css`:
- Colors: `--primary`, `--primary-dark`, `--primary-light`, `--accent`, `--danger`, gray scale
- Utilities: `--radius`, `--shadow-sm`, `--shadow-md`, `--shadow-lg`
- Responsive breakpoints: `@media (max-width: 900px)` and `@media (max-width: 600px)`
- No CSS preprocessor, no CSS Modules, no CSS-in-JS
- Follow existing BEM-like class naming: `app-header`, `card-grid`, `filter-panel`, etc.

### Component Props

**`<FilterPanel filter onFilterChange />`**
- `filter`: current filter object
- `onFilterChange`: setter from `useState`

**`<HausCard haus isSelected onToggleCompare compareCount />`**
- `haus`: single vacation home object
- `isSelected`: whether this home is in the comparison list
- `onToggleCompare(id)`: callback to add/remove from comparison
- `compareCount`: current comparison list length (to enforce 3-item max)

**`<CompareTable hauser onRemove onClose />`**
- `hauser`: array of vacation home objects (max 3)
- `onRemove(id)`: removes a home from comparison (closes modal if last one removed)
- `onClose()`: closes the modal without removing homes

---

## Filter Defaults

```js
const DEFAULT_FILTER = { features: [], maxPreis: 400, minPersonen: 1, typ: "Alle" };
```

The "reset filters" button in `FilterPanel` and the empty-state button both reset to this value.

---

## Adding New Data

To add more vacation homes, append to the `ferienhauser` array in `src/data/ferienhauser.js`. Each entry must have a unique numeric `id`. The `accessibility` array should contain only keys present in `ACCESSIBILITY_FEATURES`.

To add a new accessibility feature, add it to the `ACCESSIBILITY_FEATURES` object with `label`, `icon` (emoji), and `category` (`"mobility"` | `"bathroom"` | `"kitchen"` | `"outdoor"` | `"sensory"` | `"general"`). The `FilterPanel` groups and renders features by category automatically.

---

## What Is NOT Present (Yet)

- No tests (no Vitest, Jest, or Testing Library)
- No TypeScript (packages installed but unused)
- No backend or API calls
- No environment variables / `.env` files
- No CI/CD pipeline
- No routing (single-page, no React Router)
- No state management library (no Redux, Zustand, etc.)
- No Prettier or other formatter — only ESLint

---

## ESLint Rules of Note

```js
// Unused vars are errors, EXCEPT uppercase/underscore-prefixed names
"no-unused-vars": ["error", { varsIgnorePattern: "^[A-Z_]" }]
```

Run `npm run lint` before committing. Lint errors will block the build in CI if one is added.