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:
+5
-3
@@ -1,4 +1,5 @@
|
||||
import { Box, Paper, SimpleGrid, FieldValue, Text } from '@repo/ui/components';
|
||||
import { Paper, SimpleGrid, FieldValue, Stack, Text } from '@repo/ui/components';
|
||||
import { LocationMap } from '@repo/ui/map';
|
||||
import { useDetailPageContext, useEnterpriseModuleTranslationContext } from '@repo/ui/foundations';
|
||||
import type { BranchEntity } from '../../../domain/entities';
|
||||
|
||||
@@ -13,13 +14,14 @@ export function DetailLocation() {
|
||||
<Text fw={600} mb="md">
|
||||
{t('section_location')}
|
||||
</Text>
|
||||
<Box>
|
||||
<Stack gap="md">
|
||||
<LocationMap latitude={data?.latitude} longitude={data?.longitude} emptyLabel={t('common:map.noLocation')} />
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 4 }} spacing="md" verticalSpacing="xl">
|
||||
<FieldValue label={t('common:fields.latitude')} value={data?.latitude} />
|
||||
<FieldValue label={t('common:fields.longitude')} value={data?.longitude} />
|
||||
<FieldValue label={t('common:fields.division')} value={divisionLabel} />
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
+48
-34
@@ -1,5 +1,6 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Box, FieldNumberInput, FieldAsyncSelect, Paper, SimpleGrid, Text } from '@repo/ui/components';
|
||||
import { Box, FieldNumberInput, FieldAsyncSelect, Paper, SimpleGrid, Stack, Text } from '@repo/ui/components';
|
||||
import { LocationMap } from '@repo/ui/map';
|
||||
import { useEnterpriseModuleTranslationContext, useFormPageContext } from '@repo/ui/foundations';
|
||||
import { loadDivisionOptions } from '../../../../shared/load-division-options';
|
||||
import { divisionsDataService } from '../../../../divisions/domain/factories';
|
||||
@@ -9,6 +10,8 @@ export function FormLocation() {
|
||||
const { formControl } = useFormPageContext();
|
||||
const { t } = useEnterpriseModuleTranslationContext();
|
||||
const division = formControl.watch('division');
|
||||
const latitude = formControl.watch('latitude');
|
||||
const longitude = formControl.watch('longitude');
|
||||
|
||||
useEffect(() => {
|
||||
const current = formControl.getValues('division') as DivisionEntity | null | undefined;
|
||||
@@ -26,39 +29,50 @@ export function FormLocation() {
|
||||
<Text fw={600} mb="md">
|
||||
{t('section_location')}
|
||||
</Text>
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
|
||||
<FieldNumberInput
|
||||
control={formControl.control}
|
||||
name="latitude"
|
||||
label={t('common:fields.latitude')}
|
||||
placeholder="-6.2"
|
||||
decimalScale={6}
|
||||
radius="md"
|
||||
/>
|
||||
<FieldNumberInput
|
||||
control={formControl.control}
|
||||
name="longitude"
|
||||
label={t('common:fields.longitude')}
|
||||
placeholder="106.8"
|
||||
decimalScale={6}
|
||||
radius="md"
|
||||
/>
|
||||
<FieldAsyncSelect<DivisionEntity>
|
||||
control={formControl.control}
|
||||
name="division"
|
||||
label={t('common:fields.division')}
|
||||
placeholder={t('common:fields.division')}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
clearable
|
||||
searchable
|
||||
loadOptions={loadDivisionOptions}
|
||||
defaultOptions={division ? [division] : []}
|
||||
renderLabel={(item) => `${item.code} - ${item.name}`}
|
||||
/>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
<Stack gap="md">
|
||||
<LocationMap
|
||||
latitude={latitude}
|
||||
longitude={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 });
|
||||
}}
|
||||
/>
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
|
||||
<FieldNumberInput
|
||||
control={formControl.control}
|
||||
name="latitude"
|
||||
label={t('common:fields.latitude')}
|
||||
placeholder="-6.2"
|
||||
decimalScale={6}
|
||||
radius="md"
|
||||
/>
|
||||
<FieldNumberInput
|
||||
control={formControl.control}
|
||||
name="longitude"
|
||||
label={t('common:fields.longitude')}
|
||||
placeholder="106.8"
|
||||
decimalScale={6}
|
||||
radius="md"
|
||||
/>
|
||||
<FieldAsyncSelect<DivisionEntity>
|
||||
control={formControl.control}
|
||||
name="division"
|
||||
label={t('common:fields.division')}
|
||||
placeholder={t('common:fields.division')}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
clearable
|
||||
searchable
|
||||
loadOptions={loadDivisionOptions}
|
||||
defaultOptions={division ? [division] : []}
|
||||
renderLabel={(item) => `${item.code} - ${item.name}`}
|
||||
/>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,4 +1,5 @@
|
||||
import { Box, Paper, SimpleGrid, FieldValue, Text } from '@repo/ui/components';
|
||||
import { Paper, SimpleGrid, FieldValue, Stack, Text } from '@repo/ui/components';
|
||||
import { LocationMap } from '@repo/ui/map';
|
||||
import { useDetailPageContext, useEnterpriseModuleTranslationContext } from '@repo/ui/foundations';
|
||||
import type { CustomerEntity } from '../../../domain/entities';
|
||||
|
||||
@@ -12,12 +13,13 @@ export function DetailLocation() {
|
||||
<Text fw={600} mb="md">
|
||||
{t('section_location')}
|
||||
</Text>
|
||||
<Box>
|
||||
<Stack gap="md">
|
||||
<LocationMap latitude={data?.latitude} longitude={data?.longitude} emptyLabel={t('common:map.noLocation')} />
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 4 }} spacing="md" verticalSpacing="xl">
|
||||
<FieldValue label={t('common:fields.latitude')} value={data?.latitude} />
|
||||
<FieldValue label={t('common:fields.longitude')} value={data?.longitude} />
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
+35
-21
@@ -1,35 +1,49 @@
|
||||
import { Box, FieldNumberInput, Paper, SimpleGrid, Text } from '@repo/ui/components';
|
||||
import { Box, FieldNumberInput, Paper, SimpleGrid, Stack, Text } from '@repo/ui/components';
|
||||
import { LocationMap } from '@repo/ui/map';
|
||||
import { useEnterpriseModuleTranslationContext, useFormPageContext } from '@repo/ui/foundations';
|
||||
|
||||
export function FormLocation() {
|
||||
const { formControl } = useFormPageContext();
|
||||
const { t } = useEnterpriseModuleTranslationContext();
|
||||
const latitude = formControl.watch('latitude');
|
||||
const longitude = formControl.watch('longitude');
|
||||
|
||||
return (
|
||||
<Paper withBorder shadow="sm" radius="md" p="xl">
|
||||
<Text fw={600} mb="md">
|
||||
{t('section_location')}
|
||||
</Text>
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
|
||||
<FieldNumberInput
|
||||
control={formControl.control}
|
||||
name="latitude"
|
||||
label={t('common:fields.latitude')}
|
||||
placeholder="-6.2"
|
||||
decimalScale={6}
|
||||
radius="md"
|
||||
/>
|
||||
<FieldNumberInput
|
||||
control={formControl.control}
|
||||
name="longitude"
|
||||
label={t('common:fields.longitude')}
|
||||
placeholder="106.8"
|
||||
decimalScale={6}
|
||||
radius="md"
|
||||
/>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
<Stack gap="md">
|
||||
<LocationMap
|
||||
latitude={latitude}
|
||||
longitude={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 });
|
||||
}}
|
||||
/>
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
|
||||
<FieldNumberInput
|
||||
control={formControl.control}
|
||||
name="latitude"
|
||||
label={t('common:fields.latitude')}
|
||||
placeholder="-6.2"
|
||||
decimalScale={6}
|
||||
radius="md"
|
||||
/>
|
||||
<FieldNumberInput
|
||||
control={formControl.control}
|
||||
name="longitude"
|
||||
label={t('common:fields.longitude')}
|
||||
placeholder="106.8"
|
||||
decimalScale={6}
|
||||
radius="md"
|
||||
/>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user