Commit Graph
536 Commits
Author SHA1 Message Date
hamed 5937f7e176 feat: add service-based booking mode to appointment scheduling
- Introduced a new booking mode in WeeklySchedule to support service-based appointments.
- Updated SlotCalculatorService to calculate available start times based on selected service durations and buffer times.
- Enhanced AppointmentController to handle service items during booking, calculating slot_end on the server side.
- Implemented validation to ensure at least one bookable service exists for doctors in service mode.
- Added new API endpoint to retrieve available appointment slots based on selected services.
- Updated MyAppointmentsController to accept service items during appointment creation.
- Modified ServiceItem entity to include a bookable flag, allowing services to be marked for scheduling.
- Created migration to add bookable column to service_items table.
- Added tests for service-based slot calculations and validation logic.
2026-07-15 23:15:45 +03:30
hamed 6904361e32 feat(appointment): update patient name handling to prioritize existing profile name for new appointments 2026-07-15 22:35:33 +03:30
hamed 13bf9453e5 feat(appointment): ensure existing profile name is used over modal input for patient name 2026-07-15 20:33:15 +03:30
hamed d91867bd63 fix(appointment): resolve issue with reserved slots incorrectly shown as available 2026-07-15 19:13:27 +03:30
hamed de6fe1bd56 feat(appointment): update patient identification to use national code from profile and enhance appointment creation logic 2026-07-15 18:46:56 +03:30
hamed 0dc1ab949a feat(appointment): add Enter key functionality for mobile search in appointment modal 2026-07-15 18:29:59 +03:30
hamed 5d5089244b feat: add mobile-based patient lookup for appointment booking
- Implemented a new endpoint `/api/v1/my/appointment/patient-lookup` to search for patients by mobile number before booking an appointment.
- Updated the `NewAppointmentModal` component to utilize the new patient lookup feature, allowing for direct booking if the patient is found with a national code.
- Enhanced the appointment booking form to handle mobile input normalization and display relevant fields based on the search results.
- Added tests for the new patient lookup functionality, ensuring proper behavior for found and not found cases, as well as validation for mobile input.
- Updated sidebar tests to reflect changes in the sidebar component structure and functionality.
2026-07-15 18:27:29 +03:30
hamed f378bf58e6 Add AST JSON representation for BookingScopeTest.php with nodes and edges 2026-07-15 18:14:59 +03:30
hamedandClaude Opus 4.8 5548d79d4c feat(appointment): identify admin-booked patient by national code
Admin-side booking (POST /api/v1/my/appointment and
/api/v1/admin/appointment) resolved the patient User by mobile only, so
one person booked under two mobiles produced two User rows — and two
case-files, since PatientRecord is keyed on user_id. National code is the
real unique identity (User.national_code is already unique); a person may
have several mobiles.

Booking now requires + validates patient_national_code and resolves the
patient national-code-first (then mobile) via a shared PatientResolver, so
the case-file stays unique per national code even across mobiles. Reusing a
mobile already bound to a different national code returns 422
ERR_PROFILE_MOBILE_TAKEN. The admin create form and NewAppointmentDrawer
gain a national-code field and send it; both had a dead patient-picker URL
(/api/v1/patient) fixed to the real /api/v1/patients, whose payload already
carries user_national_code for autofill.

Docs (appointment.md, admin.md) and tests updated; new
AppointmentNationalCodeTest covers success, single-file reuse, missing,
invalid, and identity-conflict cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 18:11:40 +03:30
hamed 141ce478a2 chore: update graphify graph 2026-07-15 17:45:07 +03:30
hamedandClaude Opus 4.8 1aa6794786 feat: port tauri header top-menu to admin topbar
Rebuild admin Topbar to match clinic-pro-tauri header:
- Icon order: theme -> settings -> bell (was theme -> bell -> settings)
- Settings gear now navigates to the role-based settings page
  instead of opening the personalization panel
- Search placeholder changed to «جستجو», dropped the ⌘K hint
- Add ProfileMenu: avatar + user name + context/role subtitle + caret,
  with a dropdown (profile / payments / settings / personalization / logout).
  Links are role-aware; personalization keeps the existing settings panel.

