Commit Graph
100 Commits
Author SHA1 Message Date
hamed fdb5866562 feat(clinic): improve image handling and map integration in clinic components 2026-06-18 15:21:19 +03:30
hamed ecb77fcfa8 feat(clinic): enhance clinic details display with improved logo handling and address formatting 2026-06-18 15:03:31 +03:30
hamedandClaude Opus 4.8 344285dce5 feat(specialties): show per-city doctor count on /specialties
Fetch active specialties with number_of_doctors from
GET /api/v1/specialties/doctor-counts (scoped to the current city via
matchedCity.id) instead of the static specialties.json, so each specialty
card shows the real doctor count.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 22:27:39 +03:30
hamedandClaude Opus 4.8 69e591f03e fix(dashboard): appointment detail fields + sidebar hydration
- Appointment detail (DetailLg/DetailSm) read the real response shape:
  date/time from slot_start, specialty from doctor.specialties[0].name,
  phone from address.telephone.
- Sidebar Head reads userInfo (cookie) after mount to avoid an SSR/client
  hydration mismatch on the user's name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:01:43 +03:30
hamedandClaude Opus 4.8 bdf453a3ab feat(dashboard): stepwise Jalali birthday picker + correct send direction
- JalaliDatePicker gains an opt-in `stepwise` mode (year → month → day): the
  year step is a scrollable list from the current Jalali year down to 1332,
  used by the birthday field. Default-off so appointment/panel pickers keep
  the month-grid behavior. Parse incoming Jalali string values safely
  (fixes NaN keys).
- Birthday create path now converts Jalali→Unix on send (changeDateType true),
  matching the update path and the Unix-based backend contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 11:42:45 +03:30
hamedandClaude Opus 4.8 7949da9ba9 fix(appointment): real status filter + required account fields
- My-appointments tabs sent invalid status values (reserved/waiting_for_payment/
  ...) that don't exist in the backend, so every tab but "all" returned empty.
  Map tabs to real statuses (pending/confirmed/completed/cancelled_by_user/
  expired) so booked appointments show up.
- Booking form now validates required account fields before proceeding to
  payment (national_code 10 digits, name, family, gender, basic_insurance),
  in both self and other-person modes, surfacing per-field errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 10:45:41 +03:30
hamedandClaude Opus 4.8 59d29cd7c7 fix(appointment): correct payment flow and account-info prefill
- Booking response is double-nested: read appointment uuid/expires_at from
  res.data.data so the payment countdown and gateway redirect actually fire.
- Payment result page (/payment/[uuid]): unwrap res.data.data, use real
  backend fields (amount_rials, gateway, created_at, type) and statuses
  (pending/success/failed/canceled/refunded); the "pay" button now re-initiates
  via postAppointmentPayment instead of building a URL on the API origin.
- Add /payment/result interstitial that reads payment_uuid from the gateway
  callback and forwards to /payment/[uuid].
- Prefill account info correctly in the booking form: name from profile.label,
  insurances from *_id, gender as string, national_code editable unless approved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 10:06:56 +03:30
hamedandClaude Opus 4.8 7d65239615 feat(doctor): wire rich rating/review UI to multi-dimensional API
Connect the existing doctor-page review UI to the rebuilt backend contract
(see clinicpro feat/rating-multidimensional).

- page.js fetches the rating aggregate alongside comments and passes
  rateAggregate down to the chart (point / satisfaction / 5 dimensions).
- Submit form sends the five dimensions with doctor_uuid; comment/reply
  send {doctor_uuid, comment, parent}; 401/403 ERR_RATING_NOT_ELIGIBLE
  surface friendly guidance.
- Like/dislike call POST /like/{uuid} with value and update from the
  response; replies render nested.
- ModalAnswer gates the submit button on GET /rate/{uuid}/eligibility.
- services/response.js: getRateEligibility, postCommentsLike(uuid, value),
  drop unused patchDoctorRate. Fix hardcoded modal title; empty-state for
  no comments. Remove orphaned AnswerField.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 00:26:20 +03:30
hamedandClaude Opus 4.8 12917cd900 fix(doctor): correct rating/comment API paths to real backend routes
Doctor page logged a 404 on GET /api/v1/clinicpro/rate/{uuid}. The
frontend used a stale Drupal-era `clinicpro/` prefix; the Symfony API
exposes these under /api/v1 directly.

- response.js: rate/comments/like wrappers point to real routes
  (rate/{uuid}, comments/{uuid}, POST rate, POST comment,
  POST like/{commentUuid}); patch maps to POST upsert; writes use
  requireAuth. Add getDoctorComments wrapper.
- doctor page: fetch comments from comments/{doctor.uuid} (was
  clinicpro/comments/{doctor.id}) and unwrap double-nested data.
