# property-match — Development Guidelines

## Stack

- **Vite 8** + **React 19** + **TypeScript 6**
- **MUI v9** (`@mui/material`) — primary component library
- **Tailwind CSS v4** — utility classes via `@tailwindcss/vite` (no `tailwind.config.js`)
- **React Router v7** — import from `react-router`, not `react-router-dom`

## Components

Always reach for an existing MUI component before writing a custom one. Check the [MUI component list](https://mui.com/material-ui/all-components/) first. Only build a custom component when MUI has no equivalent or the required behavior diverges significantly from what MUI provides.

## Styling

Use Tailwind utility classes for all layout and styling. Do not write plain CSS rules or add styles to `.css` files. The only CSS file is `src/index.css`, which holds the Tailwind layer imports — do not add project styles there.


## Providers

All data access and data actions live in `src/provider/`.

### Naming

| Rule | Example |
|------|---------|
| Every provider file/class is suffixed `Provider` | `PropertyProvider`, `UserProvider` |
| Every provider backed by mock data is also prefixed `Mockup` | `MockupPropertyProvider`, `MockupUserProvider` |

### Interface pattern

Define a TypeScript interface for each provider so the mockup and the real implementation are interchangeable:
Every Interface should be prefixed with a capitalized I.

```ts
// src/provider/IPropertyProvider.ts
export interface PropertyProvider {
  getAll(): Promise<Property[]>
  getById(id: string): Promise<Property | null>
  create(data: CreatePropertyInput): Promise<Property>
  update(id: string, data: UpdatePropertyInput): Promise<Property>
  remove(id: string): Promise<void>
}
```

### Async methods

Every method in a provider must be `async` and return a `Promise`, even in the mockup. This ensures the real provider can be swapped in without changing any call sites.

```ts
// src/provider/MockupPropertyProvider.ts
import type { PropertyProvider } from './PropertyProvider'

const properties: Property[] = [ /* seed data */ ]

export const MockupPropertyProvider: PropertyProvider = {
  async getAll() {
    return [...properties]
  },
  async getById(id) {
    return properties.find(p => p.id === id) ?? null
  },
  async create(data) {
    const next: Property = { id: crypto.randomUUID(), ...data }
    properties.push(next)
    return next
  },
  async update(id, data) {
    const idx = properties.findIndex(p => p.id === id)
    properties[idx] = { ...properties[idx], ...data }
    return properties[idx]
  },
  async remove(id) {
    const idx = properties.findIndex(p => p.id === id)
    properties.splice(idx, 1)
  },
}
```

Swap to a real implementation by replacing `MockupPropertyProvider` with a provider that calls an API — no other code changes required.
