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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
- 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>
- 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