- ItemUser: postCommentsLike sends commentUuid for the toggle endpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 23:07:20 +03:30
hamedandClaude Opus 4.8 a79a6c0629 fix(dashboard): controlled Switch for disease status
The disease status Switch used defaultChecked, but row.status loads
async and changes via changeData, triggering MUI's uncontrolled→
controlled warning. Drive it with checked from row.status instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 22:22:43 +03:30
hamedandClaude Opus 4.8 e7db7c705b feat(dashboard): loading spinner and success toast on profile save
The ثبت اطلاعات button gave no feedback. Show a spinner while saving
(both POST and PATCH) and a 'اطلاعات با موفقیت ثبت شد' toast on success,
for the info tab and the medical-history sub-tabs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 22:21:09 +03:30
hamedandClaude Opus 4.8 caca3fda97 fix(dashboard): show name from profile label field
The backend stores the first name in the profile's label field, but the
account form binds the نام input to information.name, so a saved name
never displayed on reload. Map label→name when loading the profile (and
drop the raw label) so the field populates; saving still sends name,
which the backend hydrates back into label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 22:17:25 +03:30
hamedandClaude Opus 4.8 21676857b4 fix(dashboard): account selects store option id, not label match
DefaultSelect's onChange passes the whole option object {label,id}, but
the gender/blood_type/marital/education/job handlers compared it as a
string (education/blood via find(g=>g.label===value), others via ===),
so the value never stored — education in particular always saved empty.
Read option?.id uniformly across all five selects.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 22:13:37 +03:30
hamedandClaude Opus 4.8 41f950985b fix(dashboard): guard select .find().id crashes in account form
Clearing the blood type / education / insurance selects made
.find(...).id (and val.id) read .id on undefined, crashing the account
form. Use optional chaining with empty-string/empty-array fallbacks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:53:39 +03:30
hamedandClaude Opus 4.8 95cbee48ab fix(dashboard): empty state for comments and messages tabs
These tabs have no backend endpoint yet (only per-doctor comments and
admin exist; user messages don't), so they read the always-empty
user.comments/user.messages. Guard against null and show a clear empty
state instead of a blank list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:49:25 +03:30
hamedandClaude Opus 4.8 c80f002670 fix(dashboard): transactions tab uses real payment fields + empty state
The transactions list/card read mock fields (appointment_details,
row.amount, status 'received') and iterated user.turns.done. Pass the
real payments array and read order_id/type/created_at/amount_rials/status
from Payment.toArray(); map status to Persian labels, show rials→toman,
and render an empty state when there are no transactions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:48:06 +03:30
hamedandClaude Opus 4.8 8a87d9cf92 fix(dashboard): turns tab uses real appointment fields + empty state
The turns list/card read start_time, slot.time and doctor.specialty,
none of which exist on Appointment.toArray() (slot_start, doctor.name,
status). Use slot_start for the Jalali date/time, replace the specialty
column with a Persian status label, and show an empty state when there
are no appointments.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:39:12 +03:30
hamedandClaude Opus 4.8 224c51069c fix(dashboard): map insurance and medical history correctly in account tab
The account tab read basic_insurance.id (object) but the profile returns
basic_insurance_id (number), yielding [NaN], and never loaded the medical
history (other). Map basic_insurance_id/supplementary_insurance_id and
merge profile.other on load, and keep the profile uuid even for an empty
profile so PATCH saves work. Verified round-trip (name→label, insurance,
other) against the live API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:36:34 +03:30
hamedandClaude Opus 4.8 0a95e99efa fix(dashboard): wire turns/transactions to real endpoints + fix uuid cookie
- Login now overwrites the uuid cookie with the real user uuid (was the
  OTP uuid), so server-side profile/dashboard fetches resolve.
- getMyAppointments → /api/v1/appointments/user (patient's own bookings;
  /my/appointments is role-scoped and empty for plain users), read from
  the double-nested data.data.
- getMyPayments → /api/v1/my/payments (new endpoint), read paginated
  data + meta.totalPages.
- Drop the userId path param (both endpoints derive the user from token).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:27:18 +03:30
hamedandClaude Opus 4.8 cec6b51f23 fix(dashboard): fetch profile by real user uuid, not OTP uuid
app/dashboard/page.js fetched the profile with the standalone uuid cookie,
which still holds the OTP uuid and 404s. Read the user uuid from the
userInfo cookie (falling back to the uuid cookie); the backend resolves it
and lazy-creates the profile. Also fix buildPatientUser to read the
double-nested response (data.data) and the profile's label field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:17:50 +03:30
hamedandClaude Opus 4.8 96b1684b82 fix(dashboard): guard null userInfo in Head to stop 500 crash
getParsedUserInfo() can return null (cookie missing/unparseable), so
reading userInfo.realName crashed the dashboard with a 500. Default to
an empty object and fall back to the user prop's name or 'کاربر'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:15:25 +03:30
hamedandClaude Opus 4.8 fbb2279b49 fix(user-profile): consume profile from double-nested 200 response
With the backend now returning 200 (lazy-created profile) instead of
404, align the consumers: the profile lives at res.data.data (the
endpoint double-nests), so the booking detail and dashboard read that
instead of res.data / the raw envelope. Drop the obsolete 404 special
handling (empty editable form now comes from the 200 payload), seed the
dashboard empty state when the profile has no real data yet, and make
the profile POST fall back to PATCH on 409 (already lazy-created).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:06:38 +03:30
hamedandClaude Opus 4.8 83b2ec21b7 fix(header): detect login state live from client cookie
The header decided between profile and login button only from the
server-passed logged prop (read once via cookies() in StLayout), so a
user who logged in client-side still saw ورود | ثبت نام until a hard
reload. Seed isLogged from the server prop (correct first paint, no
hydration mismatch) then sync it from the access_token cookie on mount
and on every route change, so login/logout reflect immediately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 18:41:58 +03:30
hamedandClaude Opus 4.8 d114730768 feat(appointment): redesign payment step with test-mode and real amount
Rebuild the payment screen as a clear confirm-and-pay card: appointment
summary (doctor, patient, Jalali date/time), a prominent amount row
(15,000 تومان from the backend's 150,000 rials), and a countdown with a
progress bar tied to the booking's real expires_at. Fetch
/api/v1/payment/config: in test mode show a 'درگاه آزمایشی' notice and a
'پرداخت آزمایشی' button (gateway select hidden, since the backend forces
MockGateway); otherwise show the bank gateway select. Expired state
offers re-selecting a time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 18:36:55 +03:30
hamedandClaude Opus 4.8 9912ae06ca feat(api): surface backend error messages globally via toast
Show the backend's Persian error (errors[0].message, e.g. rate-limit
'درخواست‌های زیاد') as a toast for any failed request.* call, from the
axios response interceptor — so failures are no longer silent. 401 still
logs out/redirects without a toast; callers can opt out with
config.skipErrorToast. Drop now-redundant per-caller alerts/toasts in
the booking submit, payment, and OTP userinfo paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 18:25:11 +03:30
hamedandClaude Opus 4.8 08f5829a22 fix(auth): complete login by reading userinfo from response envelope
oauth/userinfo returns { success, data: {...} }, so after the interceptor
unwraps once the user lives at res.data, not res. getInfo checked
res.uuid (undefined), so it never set the userInfo cookie or redirected —
the /login page just sat there after entering the OTP. Read res.data,
store the user object (with a username alias for mobile_number so the
appointment flow keeps working), redirect via location.href, and show a
toast instead of silently staying when userinfo fails.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 18:16:36 +03:30
hamedandClaude Opus 4.8 eb3cb6ca10 feat(appointment): payment timer from real lock + status-driven payment UX
Drive the payment countdown from the booking's expires_at (15-min lock)
instead of a fake local 10-min timer; when it hits zero, show an expiry
notice and an 'choose time again' button back to slot selection. Show the
booked time (Jalali) and doctor on the payment step, and replace the
fabricated success amount with a confirmation/SMS note.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 18:09:33 +03:30
hamedandClaude Opus 4.8 08107d6ef2 feat(appointment): real for-another-patient form and booking payload
Replace the mock for-another button with a real toggle: switching keeps
the user's own data, clears the form to editable patient fields (phone
becomes an input, adds علت مراجعه), and can switch back. SubmitData now
sends for_self plus patient_* only when booking for someone else, skips
the self-profile PATCH/POST in that case, stores the booking expires_at,
and surfaces a clearer 409 message. Thread appointmentExpiresAt through
the wizard to the payment step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 18:07:10 +03:30
hamedandClaude Opus 4.8 969e915815 fix(appointment): extract insurance list from double-nested response
GET /api/v1/insurances returns success(['data' => items]) → the body is
{ data: { data: [...] } }, so after the interceptor unwraps once the
array lives at res.data.data, not res.data. The callers set the list to
the wrapper object, so insurance.find threw 'not a function'. Read
res.data.data and guard with Array.isArray in both the booking detail
form and the dashboard insurance loader.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:54:11 +03:30
hamedandClaude Opus 4.8 e820cc88ee fix(appointment): client guard for slots that pass while page is open
The backend already returns is_available:false for past slots, but a
slot can lapse after the list is loaded. Disable any slot whose start
(unix seconds) is before now in the time grid, so a just-passed slot
can't be clicked. The grid disabling makes a SendAppo-level guard
redundant — a past slot can no longer be selected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:51:30 +03:30
hamedandClaude Opus 4.8 da3f20e07d fix(appointment): stop insurance select crash and use current endpoint
DefaultSelect passed options={undefined} to MUI Autocomplete while the
insurance lists were still loading (or failed), throwing 'Cannot read
properties of undefined (reading length)'. Default options to [].

