diff --git a/client/messages/en.json b/client/messages/en.json
index 137a460..96fce49 100644
--- a/client/messages/en.json
+++ b/client/messages/en.json
@@ -309,6 +309,10 @@
"line_hint": "Building, street, unit — the detail a nurse needs to find the door.",
"line_required": "Enter the street address",
"city_required": "Select a city",
+ "recipient_name_label": "Recipient name",
+ "recipient_name_required": "Enter who the nurse should ask for",
+ "recipient_phone_label": "Recipient phone",
+ "recipient_phone_invalid": "Enter a valid Iranian mobile number",
"set_primary_toggle": "Set as primary address",
"map_hint": "Tap or drag the marker to the patient's exact location.",
"map_required": "Drop a pin on the map",
diff --git a/client/messages/fa.json b/client/messages/fa.json
index bec5600..b383c03 100644
--- a/client/messages/fa.json
+++ b/client/messages/fa.json
@@ -309,6 +309,10 @@
"line_hint": "پلاک، خیابان، واحد — جزئیاتی که پرستار برای یافتن درِ منزل نیاز دارد.",
"line_required": "نشانی کامل را وارد کنید",
"city_required": "شهر را انتخاب کنید",
+ "recipient_name_label": "نام تحویلگیرنده",
+ "recipient_name_required": "نام فردی که پرستار باید بپرسد را وارد کنید",
+ "recipient_phone_label": "شماره تماس تحویلگیرنده",
+ "recipient_phone_invalid": "یک شماره موبایل معتبر ایرانی وارد کنید",
"set_primary_toggle": "بهعنوان آدرس اصلی تنظیم شود",
"map_hint": "برای تعیین محل دقیق بیمار، نشانگر را بکشید یا روی نقشه بزنید.",
"map_required": "روی نقشه یک پین بگذارید",
diff --git a/client/src/app/[locale]/(private-routes)/(customer)/addresses/page.tsx b/client/src/app/[locale]/(private-routes)/(customer)/addresses/page.tsx
index a161c6a..3f28f7a 100644
--- a/client/src/app/[locale]/(private-routes)/(customer)/addresses/page.tsx
+++ b/client/src/app/[locale]/(private-routes)/(customer)/addresses/page.tsx
@@ -172,6 +172,8 @@ export default function AddressesPage() {
latitude: editing.latitude,
longitude: editing.longitude,
isPrimary: editing.isPrimary,
+ recipientName: editing.recipientName,
+ recipientPhone: editing.recipientPhone,
}
: undefined
}
diff --git a/client/src/components/geography/AddressForm.test.tsx b/client/src/components/geography/AddressForm.test.tsx
index d753638..7a5d9bb 100644
--- a/client/src/components/geography/AddressForm.test.tsx
+++ b/client/src/components/geography/AddressForm.test.tsx
@@ -51,6 +51,8 @@ describe(' component', () => {
latitude: 35.7,
longitude: 51.4,
isPrimary: false,
+ recipientName: 'Sara',
+ recipientPhone: '09120001234',
}}
onSubmit={onSubmit}
/>
@@ -67,6 +69,8 @@ describe(' component', () => {
latitude: 35.7,
longitude: 51.4,
isPrimary: false,
+ recipientName: 'Sara',
+ recipientPhone: '09120001234',
});
});
});
diff --git a/client/src/components/geography/AddressForm.tsx b/client/src/components/geography/AddressForm.tsx
index 326a452..e42009c 100644
--- a/client/src/components/geography/AddressForm.tsx
+++ b/client/src/components/geography/AddressForm.tsx
@@ -7,6 +7,7 @@ import Stack from '@mui/material/Stack';
import Switch from '@mui/material/Switch';
import { AppButton } from '@/components/common';
import { RhfControlGroup, RhfTextField } from '@/components/common/form';
+import PhoneNumberField, { isIranianMobile } from '@/components/PhoneNumberField';
import { cityCentroid } from '@/services/geography/constants';
import type { CreateAddressInput, LatLng } from '@/services/addresses/types';
import CascadingRegionSelect, { type CascadingRegionValue } from './CascadingRegionSelect';
@@ -22,6 +23,8 @@ export interface AddressFormInitial {
latitude?: number | null;
longitude?: number | null;
isPrimary?: boolean;
+ recipientName?: string | null;
+ recipientPhone?: string | null;
}
export interface AddressFormProps {
@@ -39,6 +42,8 @@ interface AddressFormValues {
pin: LatLng | null;
addressLine: string;
isPrimary: boolean;
+ recipientName: string;
+ recipientPhone: string;
}
// Only prefill the region when we have the province — a city id without its province can't drive
@@ -78,6 +83,8 @@ const AddressForm: FunctionComponent = ({ initial, submitting
pin: initialPin(initial),
addressLine: initial?.addressLine ?? '',
isPrimary: initial?.isPrimary ?? false,
+ recipientName: initial?.recipientName ?? '',
+ recipientPhone: initial?.recipientPhone ?? '',
},
});
const { control, handleSubmit, formState } = form;
@@ -98,6 +105,8 @@ const AddressForm: FunctionComponent = ({ initial, submitting
latitude: (values.pin as LatLng).latitude,
longitude: (values.pin as LatLng).longitude,
isPrimary: values.isPrimary,
+ recipientName: values.recipientName.trim(),
+ recipientPhone: values.recipientPhone,
});
};
@@ -153,6 +162,29 @@ const AddressForm: FunctionComponent = ({ initial, submitting
fullWidth
/>
+
+ name="recipientName"
+ label={t('recipient_name_label')}
+ rules={{ validate: (value) => String(value ?? '').trim().length > 0 || t('recipient_name_required') }}
+ fullWidth
+ />
+
+
+ name="recipientPhone"
+ rules={{ validate: (value) => isIranianMobile(String(value ?? '')) }}
+ >
+ {({ field, hasError }) => (
+
+ )}
+
+
name="isPrimary">
{({ field }) => (