feat: implement location management with interactive maps
- Introduced a new `LocationMap` component for handling latitude and longitude inputs in forms and detail views. - Updated form and detail components to utilize the `LocationMap`, enhancing user experience by allowing map-based location selection. - Added internationalization support for map-related labels in English and Indonesian. - Developed unit tests for the `LocationMap` to ensure functionality and reliability. This commit enhances the application by providing a user-friendly interface for managing geographical locations, improving data accuracy and user interaction.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
---
|
||||
description: Entities with latitude/longitude must pick coords on OSM LocationMap in forms and render LocationMap on detail pages
|
||||
globs: apps/web/src/apps/main/modules/**/*.{ts,tsx}
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Location maps (lat / lng)
|
||||
|
||||
If an entity, DTO, or Zod schema has `latitude` and `longitude`, it is a **location entity**. Do not ship lat/lng as number fields alone.
|
||||
|
||||
Canonical component: `LocationMap` from `@repo/ui/map` (OpenStreetMap / Leaflet). Do not add Google Maps, Mapbox, or a second Leaflet wrapper.
|
||||
|
||||
Line geometry (`routeGeometry`) uses `RouteMap`, not `LocationMap`.
|
||||
|
||||
## Form (required)
|
||||
|
||||
Full-width `LocationMap` **above** the lat/lng inputs. Clicking the map writes both fields. Keep `FieldNumberInput` so values can still be typed.
|
||||
|
||||
```tsx
|
||||
// ✅ GOOD
|
||||
<LocationMap
|
||||
latitude={formControl.watch('latitude')}
|
||||
longitude={formControl.watch('longitude')}
|
||||
helperLabel={t('common:map.pickLocation')}
|
||||
onChange={(point) => {
|
||||
formControl.setValue('latitude', point.latitude, { shouldDirty: true, shouldValidate: true });
|
||||
formControl.setValue('longitude', point.longitude, { shouldDirty: true, shouldValidate: true });
|
||||
}}
|
||||
/>
|
||||
|
||||
// ❌ BAD — lat/lng inputs with no map picker
|
||||
<FieldNumberInput name="latitude" />
|
||||
<FieldNumberInput name="longitude" />
|
||||
```
|
||||
|
||||
Layout: map is full width (form-layout compound field). Lat/lng stay a two-column pair under the map. Copy `customers` / `branches` `form-location.tsx`.
|
||||
|
||||
## Detail (required)
|
||||
|
||||
Render `LocationMap` **without** `onChange` (read-only). Pass `emptyLabel` when coords are missing. Keep `FieldValue` for the numeric pair under the map.
|
||||
|
||||
```tsx
|
||||
// ✅ GOOD
|
||||
<LocationMap
|
||||
latitude={data?.latitude}
|
||||
longitude={data?.longitude}
|
||||
emptyLabel={t('common:map.noLocation')}
|
||||
/>
|
||||
|
||||
// ❌ BAD — coordinates as text only
|
||||
<FieldValue label={t('common:fields.latitude')} value={data?.latitude} />
|
||||
```
|
||||
|
||||
Copy `customers` / `branches` `detail-location.tsx`.
|
||||
|
||||
## i18n and validation
|
||||
|
||||
- Helper / empty copy: `common:map.pickLocation`, `common:map.noLocation`
|
||||
- Labels: `common:fields.latitude`, `common:fields.longitude`
|
||||
- Keep existing Zod lat/lng range checks (`optionalLatitudeSchema` / `optionalLongitudeSchema`)
|
||||
Reference in New Issue
Block a user