The old categorys/insurance_type + supplementary_insurance routes were
removed server-side (ERR_MOVED), so the lists never loaded. Point
getInsuranceType/getSupplementaryInsurance at the current
/api/v1/insurances?type=basic|supplementary (authed; the booking detail
step and dashboard are both logged-in), returning a flat data array.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:41:17 +03:30
hamedandClaude Opus 4.8 65b3f56530 fix(auth): surface real OTP error on verification step
The booking login step showed only a generic error when /api/auth/token
returned 400, so an invalid or expired OTP looked like a broken page.
The backend returns the reason (ERR_AUTH_002 invalid / ERR_AUTH_003
expired) in errors[].message, forwarded by the route; show it via toast.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:37:50 +03:30
hamedandClaude Opus 4.8 232e7eaeb2 feat(appointment): grey out unavailable days on the booking calendar
DatePicker now loads month-availability for the two displayed Jalali
months (mapped to the Gregorian months they span, fetched once and
cached per month) and disables any day in disabled_dates plus past
days. Auto-select skips disabled days. When the doctor has online
booking turned off, show a notice instead of the calendar. doctorUuid
comes from the route params.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:31:47 +03:30
hamedandClaude Opus 4.8 96f4126c0b feat(appointment): add getMonthAvailability request wrapper
Public wrapper for GET /api/v1/appointment-settings/month-availability
/{doctor_uuid}?year=&month= so the calendar can learn which days are
bookable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:29:31 +03:30
hamedandClaude Opus 4.8 779113bb19 fix(appointment): order calendar months RTL (خرداد right, تیر left)
The two months rendered reversed (current month on the left). Pin the
calendar row to dir=rtl and render the base month first so the current
month sits on the right and the next month on the left, matching the
design. Pin each month header to dir=ltr so the nav arrows stay on the
expected outer edges regardless of the RTL flip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:05:56 +03:30
hamedandClaude Opus 4.8 cf705a894e feat(appointment): inline dual-month Jalali calendar for day selection
The day picker used a Popover-based JalaliDatePicker that only showed two
empty text inputs on the booking page — the calendar was hidden until you
clicked the input, so it never matched the design. Replace it with an
always-visible inline two-month calendar (InlineJalaliMonth) rendered side
by side: current month on the right, next on the left (RTL), weekday
headers, Fridays in red, disabled days greyed, selected day in orange,
shared month navigation on the outer edges. Preserves the existing
contract: setDate(unix timestamp), disabledDates[], auto-select nearest
available day.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:58:23 +03:30
hamedandClaude Opus 4.8 1196aa64c6 fix(appointment): use existing doctor image as fallback
The appointment info/location headers fell back to /default-doctor.jpg,
which does not exist in public/, so the Next image optimizer returned
400 for doctors without a photo. Point the fallback at the existing
/assets/images/doctor.png (same default used on the doctor page).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:49:45 +03:30
hamedandClaude Opus 4.8 81121ad7d7 fix(appointment): convert picker timestamp to date and fix summary panel
Follow-ups found while sweeping for stale shapes:
- The date picker emits a unix timestamp, but appointment-slots needs
  Y-m-d; convert with moment before calling (slots never loaded before).