Frontend-only, no API changes. Adds ProfileMenu.test + Topbar.test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 17:44:47 +03:30
hamed 952fcf3634 style: enhance SettingsLayout and AppointmentSettingsPage for improved layout and spacing 2026-07-15 17:35:24 +03:30
hamed ffc4351038 fix: update PurchaseSubscriptionSidebar and AppointmentSettingsPage for pixel-perfect alignment and color consistency 2026-07-15 17:30:26 +03:30
hamedandClaude Opus 4.8 810293764a chore: update graphify graph
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 17:06:42 +03:30
hamedandClaude Opus 4.8 62e0cdb518 feat(admin): add orange rgb(241,119,50) as an exact brand-color option
Revert the earlier mis-scoped orange on the personalization panel and
instead expose rgb(241,119,50) as a selectable 'رنگ اصلی' swatch. When
picked it overrides --primary/-600/-700/-soft/-soft2/-ring inline with
exact hex, so every var(--primary) consumer across the whole admin
(buttons, active nav, rings) becomes that orange. Non-fixed hues keep
the oklch hue pipeline (inline overrides removed on switch).

- uiStore: BrandHue interface + optional fixed hex; shared applyBrand()
  helper handles fixed vs hue, dark-aware soft tints
- AdminLayout: reuse applyBrand() (no divergence with store)
- Topbar: swatch shows the exact fixed color
- tests: fixed-color apply, dark soft, and override-cleanup on switch

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 17:06:24 +03:30
hamedandClaude Opus 4.8 89ebeb8fce style(admin): orange accent for شخصی‌سازی panel
Apply rgb(241,119,50) exclusively to the personalization (شخصی‌سازی)
settings panel — its heading and active segmented buttons — matching
the product requirement that this section use the dedicated orange
while the rest of the panel keeps tauri's purple.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 16:55:53 +03:30
hamedandClaude Opus 4.8 edf3cea51f chore: update graphify graph
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 16:48:58 +03:30
hamedandClaude Opus 4.8 0a78bf7a6b style(admin): align design tokens to clinic-pro-tauri
Match the admin panel's visual system to the tauri source app:
- neutralize color tokens (border/surface-2/3, text 1-3) from the
  bluish indigo tint to tauri's neutral grays (#efefef/#3b3b3b/#7e7e7e/#a1a1a1)
