81 lines
2.8 KiB
Markdown
81 lines
2.8 KiB
Markdown
# 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.
|