- Appointment summary (information/Detail.js) used the auth-required
  getDoctorAddress and selectedSlot.time; derive the address from the
  loaded doctor.address by location_id and use selectedSlot.start_time.
- SendAppo: drop the dead postAppointment block, unused useParams/loading,
  and a duplicate disabled prop on the button.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:47:21 +03:30
hamedandClaude Opus 4.8 61c21136d2 fix(appointment): read user profile from response envelope
getUserProfile returns { success, data } (interceptor unwraps once), so
the profile fields live under res.data, not res directly — the form was
always populated empty. Extract a buildProfileData helper and use it in
both the mount and step-3 effects, removing the duplicated mapping.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:44:12 +03:30
hamedandClaude Opus 4.8 ba32cd4192 fix(appointment): initiate payment against real gateway endpoint
POST /api/v1/payment/appointment expects { appointment_uuid, gateway,
frontend_address } and returns data.redirect_url. Send that body, redirect
to the gateway URL the backend returns (instead of hand-building one),
align the bank options with the real mellat/sep gateways, and remove the
hard-coded 10,000 toman amount (no real price available at this step).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:42:35 +03:30
hamedandClaude Opus 4.8 7a8700b09b fix(appointment): book with real payload and handle slot conflict
POST /api/v1/appointment expects { doctor_uuid, slot_start, slot_end,
note } with unix timestamps, and returns the appointment uuid at
data.uuid (not data.id). Send the right body, read the uuid, and on a
409 (slot already booked) alert the user and return to slot selection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:41:22 +03:30
hamedandClaude Opus 4.8 dcfdedd93c fix(appointment): render real slot structure in time picker
The slots API returns data.sessions[].slots[] with start_time (HH:MM),
is_available, and start/end unix timestamps — not the morning/evening +
time/status shape the UI assumed. Add lib/appointmentSlots.js to flatten
sessions into morning/evening by start_time, fetch with doctor.uuid, and
read item.start_time / item.is_available in the slot grid. Derive the
clinic address from the already-loaded doctor.address by location_id
instead of a separate auth-required call.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:40:21 +03:30
hamedandClaude Opus 4.8 0e112d2299 fix(appointment): unwrap doctor response and drop dead not-available call
The doctor endpoint is triple-nested, so doctorRes.data left doctor.id
undefined and the booking page received a broken doctor object. Extract
with data?.data?.data and remove the disabledDates fetch to the
nonexistent /appointment/not-available route (404); pass [] so the date
picker enables all dates and lets the slots response gate availability.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:37:47 +03:30
hamedandClaude Opus 4.8 811882ea05 fix(appointment): align request layer with real backend contract
- getAppointmentSlots uses doctor_uuid + date (was doctor_id, which the
  backend rejects with دکتر یافت نشد).
