Commit Graph
76 Commits
Author SHA1 Message Date
hamedandClaude Opus 4.8 b37096048c feat(booking): show only locations that can actually be booked that day
The site offered a "personal practice" for a doctor who has no personal address
at all — the schedule existed but its shifts pointed at the clinic's address, so
there was nowhere to go. The backend now filters those out; this consumes the
filtered contract and adds the per-day dimension.

- getBookingLocations takes an optional date and the appointment page refetches
  on it, merging available_on_date into the existing list rather than replacing
  it, so browsing the calendar never resets the user's choice.
- The browsed day had to be lifted out of the Date step: selectedDate is only
  set once a slot is confirmed, far too late to drive availability.
- A location closed on the chosen day renders disabled with «در این روز نوبت
  ندارد», and when every location is closed the step says so instead of showing
  an empty slot list. If the already-selected location closes, a notice appears
  with a link back to the picker — silently showing nothing was the failure mode
  worth avoiding.
- Doctor profile: workLocation in the Physician JSON-LD is limited to addresses
  that appear in booking_locations, since schema.org presents them as places a
  patient can attend. The address card still lists the others — they are real
  practice details — tagged «بدون نوبت‌دهی آنلاین».

Verified end-to-end with a temporary unused address on the test doctor: the
visible card listed both and tagged the unused one, while workLocation carried
only the bookable one. The row was removed afterwards.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 14:44:49 +03:30
hamedandClaude Opus 4.8 eba0c6a5ba feat(booking): let patients choose the booking location
A doctor now has one booking schedule per context — the personal practice plus
one per clinic — and every booking endpoint takes an optional clinic_uuid where
omitting it means the personal practice, not a wildcard. This site sent none, so
a clinic-only doctor showed no availability at all and a doctor working in both
places silently booked into the wrong one.

- services/response.js: getBookingLocations + clinic_uuid on slots,
  service-slots, booking-services and month-availability. The manual query
  building is kept so the service_item_uuids[] serialisation does not change.
- AppointmentPage owns the selected location; booking_mode and services are
  derived from it instead of a separate getBookingServices call, which drops a
  request. Changing location clears the selected service, slot and date, since
  a service from one location cannot be booked into another.
- New LocationSelect step, shown only when there is more than one location.
  The list arrives sorted by earliest free slot, so the first item is the
  default and is not re-sorted here.
- DatePicker drops its month cache when the location changes; otherwise the
  previous location's disabled days stayed on the calendar.
- The slot address now comes from the selected location rather than
  doctor.address, which does not contain clinic addresses.
- clinic_uuid rides through to the appointment payload, and
  /appointment/[doctorId]?clinic_uuid=… preselects a location.
- Doctor page JSON-LD gains availableService from the bookable services.
  openingHoursSpecification still needs a public weekly-hours endpoint.

Removed the dead locateVisit state, which was initialised true and never unset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 13:48:31 +03:30
hamed 165a0a2240 feat(appointment): implement service-based booking flow with service selection and slot adaptation 2026-07-15 23:48:40 +03:30
hamedandClaude Opus 4.8 4fed9a8c57 feat(doctor): fix map render + claim modal captcha/mobile + owner delete
- Doctor page map: the visible locations card read doctor.address (empty
  from the detail endpoint) while coordinates live in the separately
  fetched addresses. Thread `addresses` (with map.latitude/longitude) down
  page → DoctorPage → DetailDoctor → Locations; card hidden when empty
