- Deleted Date.js and FilterDate.js components as they are no longer needed.
- Removed SearchDoctor.js component which was responsible for searching doctors.
- Cleaned up the Head component by removing references to the deleted Date and SearchDoctor components.
- Removed TurnsPage component and its associated List component, which were not utilized.
- Deleted Cards and Table components from the list directory as they were not in use.
- Removed user account related components including Tab, Head, and Form components.
- Cleaned up bank account components including List, Item, and modal components.
- Removed representation adapters and related functions that were not in use.
fix(progress): enhance accessibility by adding aria-label to LinearProgress component
fix(share): add aria-label for better accessibility in Share button
fix(title): change h3 to h2 for semantic correctness and add aria-labels for links
fix(qrimg): add alt text for QR code image for improved accessibility
fix(buttonmenu): add aria-label for mobile menu button to enhance accessibility
feat(robots): update disallow rules to include '/panel'
feat(sitemap): implement separate sitemaps for doctors, clinics, and blogs
feat(icons): add social media icons for doctor profiles
- Added isomorphic-dompurify for improved XSS protection
- Refactored token storage to use in-memory management for access tokens
- Implemented server-side route handlers for OAuth token management
- Introduced security headers in next.config.js
- Removed client-side exposure of client_secret and sensitive tokens
- Updated API interceptors to handle token refresh logic
- Cleaned up cookie management for refresh tokens
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>
- 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>
- 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>
- 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>
- 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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
- 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>
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>
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>