- postAppointmentPayment posts to /api/v1/payment/appointment (was the
  nonexistent /api/v1/payment).
- Remove getAppointmentNotAvailable: the not-available route does not
  exist (404); disabled dates come from the slots response.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:35:43 +03:30
hamedandClaude Opus 4.8 e13d1c2eeb fix(location): correct directions deep links
The routing modal shipped broken deep links: snapp.ir/route and
tapsi.ir/route paths don't exist (404), and balad used the wrong path
and params. Keep only apps with verified destination deep links and
fix their formats:

- Remove Snapp and Tapsi (no valid web destination route).
- Balad: balad.ir/location?latitude=&longitude= (was /map?lat=&lng=).
- Google Maps and Waze kept (already correct).
- Guard data.map destructuring against null.
- Dashboard turn detail: use maps/dir directions URL instead of a
  plain q= pin to match the مسیریابی label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:26:10 +03:30
hamedandClaude Opus 4.8 365892a0f1 fix(doctor): render location map reliably when accordion expands
The map iframe lived inside a collapsed (max-h-0, overflow-hidden)
accordion with loading=lazy, so it often never loaded after expanding.
Mount the iframe only when the location item is open so it loads fresh,
and raise the open clamp from max-h-screen to max-h-[800px] so the map
isn't clipped on shorter viewports.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:21:07 +03:30
hamedandClaude Opus 4.8 ff54daf1ae fix(doctor): unwrap double-nested API response and guard empty sections
The GET /api/v1/doctor/{uuid} response is double-nested
({ success, data: { data: {...} } }), but the page only unwrapped one
level, leaving every field (name, specialties, expertise, address)
undefined — so خدمات / موقعیت مکانی / نظرات rendered empty or broken.

- Extract the doctor object with res.data?.data?.data in both
  generateMetadata and the page.
- Hide the خدمات block when expertise is empty (no fabricated data).
- Render the location map iframe and routing buttons only when the
  address has real latitude/longitude (was building q=null,null).
- Fix the comments list rendering a stray 0 on empty arrays.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:18:06 +03:30
hamedandClaude Opus 4.8 0a48c854cb chore(data): remove unused mock json after API wiring
Delete data/information.json, data/userData.json, data/bank.json — the
panel and patient dashboard now read real data from the API, and no
render path references these files anymore. Verified via grep + build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 13:47:19 +03:30
hamed 4374ed5043 feat(panel): connect representative panel and user dashboard to real API, removing mock data 2026-06-15 09:12:51 +03:30
hamedandClaude Opus 4.8 d9dc976ab3 fix(pagination): read pagination from meta instead of page
backend جدید clinicpro صفحه‌بندی را در پاسخ تحت کلید meta برمی‌گرداند
({totalRecords, totalPages, currentPage})، نه page. به همین دلیل
PaginationContent مقدار totalRecords نمی‌گرفت و count=NaN می‌شد و
صفحه‌بندی مخفی می‌ماند. اصلاح در صفحات /doctors و /clinics.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:56:26 +03:30
hamedandClaude Opus 4.8 f9a4a028eb fix(doctor): guard optional chaining on address array
برخی پزشکان address ندارند؛ data?.address[0] روی آن‌ها کرش می‌کرد
(Cannot read properties of undefined). اصلاح به data?.address?.[0]
در Address و Telefon صفحه پروفایل پزشک.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:52:32 +03:30
hamedandClaude Opus 4.8 dc60b0a4f2 chore(dev): accept ddev self-signed cert in dev for next/image optimizer
بهینه‌ساز تصویر داخلی Next با fetch بومی خودش تصویر را از ddev می‌گیرد و
گواهی self-signed را رد می‌کرد (UNABLE_TO_VERIFY_LEAF_SIGNATURE روی
/_next/image). افزودن NODE_TLS_REJECT_UNAUTHORIZED=0 فقط به اسکریپت dev.
build و start production دست‌نخورده و امن می‌مانند.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:46:43 +03:30
hamedandClaude Opus 4.8 e6570e06f6 fix(images): resolve relative backend image URLs to absolute
API مسیرهای تصویر را نسبی برمی‌گرداند (/uploads/...) که next/image روی
دامنه localhost می‌جست و 404 می‌داد. helper جدید imageUrl مسیرهای نسبی
uploads را با NEXT_PUBLIC_API_URL کامل می‌کند (absolute و asset محلی
دست‌نخورده). اعمال روی لیست/جزئیات پزشک، نوبت، گالری کلینیک، آواتارها.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:44:27 +03:30
hamedandClaude Opus 4.8 05cf5fc585 fix(auth): align token/refresh routes with clinicpro 3-step OTP flow
backend جدید clinicpro جریان سه‌مرحله‌ای دارد:
send-code → verify-code (uuid+code) → oauth/token (uuid).
- token route حالا اول /api/v1/user/verify-code را صدا می‌زند سپس
  /oauth/token با بدنه JSON {grant_type, uuid} (به‌جای form-urlencoded
  با client_id/secret/scope که فقط backend پروداکشن قدیم می‌پذیرفت)