- Claim modal: updated info-box text ("نوبت‌های این پروفایل عمومی و غیرخاص
  هستند")، added mobile field (validated, must match account), added ALTCHA
  widget (submit disabled until captcha resolves; payload sent as `altcha`)
- Owner delete: services.deleteDoctor + a guarded two-step "حذف این پروفایل"
  in the claim success screen (owner enforced server-side; 403/409 shown)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 15:04:28 +03:30
hamedandClaude Opus 4.8 d8ab26b4b7 feat(doctor): claim-profile section + modal for unclaimed IRIMC-imported doctors
- ClaimProfileSection (components/doctor/claim): shown only when
  doctor.owner_status === "unclaimed"; banner explains the profile is not
  yet managed by the doctor, button "تأیید و مدیریت این پروفایل"
- Modal: login prompt when logged out; otherwise first/last name,
  national code, Jalali birth-date (existing JalaliDatePicker) — posts to
  POST api/v1/doctor/{uuid}/claim (identity verified server-side via API.ir;
  no client call to API.ir, no token exposure)
- States: loading, per-field validation, server error (Persian envelope
  message), double-submit guard, success welcome message + redirect
- Shared component across main domain and all representative subdomains
- services/response.js: getDoctorClaimInfo / postDoctorClaim

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 11:44:40 +03:30
hamed 778876b1f7 Refactor code structure for improved readability and maintainability 2026-07-10 11:27:17 +03:30
hamed 97cc4fdc69 feat: add domain parameter to sendCode for OTP requests to include city site name 2026-07-04 11:01:56 +03:30
hamed e6b55c6bad feat: refactor payment handling to use direct backend redirect instead of API call 2026-07-02 17:08:52 +03:30
hamed c316d22160 feat: add testing setup with Vitest and Testing Library
- Updated package.json to include Vitest and Testing Library dependencies and scripts for testing.
- Created a test suite for the ProvinceProvider context to validate cityId and province detection based on subdomains.
- Implemented unit tests for utility functions in helper/index.js, including phone number formatting and validation.
- Added tests for state information retrieval in lib/getStateInfo.js, ensuring correct city and state matching based on subdomains.
- Developed tests for appointment slot adaptation and availability checks in lib/appointmentSlots.js.
- Created tests for token storage functionality in lib/tokenStore.js.
- Implemented sanitization and JSON parsing tests in lib/sanitize.js.
- Added CASL ability tests in lib/ability.js to verify user access rights.
- Created tests for cookie management in lib/refreshCookie.js.
- Developed tests for patient user representation in lib/representationAdapters.js.
- Implemented client-side state information retrieval tests in lib/getStateInfoClient.js.
- Created tests for canonical URL generation in lib/getCanonicalUrl.js.
- Developed tests for clinic API service functions in services/clinicApi.js.
- Added request wrapper tests in services/response.js to ensure correct API interaction.
- Set up Vitest configuration in vitest.config.mjs for JSX support and alias resolution.
- Created setup and utility files for testing environment in test/setup.js and test/utils.jsx.
2026-06-28 23:25:46 +03:30
hamed e0d729dcf1 fix(api): ensure token is refreshed if not available during request 2026-06-21 13:47:07 +03:30
hamed 194ffd889c feat: enhance security by implementing HttpOnly refresh tokens and in-memory access token management
- 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
2026-06-20 13:10:17 +03:30
hamed ea2c0c29ec feat(userAccount): enhance user profile handling with avatar upload and additional user data 2026-06-19 10:19:52 +03:30
hamed e9136ea42b feat(blog): enhance blog data handling with normalization and improved image management 2026-06-19 00:35:11 +03:30
hamed 4dca516598 feat(clinic): enhance doctor data handling with improved pagination and default values 2026-06-18 19:16:52 +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 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 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 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 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 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 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 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
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
hamed 3ca69dcd0f refactor: enhance representation info fetching and pass it to relevant components 2025-12-02 15:38:42 +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 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
hamed 5a9f21e88d refactor: require authentication for appointment posting in response service 2025-11-18 16:57:42 +03:30
hamed 8c03717cb7 refactor: add supplementary insurance handling in Form component and update Detail component to fetch insurance data 2025-11-17 15:48:33 +03:30
hamed b46a017773 refactor: enhance appointment flow by adding selected slot and date management across components 2025-11-17 15:33:47 +03:30
hamed 2777db3b8c refactor: enhance phone number validation and input handling in Field and LogInPage components 2025-11-17 15:09:25 +03:30
hamed 6c787fe5fa refactor: add location address handling in DateTime component and update Hours component to display address 2025-11-17 14:50:53 +03:30
hamed 1e510a84b1 refactor: enhance date selection logic in DatePicker and update appointment request parameters 2025-11-17 14:18:15 +03:30
Arezoo 79ff139779 loading ,page 2025-10-27 10:58:26 +03:30
Arezoo 34188ab366 error handeling on the pagination 2025-10-22 17:38:29 +03:30
Arezoo f22526bff3 paginations ,limit=50 2025-10-22 14:30:30 +03:30
Arezoo bfd797dd02 api change 2025-10-21 14:32:13 +03:30
Arezoo 2cbf96ec6f handel filter clinic and added changenumber function 2025-10-21 13:31:44 +03:30
ehsan 0b90e1abc4 change api file and design poster 2025-10-04 20:36:50 +03:30
ehsan 83e482507b responsive pagination && handle free_turn value && fix set value in small size appo list in page doctors && set data rate in doctor item && fix set token in cookie in page login on domain nobat724.com 2025-10-04 17:16:47 +03:30
ehsan 6f35ee3c10 round img of doctors && fix remove 'nobat724' value in city data for all pages && handle send req for filter clinics && filter list clinic for first time on load page && add component loading and handle it in page clinics 2025-09-27 21:06:32 +03:30
ehsan dfc8492afa handle like comments data, req for update comments and add loading for like comment && search specialty with searchbar in doctors page && set category and specialty data 2025-09-20 17:04:36 +03:30
Ehsan dc40129034 handle change data in doctor model, set previous data when user close modal, update list doctor after update data and change key name in url 2025-09-05 23:05:02 +03:30
Ehsan ebfe47468c get data with filter location for first time, get comment of doctor and show in doctor page, handle new comment 2025-09-03 22:05:26 +03:30
Ehsan 6920e4078b redirect filter data to doctors page from home page just with one key && add picture url to doctors page && add conditional to appo page and change data in server 2025-09-02 00:32:04 +03:30