Refactor AddressFormContent and ProfilePage to integrate CountrySelect for nationality selection and update address payload handling

This commit is contained in:
estifanos
2026-08-08 07:40:33 +00:00
parent 451e9a7f35
commit 56de3727fa
4 changed files with 20 additions and 19 deletions

View File

@@ -2,7 +2,7 @@ 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 { ethiopianPhone, optionalEthiopianPhone } from '@ema-platform/ui';
import { ethiopianPhone, optionalEthiopianPhone, CountrySelect } from '@ema-platform/ui';
import { LocationPicker } from '../../location/components/LocationPicker';
import { useGetLocationTypesQuery } from '../../location/api/location-api';
import type { Location } from '../../location/types/location';
@@ -10,11 +10,11 @@ import type { Location } from '../../location/types/location';
export const addressSchema = z.object({
idType: z.string().min(1, 'Select ID type'),
idNumber: z.string().trim().min(1, 'Enter ID number'),
nationality: z.string().trim().min(1, 'Enter nationality'),
// Alpha-2 country code from CountrySelect; converted to a full name at submit.
nationality: z.string().min(1, 'Select nationality'),
primaryPhoneNumber: ethiopianPhone,
secondaryPhoneNumber: optionalEthiopianPhone,
email: z.string().trim().email('Invalid email').optional().or(z.literal('')),
website: z.string().trim().url('Enter a valid URL').optional().or(z.literal('')),
regionId: z.string().optional(),
cityId: z.string().optional(),
subcityId: z.string().optional(),
@@ -115,11 +115,11 @@ export function AddressFormContent({
{...register('idNumber')}
error={errors.idNumber?.message}
/>
<TextInput
<CountrySelect
label="Nationality"
placeholder="e.g. Ethiopian"
required
{...register('nationality')}
value={watch('nationality') || null}
onChange={(val) => setValue('nationality', val || '', { shouldValidate: true })}
error={errors.nationality?.message}
/>
<TextInput
@@ -144,12 +144,6 @@ export function AddressFormContent({
{...register('email')}
error={errors.email?.message}
/>
<TextInput
label="Website"
placeholder="https://example.com"
{...register('website')}
error={errors.website?.message}
/>
</SimpleGrid>
<Text fw={600} fz="sm" tt="uppercase" c="gray.6" mt="lg" mb="sm">

View File

@@ -47,7 +47,7 @@ import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { useTranslation } from 'react-i18next';
import { notify, PageHeader, useErrorHandler, passwordSchema as strongPasswordSchema, PasswordRequirements } from '@ema-platform/ui';
import { notify, PageHeader, useErrorHandler, passwordSchema as strongPasswordSchema, PasswordRequirements, getCountryCode } from '@ema-platform/ui';
import { useApiMutation } from '@ema-platform/api';
import { setUser, useCurrentProfile } from '@ema-platform/auth';
import type { CurrentProfile } from '@ema-platform/auth';
@@ -201,11 +201,11 @@ export function ProfilePage() {
setLoadedAddress({
idType: currentProfile.address?.idType || '',
idNumber: currentProfile.address?.idNumber || '',
nationality: currentProfile.address?.nationality || '',
// Stored as a country name; the select works in alpha-2 codes.
nationality: getCountryCode(currentProfile.address?.nationality) || '',
primaryPhoneNumber: user?.phoneNumber || '',
secondaryPhoneNumber: currentProfile.address?.secondaryPhoneNumber || '',
email: user?.email || '',
website: currentProfile.address?.website || '',
regionId: currentProfile.address?.regionId || '',
cityId: currentProfile.address?.cityId || '',
subcityId: currentProfile.address?.subCityId || '',

View File

@@ -1,3 +1,4 @@
import { getCountryName } from '@ema-platform/ui';
import type { AddressValues } from '../components/AddressFormContent';
/** Exact request body of `POST /addresss/profile/{profileId}`. */
@@ -14,7 +15,7 @@ export interface AddressPayload {
primaryPhoneNumber: string;
secondaryPhoneNumber?: string;
email?: string;
website?: string;
website: null;
postalAddress?: string;
emergencyContactName?: string;
emergencyContactPhone?: string;
@@ -28,7 +29,8 @@ export function toAddressPayload(values: AddressValues): AddressPayload {
return {
idType: values.idType.trim(),
idNumber: values.idNumber.trim(),
nationality: values.nationality.trim(),
// Form holds the alpha-2 code (CountrySelect); API stores the full name.
nationality: getCountryName(values.nationality),
regionId: clean(values.regionId),
cityId: clean(values.cityId),
subcityId: clean(values.subcityId),
@@ -38,7 +40,7 @@ export function toAddressPayload(values: AddressValues): AddressPayload {
primaryPhoneNumber: values.primaryPhoneNumber,
secondaryPhoneNumber: clean(values.secondaryPhoneNumber),
email: clean(values.email),
website: clean(values.website),
website: null, // no website field in the form — always sent as null
postalAddress: clean(values.postalAddress),
emergencyContactName: clean(values.emergencyContactName),
emergencyContactPhone: clean(values.emergencyContactPhone),