(null);
const [editGender, setEditGender] = useState<'man' | 'woman' | ''>('');
+ const [editActivityDate, setEditActivityDate] = useState('');
// ── Queries ──
@@ -2396,6 +2398,9 @@ export default function DoctorDetailPage({ isOwnProfile = false }: { isOwnProfil
social_linkedin: doctor.social_media?.linkedin ?? '',
});
setEditGender((doctor.gender as any) ?? '');
+ setEditActivityDate(
+ doctor.activity_time ? toGregorianDate(toDate(Number(doctor.activity_time))!) : ''
+ );
}
}, [doctor, reset]);
@@ -2419,6 +2424,9 @@ export default function DoctorDetailPage({ isOwnProfile = false }: { isOwnProfil
medical_system_code: body.medical_system_code || undefined,
mobile_number: body.mobile_number || undefined,
info: body.info || undefined,
+ ...(editActivityDate
+ ? { activity_time: Math.floor(new Date(`${editActivityDate}T12:00:00`).getTime() / 1000) }
+ : {}),
specialties: body.specialties ?? [],
doctor_services: body.services ?? [],
social_media: {
@@ -2877,6 +2885,18 @@ export default function DoctorDetailPage({ isOwnProfile = false }: { isOwnProfil
+
+
diff --git a/assets/admin/pages/DoctorFormPage.tsx b/assets/admin/pages/DoctorFormPage.tsx
index 990110ec..33d41cc8 100644
--- a/assets/admin/pages/DoctorFormPage.tsx
+++ b/assets/admin/pages/DoctorFormPage.tsx
@@ -14,6 +14,7 @@ import { api } from '../lib/api';
import type { ApiResponse } from '../lib/api';
import SearchableSelect from '../components/ui/SearchableSelect';
import MobileInput from '../components/ui/MobileInput';
+import PersianDatePicker from '../components/ui/PersianDatePicker';
import { iranMobileSchema } from '../lib/utils';
import { useAuthStore } from '../stores/authStore';
@@ -261,6 +262,7 @@ export default function DoctorFormPage() {
primaryRole === 'representation' ? '/api/v1/representation/doctor' : '/api/v1/admin/doctors';
const [selectedSpecialties, setSelectedSpecialties] = useState([]);
const [gender, setGender] = useState<'man' | 'woman' | ''>('');
+ const [activityDate, setActivityDate] = useState('');
const specialtiesQ = useQuery({
queryKey: ['specialties-list'],
@@ -286,6 +288,9 @@ export default function DoctorFormPage() {
degree: values.degree || undefined,
medical_system_code: values.medical_system_code || undefined,
info: values.info || undefined,
+ ...(activityDate
+ ? { activity_time: Math.floor(new Date(`${activityDate}T12:00:00`).getTime() / 1000) }
+ : {}),
specialties: selectedSpecialties,
}),
onSuccess: (res) => {
@@ -369,6 +374,18 @@ export default function DoctorFormPage() {
+
+
diff --git a/docs/api/admin.md b/docs/api/admin.md
index 2957d0cd..48c649d7 100644
--- a/docs/api/admin.md
+++ b/docs/api/admin.md
@@ -295,6 +295,9 @@ Delete a user.
|-------|------|----------|-------------|
| `mobile` | string | ✅ | موبایل ورود؛ باید فرمت معتبر موبایل ایران داشته باشد (`^09\d{9}$`) — ارقام فارسی/عربی به انگلیسی نرمال میشوند |
| `name` | string | ✅ | نام پزشک |
+| `gender` / `degree` / `medical_system_code` / `info` | string | ❌ | اطلاعات حرفهای |
+| `activity_time` | integer | ❌ | Unix timestamp (ثانیه) تاریخ شروع فعالیت؛ مبنای محاسبهٔ سال تجربه |
+| `specialties` | integer[] | ❌ | آرایهٔ IDهای تخصص |
#### Errors
| Code | HTTP | Description |
diff --git a/docs/api/doctor.md b/docs/api/doctor.md
index d88463b5..72201d85 100644
--- a/docs/api/doctor.md
+++ b/docs/api/doctor.md
@@ -34,6 +34,7 @@ Create a doctor profile for the authenticated user.
| `info` | string | ❌ | Bio/description |
| `specialties` | integer[] | ❌ | Array of specialty IDs |
| `doctor_services` | integer[] | ❌ | Array of doctor service IDs |
+| `activity_time` | integer | ❌ | Unix timestamp (ثانیه) تاریخ شروع فعالیت؛ مبنای محاسبهٔ `experience` (سال تجربه) در پاسخ |
### Response `201`
```json
diff --git a/docs/api/representation.md b/docs/api/representation.md
index bfa10b9b..8469e25f 100644
--- a/docs/api/representation.md
+++ b/docs/api/representation.md
@@ -349,6 +349,7 @@ Get yearly earnings dashboard for a representation.
| `mobile` | string | ✅ |
| `name` | string | ✅ |
| `gender` / `degree` / `medical_system_code` / `info` | string | ❌ |
+| `activity_time` | integer (Unix ts، تاریخ شروع فعالیت) | ❌ |
| `specialties` | integer[] | ❌ |
#### Response `201`
diff --git a/src/Admin/Controller/AdminApiController.php b/src/Admin/Controller/AdminApiController.php
index 551e7a46..23daeb14 100644
--- a/src/Admin/Controller/AdminApiController.php
+++ b/src/Admin/Controller/AdminApiController.php
@@ -418,6 +418,7 @@ class AdminApiController extends BaseController
if (!empty($data['medical_system_code'])) $doctor->setMedicalSystemCode($data['medical_system_code']);
if (!empty($data['info'])) $doctor->setInfo($data['info']);
if (!empty($data['mobile_number'])) $doctor->setMobileNumber($data['mobile_number']);
+ if (!empty($data['activity_time'])) $doctor->setActivityTime((int) $data['activity_time']);
if (!empty($data['specialties']) && is_array($data['specialties'])) {
foreach ($data['specialties'] as $id) {
diff --git a/src/Doctor/Controller/DoctorController.php b/src/Doctor/Controller/DoctorController.php
index 3bf99a0a..f17f2602 100644
--- a/src/Doctor/Controller/DoctorController.php
+++ b/src/Doctor/Controller/DoctorController.php
@@ -61,6 +61,7 @@ class DoctorController extends BaseController
new OA\Property(property: 'medical_system_code', type: 'string', nullable: true),
new OA\Property(property: 'degree', type: 'string', nullable: true),
new OA\Property(property: 'info', type: 'string', nullable: true),
+ new OA\Property(property: 'activity_time', type: 'integer', nullable: true, description: 'Unix timestamp (seconds) of career start date; basis for years-of-experience'),
new OA\Property(
property: 'specialties',
type: 'array',
@@ -269,6 +270,7 @@ class DoctorController extends BaseController
new OA\Property(property: 'medical_system_code', type: 'string', nullable: true),
new OA\Property(property: 'degree', type: 'string', nullable: true),
new OA\Property(property: 'info', type: 'string', nullable: true),
+ new OA\Property(property: 'activity_time', type: 'integer', nullable: true, description: 'Unix timestamp (seconds) of career start date; basis for years-of-experience'),
new OA\Property(
property: 'specialties',
type: 'array',
diff --git a/src/Representation/Controller/RepresentationActionController.php b/src/Representation/Controller/RepresentationActionController.php
index 852aeb55..e9e85ff1 100644
--- a/src/Representation/Controller/RepresentationActionController.php
+++ b/src/Representation/Controller/RepresentationActionController.php
@@ -242,6 +242,7 @@ class RepresentationActionController extends BaseController
new OA\Property(property: 'gender', type: 'string', nullable: true),
new OA\Property(property: 'degree', type: 'string', nullable: true),
new OA\Property(property: 'medical_system_code', type: 'string', nullable: true),
+ new OA\Property(property: 'activity_time', type: 'integer', nullable: true, description: 'Unix timestamp (seconds) of career start date; basis for years-of-experience'),
new OA\Property(property: 'specialties', type: 'array', items: new OA\Items(type: 'integer'), nullable: true),
]
)
@@ -284,6 +285,7 @@ class RepresentationActionController extends BaseController
if (!empty($data['medical_system_code'])) $doctor->setMedicalSystemCode($data['medical_system_code']);
if (!empty($data['info'])) $doctor->setInfo($data['info']);
if (!empty($data['mobile_number'])) $doctor->setMobileNumber($data['mobile_number']);
+ if (!empty($data['activity_time'])) $doctor->setActivityTime((int) $data['activity_time']);
if (!empty($data['specialties']) && is_array($data['specialties'])) {
foreach ($data['specialties'] as $id) {