- refresh route به مسیر درست /oauth/token/refresh با بدنه JSON
- تست E2E روی ddev محلی: access_token واقعی صادر شد

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:39:43 +03:30
hamedandClaude Opus 4.8 8255283ec0 fix(ui): remove invalid MUI v5 Button loading prop project-wide
prop loading روی Button فقط در MUI v6+ پشتیبانی می‌شود؛ این پروژه v5 است
و هشدار "Received false for a non-boolean attribute loading" می‌داد.
- دکمه‌های login/verify: disabled + CircularProgress شرطی (بازخورد بصری حفظ شد)
- بقیه دکمه‌ها: loading → disabled (ادغام با disabled موجود در صورت وجود)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:30:55 +03:30
hamedandClaude Opus 4.8 ecc212db86 fix(auth): use SSL-tolerant axios for oauth token/refresh routes
route های token و refresh از fetch بومی Node استفاده می‌کردند که گواهی
self-signed ddev محلی را رد می‌کرد و خطای 500 می‌داد. حالا از axiosInstance
استفاده می‌کنند و خطای واقعی backend را با status درست برمی‌گردانند.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:30:42 +03:30
hamedandClaude Opus 4.8 1d56972b65 fix: use SSL-tolerant axios instance for server-side API calls
صفحات سرور (doctors, doctor/[slug], appointment/[doctorId]) از axios خام
استفاده می‌کردند که گواهی self-signed ddev محلی را رد می‌کرد
(unable to verify the first certificate). حالا از axiosInstance/fetchReq
در lib/req استفاده می‌کنند که در development آن را می‌پذیرد.
افزودن clinic-pro.ddev.site (http/https) به remotePatterns تصاویر.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:21:34 +03:30
hamedandClaude Opus 4.8 f3192945c7 fix(doctors): resolve next/image http host and MUI v5 loading prop
- افزودن الگوی http برای api.clinic-pro.ir به next.config (عکس‌های بیمه
  با http برمی‌گردند و خطای 500 next/image می‌دادند)
- جایگزینی prop loading نامعتبر روی Button با disabled در SendReq/ButtonApply
  (loading فقط در MUI v6+ پشتیبانی می‌شود؛ این پروژه v5 است و lab نصب نیست)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:15:10 +03:30
hamedandClaude Opus 4.8 dc1c6d25be feat(dashboard): connect patient dashboard to real user profile
- buildPatientUser: ساخت آبجکت user از user-profile واقعی با کلیدهای
  مورد انتظار کامپوننت‌ها؛ comments/messages خالی و اعداد هدر صفر
  (بدون داده ساختگی، چون endpoint ندارند)
- app/dashboard/page.js پروفایل را server-side از user-profile/{uuid} می‌گیرد
- حذف import userData.json mock از Content داشبورد
- نوبت/تراکنش/تب اطلاعات از قبل به API واقعی وصل بودند (بدون تغییر)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:10:40 +03:30
hamedandClaude Opus 4.8 5067824f28 feat(panel): connect turns/user-account/add-doctor to real data
- انتقال adapterهای نماینده به lib/representationAdapters (server-safe،
  بدون وابستگی client مثل js-cookie/react-toastify)
