mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-08 00:45:42 +00:00
feat: add i18n support and localized labels to certification and profession features commit
This commit is contained in:
@@ -6,11 +6,12 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface LocationPickerProps {
|
||||
value?: string;
|
||||
onChange: (locationId: string | null) => void;
|
||||
onChange?: (locationId: string | null) => void;
|
||||
onChainChange?: (chain: Location[]) => void;
|
||||
required?: boolean;
|
||||
}
|
||||
|
||||
export function LocationPicker({ value, onChange, required }: LocationPickerProps) {
|
||||
export function LocationPicker({ value, onChange, onChainChange, required }: LocationPickerProps) {
|
||||
const { t } = useTranslation();
|
||||
const { data: typesRes, isLoading: typesLoading } = useGetLocationTypesQuery();
|
||||
const { data: locsRes, isLoading: locsLoading } = useGetLocationsQuery({ take: 10000 });
|
||||
@@ -54,7 +55,8 @@ export function LocationPicker({ value, onChange, required }: LocationPickerProp
|
||||
current = current.parentId ? locMap.get(current.parentId) : undefined;
|
||||
}
|
||||
setSelectedChain(chain);
|
||||
}, [value, locMap]);
|
||||
onChainChange?.(chain);
|
||||
}, [value, locMap, onChainChange]);
|
||||
|
||||
const currentLevelChildren = useMemo(() => {
|
||||
const parentId =
|
||||
@@ -89,7 +91,8 @@ export function LocationPicker({ value, onChange, required }: LocationPickerProp
|
||||
if (!id) {
|
||||
const newChain = selectedChain.slice(0, -1);
|
||||
setSelectedChain(newChain);
|
||||
onChange(newChain.length > 0 ? newChain[newChain.length - 1].id : null);
|
||||
onChange?.(newChain.length > 0 ? newChain[newChain.length - 1].id : null);
|
||||
onChainChange?.(newChain);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -100,9 +103,10 @@ export function LocationPicker({ value, onChange, required }: LocationPickerProp
|
||||
newChain.push(loc);
|
||||
setSelectedChain(newChain);
|
||||
|
||||
onChange(id);
|
||||
onChange?.(id);
|
||||
onChainChange?.(newChain);
|
||||
},
|
||||
[selectedChain, locMap, onChange, depth],
|
||||
[selectedChain, locMap, onChange, onChainChange, depth],
|
||||
);
|
||||
|
||||
const buildOptions = (levelIdx: number) => {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { Select, SimpleGrid, Text, TextInput } from '@mantine/core';
|
||||
import type { FieldErrors, UseFormRegister, UseFormSetValue, UseFormWatch, UseFormTrigger } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import { LocationPicker } from '../../location/components/LocationPicker';
|
||||
import { useGetLocationTypesQuery } from '../../location/api/location-api';
|
||||
import type { Location } from '../../location/types/location';
|
||||
|
||||
export const addressSchema = z.object({
|
||||
idType: z.string().min(1, 'Select ID type'),
|
||||
@@ -25,6 +29,13 @@ export type AddressValues = z.infer<typeof addressSchema>;
|
||||
|
||||
export const ID_TYPES = ['NID', 'VITAL', 'PASSPORT', 'DRIVERS_LICENSE'] as const;
|
||||
|
||||
const LEVEL_TO_FIELD: Record<number, keyof AddressValues> = {
|
||||
1: 'cityId',
|
||||
2: 'subcityId',
|
||||
3: 'woredaId',
|
||||
4: 'kebeleId',
|
||||
};
|
||||
|
||||
interface AddressFormContentProps {
|
||||
register: UseFormRegister<AddressValues>;
|
||||
errors: FieldErrors<AddressValues>;
|
||||
@@ -40,6 +51,38 @@ export function AddressFormContent({
|
||||
watch,
|
||||
trigger,
|
||||
}: AddressFormContentProps) {
|
||||
const { data: typesRes } = useGetLocationTypesQuery();
|
||||
const locationTypes = typesRes?.items ?? [];
|
||||
|
||||
const typeLevelMap = useMemo(() => {
|
||||
const map = new Map<string, number>();
|
||||
locationTypes.forEach((lt) => map.set(lt.id, lt.level));
|
||||
return map;
|
||||
}, [locationTypes]);
|
||||
|
||||
const leafId = watch('kebeleId') || watch('woredaId') || watch('subcityId') || watch('cityId') || undefined;
|
||||
|
||||
const handleChainChange = useCallback(
|
||||
(chain: Location[]) => {
|
||||
if (chain.length > 0 && !typeLevelMap.has(chain[0].locationTypeId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setValue('cityId', '');
|
||||
setValue('subcityId', '');
|
||||
setValue('woredaId', '');
|
||||
setValue('kebeleId', '');
|
||||
|
||||
chain.forEach((loc) => {
|
||||
const level = typeLevelMap.get(loc.locationTypeId);
|
||||
if (level && LEVEL_TO_FIELD[level]) {
|
||||
setValue(LEVEL_TO_FIELD[level], loc.id);
|
||||
}
|
||||
});
|
||||
},
|
||||
[setValue, typeLevelMap],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md">
|
||||
@@ -93,37 +136,11 @@ export function AddressFormContent({
|
||||
<Text fw={600} fz="sm" tt="uppercase" c="gray.6" mt="lg" mb="sm">
|
||||
Address
|
||||
</Text>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md">
|
||||
<TextInput
|
||||
label="Region ID"
|
||||
placeholder="Region UUID (optional)"
|
||||
{...register('regionId')}
|
||||
error={errors.regionId?.message}
|
||||
/>
|
||||
<TextInput
|
||||
label="City ID"
|
||||
placeholder="City UUID (optional)"
|
||||
{...register('cityId')}
|
||||
error={errors.cityId?.message}
|
||||
/>
|
||||
<TextInput
|
||||
label="Subcity ID"
|
||||
placeholder="Subcity UUID (optional)"
|
||||
{...register('subcityId')}
|
||||
error={errors.subcityId?.message}
|
||||
/>
|
||||
<TextInput
|
||||
label="Woreda ID"
|
||||
placeholder="Woreda UUID (optional)"
|
||||
{...register('woredaId')}
|
||||
error={errors.woredaId?.message}
|
||||
/>
|
||||
<TextInput
|
||||
label="Kebele ID"
|
||||
placeholder="Kebele UUID (optional)"
|
||||
{...register('kebeleId')}
|
||||
error={errors.kebeleId?.message}
|
||||
/>
|
||||
<LocationPicker
|
||||
value={leafId}
|
||||
onChainChange={handleChainChange}
|
||||
/>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md" mt="md">
|
||||
<TextInput
|
||||
label="Street Address"
|
||||
placeholder="Street name, house number"
|
||||
|
||||
@@ -33,9 +33,8 @@ import {
|
||||
IconUser,
|
||||
} from '@tabler/icons-react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { notify } from '@ema-platform/ui';
|
||||
import { BilingualInput } from '../../../components/BilingualInput';
|
||||
import type { BilingualValue } from '../../../components/BilingualInput';
|
||||
import { notify, BilingualInput } from '@ema-platform/ui';
|
||||
import type { BilingualValue } from '@ema-platform/ui';
|
||||
import { AmharicDatePicker, toEthiopicDateLabel } from '../../../components/AmharicDatePicker';
|
||||
import { LocationPicker } from '../../location/components/LocationPicker';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user