Commit Graph
42 Commits
Author SHA1 Message Date
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
hamed ab2ab0dea2 feat: enhance domain handling for global representatives
- Updated `getStateInfo` to fetch site context for domains not in city.json, returning `repContext` with representative details.
- Implemented caching for site context requests to optimize performance.
- Modified doctor and clinic listing pages to pass the `domain` parameter when fetching data for global representatives.
- Adjusted metadata generation in layout and pages to reflect representative branding based on `repContext`.
- Added documentation for the new functionality in `.claude/prompt/global-rep-domain-site.md`.
2026-07-09 07:34:09 +03:30
hamed 92b8f474c1 Add SEO fields to city.json for local branding optimization
- Introduced a new `title` field for each city record, incorporating local brand names.
- Rewrote `slogan` for each city to reflect startup tone and include city keywords.
- Optimized `keywords` with relevant local and long-tail search terms.
- Ensured compliance with SEO best practices and maintained JSON structure.
2026-07-08 11:57:31 +03:30
hamed df7fbb7530 Refactor code structure for improved readability and maintainability 2026-07-06 15:10:19 +03:30
hamed e8e3d7bfd8 Add cache index and graph files for improved data handling
- Created stat-index.json to store metadata for various data files, including size, modification time, and hash.
- Added graph.html and graph.json files to the graphify-out directory for enhanced graph representation.
2026-07-06 10:12:59 +03:30
hamed b04bb45ca1 Implement multi-domain SEO improvements:
- Add metadata to login and login-verify pages to prevent indexing.
- Update robots.txt to disallow additional sensitive paths.
- Enhance sitemap generation to filter by city and include accurate last modified dates.
- Refactor canonical URL generation to support multi-domain architecture, ensuring self-canonicalization for city domains.
- Remove deprecated CanonicalHandler component and streamline canonical URL handling.
- Introduce safe JSON-LD output to prevent XSS vulnerabilities.
- Add payment layout with appropriate metadata to prevent indexing.
- Conduct a comprehensive technical SEO audit and implement necessary fixes across the application.
2026-07-05 15:47:47 +03:30
hamed 3c019932bd feat: redesign doctor sharing poster layout and enhance download functionality with dynamic file naming 2026-07-04 22:25:49 +03:30
hamed 199c843b08 feat: enhance poster download functionality by ensuring images load before PDF generation and adding QR readiness check 2026-07-04 21:50:57 +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 3fdd8b3e8b fix: update site_name for city record to remove redundancy 2026-07-03 12:35:30 +03:30
hamed 5bec4848a2 feat: unify currency display to toman across the application 2026-07-03 10:31:16 +03:30
hamed 79f7df2e4d feat: implement root domain handling for nobat724.com to prevent city filtering 2026-07-02 21:53:45 +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 e83a666adb feat: enhance payment flow with dynamic URL handling and improved error messaging 2026-07-02 15:36:09 +03:30
hamed 9e67ce4872 feat: update payment gateway selection to use active gateways from backend config 2026-07-02 12:19:44 +03:30
hamed ee1192b5b9 feat: prepare nobat724_front for deployment on Liara platform
- Added Node.js engine requirement in package.json to ensure compatibility.
- Created liara-deploy.md for deployment instructions and environment setup.
- Added example environment variables in .env.liara.example for clarity.
- Introduced .liaraignore to exclude unnecessary files from deployment.
- Created liara.json for Liara configuration, including health check settings.
- Removed redundant next.config.mjs file to prevent configuration conflicts.
2026-06-30 14:48:21 +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 de9e6b7678 feat(api): add adaptation for backend-audit changes and update comment pagination 2026-06-28 22:04:54 +03:30
hamed cc6b42c1a5 feat(appointment): add city_id to appointment payload and update ProvinceProvider for city context 2026-06-24 19:56:04 +03:30
hamed a83e352dd8 fix(appointment): update display logic for inactive doctors and free turns 2026-06-22 09:47:11 +03:30
hamed cb13ba3f45 fix(doctors): improve filter performance and resolve modal closing issues 2026-06-21 15:47:37 +03:30
hamed 609479919a fix(verification): remove hardcoded prefix from phone number in confirmation message 2026-06-21 13:35:05 +03:30
hamed 9dd71ab2f5 feat(clinic): enhance generateMetadata and JSON-LD for comprehensive clinic schema 2026-06-21 13:26:49 +03:30
hamed a8c3a57114 feat(doctor): enhance doctor schema with addresses, ratings, and social media links
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
2026-06-21 12:35:15 +03:30
hamed 06a877a725 feat(metadata): enhance SEO by adding Open Graph and Twitter metadata across various pages
feat(blog): implement loading and error handling components for blog pages

feat(clinic): add loading and error handling components for clinic pages

feat(doctor): create loading and error handling components for doctor pages

feat(clinics): add loading component for clinics page

feat(specialties): improve metadata for specialties page with Open Graph and Twitter images

feat(layout): add structured data for Organization and WebSite in layout

fix(middleware): restrict middleware execution to specific routes to improve performance

chore(audit): add comprehensive SEO and performance audit documentation
2026-06-21 11:38:39 +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
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 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 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 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 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 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 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
hamed 4374ed5043 feat(panel): connect representative panel and user dashboard to real API, removing mock data 2026-06-15 09:12:51 +03:30