- turns: لیست از daily[] داشبورد ماهانه (ستون نام/تخصص خالی، بدون داده ساختگی)
- user-account: حساب بانکی واقعی از bank_account نماینده (map به آرایه تک‌کارته)
- add-doctor: حذف import mock مرده (کامپوننت data مصرف نمی‌کرد)
- رفع dead import اشتباه از turns/page در clinic/doctors که build را می‌شکست

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:06:01 +03:30
hamedandClaude Opus 4.8 1599098b6d feat(panel): connect dashboard page to representation monthly stats
تبدیل صفحه dashboard پنل به Server Component که آمار ماهانه نماینده را
از API می‌گیرد (year/month میلادی جاری) و با adaptRepresentationDashboard
به propهای کامپوننت map می‌کند. حذف داده mock.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:00:16 +03:30
hamedandClaude Opus 4.8 bef36f86ca feat(panel): wire panel header/userDetail to real representation info
افزودن adaptRepresentationInfo که خروجی API نماینده را به propهای
کامپوننت‌های نمایشی map می‌کند و حذف import داده mock از Content پنل.
فیلدهای آماری بدون معادل API خالی می‌مانند (بدون داده ساختگی).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 23:57:48 +03:30
hamedandClaude Opus 4.8 d513d2dd30 feat(panel): add representation dashboard API helpers
افزودن getRepresentationDashboardMonthly و getRepresentationDashboardYearly
به لایه request برای مصرف endpointهای داشبورد نماینده.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 23:54:58 +03:30
hamed 52f6bf6d0f Refactor code structure for improved readability and maintainability 2026-06-14 23:37:53 +03:30
hamedandClaude Sonnet 4.6 59e0a0fe4f fix: resolve critical bugs and security issues across the project
Security:
- Disable SSL verification only in development (lib/req.js)
- Wrap all JSON.parse(cookie) calls in try-catch via safeJsonParse utility
- Sanitize dangerouslySetInnerHTML in blog/clinic with sanitizeHtml utility
- Fix open redirect in payment page — validate URL origin before redirect
- Fix cookie cleanup on 401 — use js-cookie with correct domain scope

Performance:
- Wrap ItemDoctor with React.memo to prevent unnecessary re-renders
- Replace <img> with Next.js <Image> in blog Caption component

Functionality:
- Fix memory leak in Recode.js — store intervals in refs, cleanup on unmount
- Add null guard on retryIcon.current before classList manipulation
- Fix getParsedUserInfo in helper to handle malformed cookie gracefully

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 09:19:20 +03:30
hamedandClaude Sonnet 4.6 1aa9f82d2a fix: resolve critical bugs and security issues across the project
- Fix GPS map links always sending literal "latitude"/"longitude" strings
  instead of actual coordinates in openLocation/Content.js
- Add api.clinic-pro.ir to next.config.js remotePatterns so production
  images load correctly
- Fix appointment page: await params and getStateInfo (Next.js 15 pattern)
- Enable 401 handling in api.js: clear cookies and redirect to /login
- Move OAuth client_secret to server-side API routes (/api/auth/token,
  /api/auth/refresh) so it is never bundled into client-side JavaScript
- Update SendReq, SubmitData, ButtonSendData to call API routes instead
  of directly sending client_secret from the browser
- Update docker-compose.yml to use server-only CLIENT_SECRET env var
- Remove debug console.log from clinic doctors list component

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 22:18:11 +03:30
hamedandClaude Sonnet 4.6 ec536bfc32 fix: resolve sitemap build error caused by invalid Date values
- Replace new Date(b.created) with toSafeDate() helper to guard against
  invalid date strings from blog API responses
- Use a single NOW constant instead of new Date() per entry to avoid
  serialization issues during static generation
