The Google Maps iframe was blocked by CSP (frame-src falls back to
default-src 'self'). Switched the doctor-page location map to react-leaflet
with OpenStreetMap tiles — no iframe, and CSP already allows https image
tiles (img-src 'self' https:). Marker icons are bundled from the leaflet
package (no CDN). MapView is dynamically imported (ssr:false) since Leaflet
needs window.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mobile is prefilled from the logged-in user's cookie (userInfo.mobile_number)
and rendered read-only; removed it from editable form state/validation and
send that number in the claim body. Backend already enforces it must match
the account, so the field can't diverge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- isUserLoggedIn() checked the access_token cookie, which is never set
(access_token lives in memory / tokenStore; only userInfo + uuid are
cookies). It therefore always returned false — the claim modal (and
comment auth checks) kept showing the login prompt even when logged in.
Now reads the userInfo cookie.
- Claim modal login link carries ?redirect=<current path>; after OTP login
SendReq returns to that path (guarded to internal "/..." only, blocks
protocol-relative //) instead of always going to "/".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 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>
- 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>
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
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 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>
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>
برخی پزشکان address ندارند؛ data?.address[0] روی آنها کرش میکرد
(Cannot read properties of undefined). اصلاح به data?.address?.[0]
در Address و Telefon صفحه پروفایل پزشک.
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>
- 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
- 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