- add --nav-active-bg (#f8f8ff light) for the sidebar active item,
  matching tauri active-link-side
- enable Vazirmatn ss02 stylistic set on body (tauri typography)
- responsive topbar heights 56/67/79/90 exactly as tauri

Settings sub-sidebar active orange (#f17732 = rgb(241,119,50)) and
ClinicPro branding/section grouping kept per product decision.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 16:48:25 +03:30
hamed 5c15a4dd7f feat(services): add services menu item to sidebar and update related components 2026-07-15 16:35:02 +03:30
hamed 704e69f05f chore: update graphify graph 2026-07-15 16:20:34 +03:30
hamedandClaude Opus 4.8 10d289cfd1 fix(appointments): detail page back/breadcrumb return to the appointment day
AppointmentDetailPage now derives the appointment's local day from slot_start
and points both the «بازگشت» button and the «نوبت‌ها» breadcrumb to
/admin/appointments?date=<that day>, so viewing/acting on an appointment from
any day returns to that day instead of today.

Test: the «نوبت‌ها» breadcrumb links back to the appointment's date.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 16:20:22 +03:30
hamed ab2904b81a chore: update graphify graph 2026-07-15 16:13:41 +03:30
hamedandClaude Opus 4.8 526048fd56 fix(appointments): stay on the same day after edit/create
AppointmentsPage now reads an optional ?date=YYYY-MM-DD query param as its
initial selected date. AppointmentEditPage and AppointmentCreatePage navigate
back to /admin/appointments?date=<the appointment's day> on save (and the edit
page's back link carries the date too), so the user returns to the day they
were viewing instead of today.

Test: AppointmentsPage honors ?date= and fetches that day.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 16:13:32 +03:30
hamed 41e193ab83 chore: update graphify graph 2026-07-15 16:07:15 +03:30
hamedandClaude Opus 4.8 f41852b168 feat(appointments): profile-aware doctor tabs + toolbar to match tauri turns
- Multi-doctor clinic profile (clinic/admin) shows the doctor tabs for
  multi-doctor management; clinic auto-selects the first doctor so the timeline
  loads immediately (as in the reference). Admin keeps the «همه» tab.
- Independent doctor profile (doctor role, incl. clinic-scoped guest) shows no
  tabs and only its own schedule — no clinic/doctor selection.
- Toolbar reordered to match the reference: date + service select
  («سرویس مورد نظر را انتخاب کنید...») + view toggle on the right; filter +
  «افزودن نوبت» on the left. The in-toolbar doctor picker is removed (doctor
  selection is via tabs); the personnel select is replaced by a service filter
  bound to the existing itemUuid filter (client-side, no new endpoint).

Tests: added clinic-profile tests (tabs shown, no «همه», first doctor
auto-selected) and independent-doctor test (no tabs, service filter shown).

No API endpoints changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 16:07:04 +03:30
hamed ef6017e688 chore: update graphify graph 2026-07-15 15:46:00 +03:30
hamedandClaude Opus 4.8 48c70e89f2 fix(appointments): center timeline card and match tauri turns layout
- Center the whole page in a max-width container; move the toolbar above the
  card and make the doctor tabs the card header (as in the tauri turns design).
- Rebuild the timeline card to match the reference: inner start/end ring-dot
  time markers, patient name / phone / «سرویس» lines, and status pill + عملیات
  on the card's left; outer marker rail with time on the right.
- Timeline rows are width-capped and centered on the page.
- Empty slots render the light-blue «افزودن نوبت +» card with a «نوبت جدید» pill.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 15:45:51 +03:30
hamed bf9fce4e05 chore: update graphify graph 2026-07-15 15:33:24 +03:30
hamedandClaude Opus 4.8 a6ae6220cb feat: redesign appointments (نوبت‌ها) admin UI to match tauri turns + expandable sidebar
Rebuild the /admin/appointments page visual layer to match the tauri
clinic-pro-tauri "turns" design while keeping all existing data wiring and
backend endpoints unchanged (add/edit/move/transfer-reserve/replace already
supported via PATCH /api/v1/appointment/{uuid} and POST /api/v1/my/appointment).

Frontend (assets/admin):
- Sidebar: نوبت‌ها becomes an expandable parent with sub-items
  «نوبت های تایید شده» (/admin/appointments) and «افزودن نوبت»
  (/admin/appointments/new); auto-expands on active child. Applied to
  admin/clinic/doctor/secretary roles. Adds nav-subitem styling.
- New presentational components under components/appointments/: tauri status
  palette (turnStatus), TurnsStatInfo, TurnsViewToggle (sliding), DoctorTabs
  (underline), TurnsTimeline (marker rail + status cards, empty slot → افزودن
  نوبت), TurnsTable.
- AppointmentsPage recomposed with the new components (stats bar, doctor tabs,
  view toggle, timeline/table), preserving queries, filters, pagination,
  quick-book modal and the row actions menu.
- AppointmentCreatePage: full-page create form (CreateTurn layout) at
  /admin/appointments/new, reusing POST /api/v1/my|admin/appointment.

Tests: TurnsStatInfo, TurnsTimeline, Sidebar (expandable), AppointmentsPage,
AppointmentCreatePage. Backend move/reserve/replace verified green via existing
tests/Appointment/AppointmentUpdateTest + AppointmentWorkflowFieldsTest.

No API endpoints changed → no docs/api change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 15:33:03 +03:30
hamed 9f75aeedf5 feat: redesign insurance pricing page with tabbed navigation for basic and supplementary insurance, expandable rows for contract details, and move free visit price card to appointment settings 2026-07-15 14:55:16 +03:30
hamed 3e5dee0ad5 feat: Implement category and unit selection for inventory items
- Added a new 'category' field to the InventoryItem entity and updated the database schema.
- Replaced free-text input for 'unit' and 'category' with select dropdowns in the AddItemModal.
- Introduced a new API endpoint to fetch metadata for units and categories.
- Updated inventory filtering logic to use the new 'category' field instead of 'consumable'.
- Enhanced validation for item creation and updates to ensure valid unit and category values.
- Updated tests to cover new functionality and ensure proper validation.
2026-07-15 14:32:29 +03:30
hamedandClaude Opus 4.8 defa0db023 feat: group thousands in inventory item price input
Show the قیمت (تومان) field with thousand separators as the user types
(e.g. 1200000 → 1,200,000). Stored value stays digit-only, so the
Toman→Rial conversion on submit is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 14:09:49 +03:30
hamedandClaude Opus 4.8 7ea2cb4ab2 fix: render inventory actions menu in a portal so it is not clipped
The «عملیات» dropdown was absolutely positioned inside the table container,
which has overflow:hidden for its rounded corners, so the menu was clipped
below the table. Render it through a Portal with fixed positioning computed
from the trigger's rect (RTL-aligned to the trigger's right edge), tracking
scroll/resize while open.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 14:07:47 +03:30
hamed 7819068e82 chore: update graphify graph 2026-07-15 13:48:47 +03:30
hamedandClaude Opus 4.8 519bc8d7f6 feat: port inventory (انبارداری) page from tauri to admin dashboard
Add a per-tenant (doctor/clinic) Inventory domain and admin page, ported
from clinic-pro-tauri /inventory (which was static/mock) into a real feature.

Backend (src/Inventory/):
- Entities InventoryItem, InventoryPackage, InventoryPackageItem, scoped via
  entity_type/entity_id like TenantTag. Item status is derived, package total
  and availability derived at read time.
- InventoryService (stats, package assembly, availability), thin
  InventoryController with CRUD for items and packages + categories endpoint.
- Migration + docs/api/inventory.md + functional tests (10 tests, 42 assertions).

Frontend (assets/admin/):
- InventoryPage with two tabs (کالاهای مصرفی / پکیج), stat cards, items table
  (desktop + mobile cards), packages accordion, add/edit item and package
  modals, search + category filter — pixel-matched to the tauri source.
- useInventory hook (TanStack Query), route + sidebar link for doctor/clinic.
- Vitest coverage (real data, empty state, modal, packages tab).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 13:48:29 +03:30
hamed f1e9129a2c Add AST JSON representation for insurance API documentation
- Created a new JSON file containing nodes and edges representing the structure of the insurance API documentation.
- The nodes include various API endpoints, their labels, file types, and source locations.
- The edges define relationships between the nodes, indicating how they are connected within the documentation.
2026-07-15 13:25:13 +03:30
hamedandClaude Opus 4.8 d7cb9ea5a3 feat(insurance): redesign insurance management page to match Figma
Rebuild the /admin/insurance-pricing contracts UI to the Figma "مدیریت بیمه"
design and inject the coverage/franchise/ceiling fields the design omitted.

Backend:
- Add contract-level `kind` column to TenantInsurance (basic|supplementary),
  defaulting to the catalog type; migration Version20260715093358.
- POST/PATCH /billing/tenant-insurances now accept effective_from,
  effective_to, kind; PATCH also toggles is_active without clobbering the
  user-set effective_to (unlike DELETE/deactivate).
- List returns the latest version of every insurance (active + inactive) via
  TenantInsuranceRepository::findLatestByTenant, for the فعال/غیرفعال toggle.

Frontend:
- New InsuranceModal (ui/Modal + SearchableSelect + PersianDateInput) with the
  seven fields; submit "ثبت بیمه".
- TenantInsuranceContracts rebuilt: header + search box, desktop table
  (ردیف/نام/کد/نوع/وضعیت/عملیات) and mobile cards, status toggle -> PATCH.
- utils: isoToUnix/unixToIso helpers for contract dates.

Tests: TenantInsuranceContractApiTest (create/edit/toggle/list, 5 cases),
InsuranceModal + TenantInsuranceContracts vitest suites, docs/api updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 13:23:38 +03:30
hamed e94f832c8a fix: adjust styles for PermissionAccordions component for better usability 2026-07-15 12:47:42 +03:30
hamed 3634d37cb6 chore: update graphify graph 2026-07-15 12:28:52 +03:30
hamed 28032892da fix: render secretary modal via portal Modal component (centered card)
The custom inline overlay was mounted inside the SettingsLayout grid, so the
fixed positioning resolved against a transformed ancestor and the modal
rendered top-aligned and full-width. Use the shared Modal (portal to body)
for a correctly centered card; keep the tauri-styled form body + permission
accordions as its children.
2026-07-15 12:28:18 +03:30
hamed f2029a5ad4 chore: update graphify graph 2026-07-15 12:23:46 +03:30
hamedandClaude Opus 4.8 89e23a2c0d feat: port secretaries tab from tauri to admin my-secretaries page
- Redesign MySecretariesPage pixel-perfect to clinic-pro-tauri (active/previous
  tabs, desktop table, mobile cards, add/edit/view modal with permission
  accordions, deactivate confirm)
- Permission sections based on existing admin pages (appointments, patients,
  payments, insurances, addresses, clinic_info)
- Extend DoctorSecretary with national_code + address columns (+migration);
  wire create/update in SecretaryController; add patients/payments to
  DEFAULT_PERMISSIONS
- Extend Secretary/SecretaryPermissions types; update admin SecretariesPage
- Backend + frontend tests; update docs/api/secretary.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 12:23:17 +03:30
hamed 57c5383baf chore: update graphify graph 2026-07-15 11:51:46 +03:30
hamedandClaude Opus 4.8 850b2832ff refactor: move secretary and staff management from main nav to settings menu
Remove پرسنل (/admin/staff) and منشی ها (/admin/my-secretaries) from the
clinic and doctor main sidebars; surface them under the settings menu instead
(PurchaseSubscriptionSidebar + SETTINGS_MENU). Wrap StaffPage in SettingsLayout
so it renders inside the settings shell like MySecretariesPage already does.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 11:51:31 +03:30
hamedandClaude Opus 4.8 cf02fdd433 fix: add card padding on payment management page so content isn't flush to edges
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 11:44:00 +03:30
hamed d89068e668 chore: update graphify graph 2026-07-15 11:39:57 +03:30
hamedandClaude Opus 4.8 b459d082a4 feat: port payment management tab from tauri to admin dashboard
Add per-clinic payment methods (bank accounts + POS/card-reader devices)
under the "مدیریت پرداخت" settings tab at /admin/my-financial, ported from
clinic-pro-tauri's mock-only PaymentManagement tab into a real persisted
feature. These records are referenceable (by uuid) from patient invoices to
record which method a service payment was made with.

Backend (new src/PaymentMethod domain):
- BankAccount + Pos entities, repositories, PaymentMethodService (validation,
  ownership scoping, create/update/toggle logic).
- Thin PaymentMethodController exposing /api/v1/my/payment-methods/{bank-accounts,pos}
  (GET/POST/PUT + PATCH .../status), guarded to clinic/doctor/secretary/admin.
- Migration for bank_accounts + pos_devices tables.
- Functional tests (success + validation/404/403 + empty boundaries).
- docs/api/payment-method.md.

Frontend:
- Replace MyFinancialPage content with the payment-management UI (two tabs,
  tables, add/edit modals, status toggle) using the admin design system.
- usePaymentMethods hook (TanStack Query) + presentational components.
- Update page test to cover tabs, data, empty state and the add modal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 11:39:32 +03:30
hamed cac2e8b46a chore: update graphify graph 2026-07-15 11:17:00 +03:30
hamedandClaude Opus 4.8 f0b7a51b8f fix: make patient detail page full-width to match tauri FilesServices
Removed the maxWidth:1060 centered wrapper on PatientDetailPage that
boxed the page; tauri's FilesServices renders full-width in a plain Box.
Added a regression test asserting the root wrapper has no max-width cap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 11:16:40 +03:30
hamedandClaude Opus 4.8 0e057e0c66 chore: update graphify graph
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 10:36:54 +03:30