- Remove unused imports (cityData, DOMAIN_CONFIG, etc.)
- Add CLAUDE.md with project architecture and development guidance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:47:42 +03:30
hamed 35408b059a seo check 2026-06-05 21:28:12 +03:30
hamed 3c9013ff0c check lighthous 2026-06-05 21:05:07 +03:30
hamed cf703f131a fix: update environment variables in docker-compose.yml to use default values 2025-12-23 11:27:59 +03:30
hamed 5d8c7cef1d fix: update NEXT_PUBLIC_API_URL to use default value if not set 2025-12-23 10:09:57 +03:30
hamed 54ae8c3a68 chore: update package.json to add tailwindcss and postcss dependencies 2025-12-17 17:59:20 +03:30
hamed db2f9aef60 Replace jalaali-react-date-picker with custom MUI-based Jalali date picker - fixes all 10 security vulnerabilities 2025-12-17 10:09:37 +03:30
hamed e5e6f33ae4 Update packages: Next.js 15.5.9, Tailwind 3.4.19 2025-12-17 09:58:14 +03:30
hamed a844ac20e7 Remove pull_policy - not supported in build section 2025-12-10 15:24:53 +03:30
hamed defaae05fe refactor: simplify Dockerfile for Next.js 14 and optimize build stages 2025-12-10 15:19:06 +03:30
hamed 3daa4cf333 refactor: update Dockerfile and docker-compose.yml for Next.js 15 compatibility and improved production setup 2025-12-10 15:16:28 +03:30
hamed 5c52dcda76 refactor: update Dockerfile and docker-compose.yml for Next.js 15 compatibility and improved production setup 2025-12-10 14:50:41 +03:30
hamed 8e5e8e1e9d refactor: update Dockerfile and docker-compose.yml for Next.js 15 optimization and standalone output 2025-12-10 14:44:41 +03:30
hamed 6f0c29d700 chore: update dependencies and add .dockerignore file
- Updated MUI packages to version 5.x and x-charts/x-date-pickers to 7.x
- Downgraded React and React-DOM to version 18.3.1
- Added .dockerignore to exclude unnecessary files from Docker context
2025-12-10 14:06:19 +03:30
hamed a8d4d5c090 refactor: update Dockerfile for Next.js 16 compatibility and optimize build process 2025-12-10 11:00:57 +03:30
hamed 76e96f1724 refactor: update Dockerfile and docker-compose.yml for Next.js 16 optimization and improved build process 2025-12-10 11:00:38 +03:30
hamed a0b946c39b chore: update dependencies to latest versions
- upgraded @maptiler/sdk from 2.5.1 to 3.9.0
- upgraded @mui/styled-engine-sc from 6.4.9 to 7.3.6
- upgraded @mui/x-charts from 7.29.1 to 8.21.0
- upgraded @mui/x-date-pickers from 7.29.4 to 8.21.0
- upgraded date-fns from 3.6.0 to 4.1.0
- upgraded npm from 10.9.4 to 11.7.0
- upgraded react and react-dom from 18.3.1 to 19.2.1
- upgraded swiper from 11.2.10 to 12.0.3
- upgraded cross-env from 7.0.3 to 10.1.0
2025-12-10 10:04:04 +03:30
hamed f5530d8c73 refactor: update SearchBar to use async getStateInfo for improved state handling 2025-12-10 09:55:09 +03:30
hamed 23f20626a6 refactor: improve key assignment in FrequentSearches and update TextHeader to use async getStateInfo 2025-12-10 09:53:51 +03:30
hamed 1df39909ea chore: add .npmrc file to enable legacy peer dependencies 2025-12-04 05:29:47 +03:30
hamed 40df2db108 chore: update dependencies in package.json
- Bumped versions for several packages including:
  - @emotion/styled from ^11.14.0 to ^11.14.1
  - @maptiler/sdk from ^2.4.0 to ^2.5.1
  - @mui/icons-material from ^7.1.0 to ^7.3.6
  - @mui/material from ^7.1.0 to ^7.3.6
  - @mui/styled-engine-sc from ^6.0.0-alpha.18 to ^6.4.9
  - @mui/x-charts from ^7.16.0 to ^7.29.1
  - @mui/x-date-pickers from ^7.17.0 to ^7.29.4
  - @next/third-parties from ^15.1.0 to ^15.5.7
  - axios from ^1.7.7 to ^1.13.2
  - dayjs from ^1.11.13 to ^1.11.19
  - jspdf from ^3.0.1 to ^3.0.4
  - next from ^14.2.20 to ^15.5.7
  - next-themes from ^0.3.0 to ^0.4.6
  - npm from ^10.8.2 to ^10.9.4
  - react from ^18.0.0 to ^18.3.1
  - react-dom from ^18 to ^18.3.1
  - react-easy-crop from ^5.1.0 to ^5.5.6
  - react-toastify from ^10.0.6 to ^11.0.5
  - sharp from ^0.34.1 to ^0.34.5
  - styled-components from ^6.1.11 to ^6.1.19
  - stylis from ^4.3.4 to ^4.3.6
  - swiper from ^11.1.9 to ^11.2.10
  - postcss from ^8 to ^8.5.6
  - prettier from ^3.5.3 to ^3.7.4
  - tailwindcss from ^3.4.1 to ^3.4.18
2025-12-04 05:26:37 +03:30
hamed 3ca69dcd0f refactor: enhance representation info fetching and pass it to relevant components 2025-12-02 15:38:42 +03:30
hamed e6cb27a714 refactor: remove unused frontend_address from payment payload in Paying component 2025-12-02 15:03:27 +03:30
hamed 95e55776c3 refactor: enhance dark mode support across components and improve user role handling in DetailProfile 2025-11-19 12:22:14 +03:30
hamed 18b03ca781 refactor: enhance user role handling in List and ability definitions 2025-11-19 11:48:40 +03:30
hamed e26d342c90 refactor: enhance blog functionality with related blogs fetching, improved loading states, and tag filtering 2025-11-19 11:32:09 +03:30
hamed 235a64c378 refactor: implement blog fetching and pagination in BlogsPage component 2025-11-19 10:55:26 +03:30
hamed 4651ae534d refactor: implement PDF download functionality for appointment details in DetailLg and DetailSm components 2025-11-19 10:34:02 +03:30
hamed aef10e7764 refactor: update map button functionality to use latitude and longitude for Google Maps links 2025-11-19 10:24:07 +03:30
hamed e7cff90516 refactor: integrate IsTurnsDetails component for enhanced appointment display 2025-11-19 09:42:59 +03:30
hamed b2f968480c refactor: update appointment handling to improve data flow and display, including status management and detail views 2025-11-19 09:16:41 +03:30
hamed e7c8501680 refactor: enhance transaction and appointment handling with pagination, status filtering, and improved data display 2025-11-18 22:21:47 +03:30
hamed 430e0b3b11 refactor: enhance payment handling by adding frontend_address to payment payload and implement PaymentDetailsPage component 2025-11-18 21:37:05 +03:30
hamed df54983fa3 refactor: enhance appointment handling by adding appointmentId state and updating payment process 2025-11-18 17:09:37 +03:30