updates
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
---
|
||||
name: api-enums-reference
|
||||
description: "Use the central API enums file as the source of truth for enum values in this project. Use when: adding enum fields, updating enum options, creating form selects, typing status/discount/rate fields, syncing backend enum changes, or avoiding duplicated hardcoded enum literals."
|
||||
---
|
||||
|
||||
# API Enums Reference
|
||||
|
||||
Use this skill whenever work touches enum-like fields in API clients, schemas, forms, table filters, or page logic.
|
||||
|
||||
## Source of Truth
|
||||
|
||||
All shared enum values and enum union types must come from:
|
||||
|
||||
- packages/api/src/contracts/enums.ts
|
||||
|
||||
Do not recreate enum arrays inline when an equivalent enum already exists in this file.
|
||||
|
||||
## Rules
|
||||
|
||||
1. Reuse before creating.
|
||||
Search and import from `@garage/api` exports (or local contracts path inside packages/api) before adding new literals.
|
||||
|
||||
2. Keep runtime and type together.
|
||||
For every enum, keep this pattern in `enums.ts`:
|
||||
|
||||
```ts
|
||||
export const ExampleStatus = ['a', 'b'] as const;
|
||||
export type ExampleStatus = (typeof ExampleStatus)[number];
|
||||
```
|
||||
|
||||
3. Preserve backend values exactly.
|
||||
Enum string values are case- and space-sensitive; keep exact spelling from backend migrations/spec.
|
||||
|
||||
4. Avoid duplicate synonyms.
|
||||
If two domains share the same canonical values, prefer reusing an existing enum unless domain separation is intentional.
|
||||
|
||||
5. Update centrally first.
|
||||
When backend enum options change, update `packages/api/src/contracts/enums.ts` first, then update consuming UI/API code.
|
||||
|
||||
6. Prefer imports in forms and schemas.
|
||||
Use central enums for select options and for typed payload/status fields instead of hardcoded string unions.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Identify the enum field and backend values.
|
||||
2. Check `packages/api/src/contracts/enums.ts` for an existing enum.
|
||||
3. If found, import and use it.
|
||||
4. If missing, add a new const+type pair in `enums.ts`.
|
||||
5. Update consumers to reference the central enum.
|
||||
6. Verify there are no duplicated literal arrays for the same field.
|
||||
|
||||
## Examples
|
||||
|
||||
```ts
|
||||
import { InvoiceStatus, type InvoiceStatus as InvoiceStatusType } from '@garage/api'
|
||||
|
||||
const statusOptions = InvoiceStatus
|
||||
|
||||
type Payload = {
|
||||
status: InvoiceStatusType
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
import { DiscountType } from '@garage/api'
|
||||
|
||||
const discountOptions = DiscountType.map((value) => ({
|
||||
label: value,
|
||||
value,
|
||||
}))
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- If a module needs a presentation-specific label, map from the central enum value instead of changing raw enum literals.
|
||||
- If backend adds/removes values, keep API and dashboard aligned in the same change set.
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
name: date-time-pickers
|
||||
description: "Use RhfDateField and RhfTimeField (shadcn Calendar/Popover-based) for all date and time inputs in forms. Use when: adding date fields, adding time fields, replacing `type=\"date\"` or `type=\"time\"` RhfTextField inputs, building any form that captures a date or time value."
|
||||
---
|
||||
|
||||
# Date & Time Pickers
|
||||
|
||||
Always use the shadcn-based picker components for date and time fields. Never use `<RhfTextField type="date">` or `<RhfTextField type="time">`.
|
||||
|
||||
## Components
|
||||
|
||||
| Use For | Component | Import |
|
||||
|---|---|---|
|
||||
| Date fields (YYYY-MM-DD) | `RhfDateField` | `@/shared/components/form` |
|
||||
| Time fields (HH:MM:SS) | `RhfTimeField` | `@/shared/components/form` |
|
||||
|
||||
## RhfDateField
|
||||
|
||||
Renders a shadcn Calendar inside a Popover. Value is a `string` in `"YYYY-MM-DD"` format.
|
||||
|
||||
```tsx
|
||||
import { RhfDateField } from "@/shared/components/form"
|
||||
|
||||
<RhfDateField name="check_in_date" label="Check-in Date" />
|
||||
```
|
||||
|
||||
**Schema type**: `z.string().optional()` (stores `"YYYY-MM-DD"`)
|
||||
|
||||
**Default value**: `""` for empty, or `new Date().toISOString().split("T")[0]` for today.
|
||||
|
||||
**`mapToFormValues`**: `d.check_in_date ? d.check_in_date.split("T")[0] : ""`
|
||||
|
||||
**`mapFormToPayload`**: `values.check_in_date || undefined`
|
||||
|
||||
## RhfTimeField
|
||||
|
||||
Renders an HH / MM / SS spinner inside a Popover. Value is a `string` in `"HH:MM:SS"` format.
|
||||
|
||||
```tsx
|
||||
import { RhfTimeField } from "@/shared/components/form"
|
||||
|
||||
// With seconds (default)
|
||||
<RhfTimeField name="check_in_time" label="Check-in Time" withSeconds />
|
||||
|
||||
// Without seconds
|
||||
<RhfTimeField name="check_in_time" label="Check-in Time" />
|
||||
```
|
||||
|
||||
**Props**:
|
||||
- `withSeconds?: boolean` — show the SS spinner (default `true`)
|
||||
- `placeholder?: string` — trigger button placeholder text
|
||||
|
||||
**Schema type**: `z.string().optional()` (stores `"HH:MM:SS"` or `"HH:MM"`)
|
||||
|
||||
**Default value for current time**:
|
||||
```ts
|
||||
(() => {
|
||||
const n = new Date()
|
||||
return `${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}:${String(n.getSeconds()).padStart(2,"0")}`
|
||||
})()
|
||||
```
|
||||
|
||||
**`mapToFormValues`** (API returns `"HH:MM"` or ISO datetime):
|
||||
- If ISO: `d.check_in_time ? d.check_in_time.split("T")[1]?.slice(0, 8) ?? "" : ""`
|
||||
- If plain time string: `d.check_in_time ?? ""`
|
||||
|
||||
**`mapFormToPayload`**: `values.check_in_time || undefined`
|
||||
|
||||
## Underlying Controls (non-RHF use)
|
||||
|
||||
If you need to use the pickers outside of RHF:
|
||||
|
||||
```tsx
|
||||
import { DatePickerField, TimePickerField } from "@/shared/components/form"
|
||||
|
||||
<DatePickerField value={date} onChange={setDate} placeholder="Select date" />
|
||||
<TimePickerField value={time} onChange={setTime} withSeconds />
|
||||
```
|
||||
|
||||
## File Locations
|
||||
|
||||
- Control: `apps/dashboard/shared/components/form/controls/date-picker-field.tsx`
|
||||
- Control: `apps/dashboard/shared/components/form/controls/time-picker-field.tsx`
|
||||
- RHF wrapper: `apps/dashboard/shared/components/form/fields/rhf-date-field.tsx`
|
||||
- RHF wrapper: `apps/dashboard/shared/components/form/fields/rhf-time-field.tsx`
|
||||
- Exports: `apps/dashboard/shared/components/form/index.ts`
|
||||
Reference in New Issue
Block a user