Commit Graph
677 Commits
Author SHA1 Message Date
hamed 79747c443c feat: Enhance specialty handling and navigation across doctor and specialty pages 2026-08-08 17:33:13 +03:30
hamed 56e264e44c feat: Refactor specialty display logic and enhance specialty filtering
- Introduced SpecialtyChips component to manage the display of doctor's specialties with a primary specialty and a count of additional specialties.
- Updated ItemDoctor component to utilize SpecialtyChips for better UI presentation.
- Enhanced PosterLight and Poster components to display primary specialties and a text line for sub-specialties.
- Implemented nextSpecialtyFilter function to improve specialty selection logic in the Content component.
- Updated search functionality to allow searching by both doctor name and specialty.
- Added new specialties to specialties.json for better coverage.
- Created sync-specialties script to synchronize specialties data with the backend during build.
- Added tests for new components and helper functions to ensure functionality and reliability.
2026-08-08 17:19:22 +03:30
hamedandClaude Opus 5 94c22de8dd docs(prompt): plan the multi-specialty UI work
Companion to clinicpro's doctor-multi-specialty-search prompt, which is already
merged and now returns specialties[].parent_id plus descendant-aware
specialty_id filtering.

Records what the code inspection turned up, so the implementation does not
rediscover it: data/specialties.json is a stale snapshot missing the five newest
children of جراحی عمومی, which is why /specialties/جراح-گوارش 404s and why the
parent/child UI cannot be built until it is synced at build time; the filters
modal force-selects the first child when a group is picked, silently narrowing
the search; and both poster variants slice specialties to a blind four, which
overflows the fixed 1080x1350 frame.

Not executed yet — committed so the plan is not carried around untracked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 16:49:43 +03:30
hamed 29881eede0 Add AST JSON file for blog category breadcrumb and filter prompt with detailed nodes and edges 2026-07-30 12:22:55 +03:30
hamed 8a24579a50 refactor: remove FEATURE flags for doctor ratings and sharing in components 2026-07-30 09:16:13 +03:30
hamed e87a0bae9b feat: add feature toggles for doctor share and ratings functionality 2026-07-30 09:05:45 +03:30
hamed eb83762016 Refactor blog components for improved tag filtering and related content display
- Added `getBlogTagFacets` API call to fetch blog tags based on city scope.
- Updated `BlogsPage` to read selected tag from URL and handle tag changes with URL updates.
- Modified `Title` component to display tags from the new API and reflect active tag state.
- Enhanced breadcrumb navigation to link categories to their respective pages.
- Adjusted related content section to display articles from the same category and fixed layout issues.
- Corrected heading hierarchy across various components for better SEO compliance.
- Ensured consistent styling and spacing in related content items.
2026-07-29 14:23:37 +03:30
hamed 533449c504 Update manifest and add new AST cache for blog frontend sync and default cover
- Updated modification times and AST hashes for several files in the manifest.json.
- Added new entries for `app/api/revalidate/route.js`, `components/blog/detail/Faq.js`, `components/blog/detail/Sources.js`, and other files related to blog functionality.
- Introduced a new AST cache file for the blog frontend sync and default cover prompt, including detailed node and edge relationships.
2026-07-27 19:38:55 +03:30
hamed 19ae08c04a feat(blogCover): enhance default blog cover layout with RTL support and improved design elements 2026-07-27 19:20:34 +03:30
hamed cea8982e6d feat: add script to generate default blog cover image
- Introduced a new script `make-blog-cover.mjs` to create a default cover image for blog posts.
- The image is generated in PNG format with dimensions 1200x630, suitable for Open Graph.
- Utilizes the site's branding colors and logo from `public/nobat724.svg`.
- Includes custom font styling using the Vazirmatn font.
- The generated image is saved to `public/assets/images/blog-default-cover.png`.
2026-07-27 19:07:30 +03:30
hamed 2f8dec0fb8 fix(sanitize): update comments for ALLOWED_TAGS to clarify synchronization with composer.py 2026-07-27 11:35:54 +03:30
hamed 2b68ad46b7 Update manifest.json with new mtime and ast_hash values for various files; add breadcrumb and breadcrumb.test.js entries. 2026-07-26 09:18:34 +03:30
hamed d02ae8bff0 feat(entityQuality): rename isThinDoctor to isNoindexDoctor for clarity and update related logic 2026-07-26 09:17:42 +03:30
hamed b8514e64cf feat(breadcrumb): implement BreadcrumbList structure and validation for SEO compliance 2026-07-24 10:39:41 +03:30
hamed 9053681375 feat(blog): implement domain-specific blog fetching and canonical URL handling 2026-07-24 10:01:35 +03:30
hamed f46ba03422 Update manifest.json and add AST cache file for recent changes
- Updated modification times and AST hashes for several JavaScript files in the app/blog, app/component, app/doctor, and components/common directories.
- Added a new AST cache file for a data JSON that was skipped due to a non-object root.
2026-07-23 22:26:58 +03:30
hamed 7bbfe9a698 feat(metadata): enhance SEO fields for blog and blogs pages 2026-07-23 22:16:32 +03:30
hamed 42b7fa5a98 feat(specialties): add new specialty for جراحی استخوان و مفاصل 2026-07-23 19:49:53 +03:30
hamed 3b6698dca0 Merge branch 'fix/hide-inactive-doctors' into main
- fix(doctor): 404 deactivated doctor profile page
- fix(datePicker): mobile/lg next-month navigation
2026-07-23 19:43:45 +03:30
hamed 0a2a2bfba3 fix(datePicker): hide next button for inactive months on larger screens 2026-07-23 19:43:02 +03:30
hamedandClaude Opus 4.8 cd32f6c8bd fix(doctor): 404 deactivated doctor profile page
Deactivated doctors are now absent from the public list, but their
/doctor/{uuid} page still loaded. getDoctor() now treats the backend's
raw `is_active === false` as not-found, so the profile 404s like the
list — matching the site's "hide inactive doctors" behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 19:39:38 +03:30
hamedandClaude Opus 4.8 1986356c91 fix(doctor): hide deactivated doctors from public site
The public list GET /api/v1/doctors only excluded inactive doctors
when an explicit `active` filter was passed; with no param it returned
everyone (deactivated doctors just ranked lower). Deactivated doctors
(admin toggled active_doctor_appointment off) leaked onto nobat724.

- DoctorRepository::findWithFilters: default (no `active` param) now
  filters activeDoctorAppointment = true. The active=1 (bookable) and
  active=0 (admin, inactive-only) escape hatches are unchanged.
- Doctor::toDetailArray: expose raw `is_active` (= activeDoctorAppointment,
  independent of schedule) so public clients can 404 a deactivated
  doctor's profile page; distinct from `active` (flag && has_schedule).
- Tests + docs/api/doctor.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 19:38:01 +03:30
hamed ccbd028fee Add JSON representation of search fix and SEO prompts for Nobat724 2026-07-22 16:49:34 +03:30
hamed a39b90c88c feat: normalize doctor name query to enhance search functionality and improve URL building 2026-07-20 12:33:22 +03:30
hamed ac3a84d55d feat: implement search URL building and enhance search functionality in Fields and RedirectLink components 2026-07-20 12:28:52 +03:30
hamed 984511653b feat: update specialty URL generation logic and improve indexing strategy for specialties 2026-07-20 11:54:03 +03:30
hamed 30c3fe8637 feat: enhance SEO for listing and specialty pages, fix search autocomplete issue 2026-07-20 10:26:03 +03:30
hamed 9011b230b3 Update manifest.json and add new AST cache files for clinic contact info and maintenance mode prompts
- Updated mtime and ast_hash for several files in manifest.json
- Added new AST cache files for the clinic contact info fix and maintenance mode client prompts
2026-07-19 22:06:34 +03:30
hamedandClaude Fable 5 daf38c8631 feat(maintenance): show maintenance page when the API is in maintenance
The backend now answers 503 with code MAINTENANCE_MODE while maintenance is
on. Without this change a visitor got a red error toast over a broken page
client-side, and a silently empty page server-side, because fetchReq discards
the status and returns null on any failure.

- lib/maintenance.js detects the state by BOTH status 503 and the error code;
  a bare 503 can come from a reverse proxy and is not maintenance
- The axios interceptor checks it before the 401 branch, so a maintenance
  response never triggers the refresh-token path or logs the user out
- fetchReq redirects to /maintenance, with a silentMaintenance opt-out used by
  getStateInfo: that one runs inside generateMetadata and while rendering the
  maintenance page itself, where a redirect is either ineffective or loops
- redirect() works by throwing, so the try/catch blocks in the doctors,
  clinics and specialties pages now rethrow NEXT_REDIRECT instead of
  swallowing it
- clinicApi.js handles 503 too; it previously rendered maintenance as a clinic
  with zero doctors
- The page reuses the existing 404 design and is marked noindex

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 22:01:45 +03:30
hamed 18484f974d feat: update doctor display logic to prioritize display_name and enhance metadata description with address details 2026-07-19 19:57:05 +03:30
hamed 1522ee8b73 feat: enhance clinic contact information display with new helper functions for phone, city, and state 2026-07-19 16:44:06 +03:30
hamed 10b5a19576 feat: add MapView component for displaying maps with markers 2026-07-19 16:43:59 +03:30
hamed e8a7bdf2fc feat: enhance doctor and clinic components with doctorTitle helper and improve rendering logic 2026-07-19 16:17:24 +03:30
hamed 4c8377f439 feat: add doctorTitle helper function and update references in metadata and FAQ 2026-07-19 15:40:24 +03:30
hamed b3ffba82d4 fix: update source locations and confidence scores in graph.json; update mtime in manifest.json for multiple components 2026-07-19 14:01:05 +03:30
hamed 29b8819021 refactor(docker): update Dockerfile for Next.js 15 and enhance build stages 2026-07-19 13:19:43 +03:30
hamed 672a7d89bf Fix community IDs and update sitemap functionality
- Updated community IDs for various components in graph.json to reflect correct associations.
- Added new function `getPublishedDoctors()` in app/sitemap.js and established relationships with existing functions.
- Adjusted source locations for several functions in app/sitemap.js to ensure accurate mapping.
- Enhanced canonical URL handling in lib/getCanonicalUrl.js to prevent incorrect canonicalization for paginated specialty pages.
- Updated manifest.json with new modification times and AST hashes for affected files.
2026-07-19 09:32:00 +03:30
hamed 97e990982f Update manifest.json with new mtime and ast_hash for sitemap.js 2026-07-19 09:10:09 +03:30
hamed 8eb55679b2 feat(sitemap): optimize doctor URL fetching and add sitemap index threshold warning 2026-07-19 09:10:04 +03:30
hamed 488e5eb0a4 Add JSON files for blog city scoping and SEO post-deploy verification prompts
- Created a new JSON file for the blog city scoping activation prompt, including nodes and edges representing the document structure.
- Added a new JSON file for the SEO post-deploy verification prompt, detailing nodes and edges related to SEO verification tasks.
2026-07-19 09:02:23 +03:30
hamed 4d7b87ee1a feat(blog): enhance metadata generation and blog fetching by city context 2026-07-19 09:02:14 +03:30
hamed 88782e70c2 test(extractEntityCityId): prioritize address over top-level city in entity extraction 2026-07-19 08:54:00 +03:30
hamedandClaude Opus 4.8 21f5f07bc6 chore(prompt): record SEO audit and split remaining work
P1-P11 of the live SEO audit are implemented and verified against a local
production build, so the audit file becomes a reference rather than a
task list: it now records what shipped, the root causes that differed
from the original hypotheses, and the deliberate trade-offs.

Remaining work is split into smaller prompts, ordered by dependency:

- seo-post-deploy-verification: the acceptance criteria were "curl on
  production" but were only run against a local build
- blog-city-scoping-activate: blocked on the backend blog city column
- sitemap-simplify-with-city: drops the 35-sweep workaround once the
  doctors list exposes city

Each names its blocking dependency and carries reference numbers so a
regression is visible.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 08:09:21 +03:30
hamed c64a4a7d69 refactor(specialties): simplify specialty link generation logic 2026-07-19 07:52:58 +03:30
hamed fd48b48613 feat: add canonical URL handling and entity quality checks
- Implemented canonical URL strategies for city-specific domains and entities.
- Added helper functions for domain and city resolution.
- Created tests for canonical URL generation and domain resolution.
- Introduced entity quality checks for doctors and clinics to ensure meaningful content.
- Developed unique introductory texts for listing pages to avoid duplicate content.
- Established robots.txt policies for listing pages to manage indexing based on user filters.
- Enhanced specialty content with dynamic introductions and FAQs to improve SEO.
2026-07-19 07:52:50 +03:30
hamedandClaude Fable 5 36816eded2 fix(doctor): derive booking state from booking_locations
The profile decided "نوبت‌دهی غیرفعال است" from `doctor.active` alone, while the
page already had `booking_locations` — the more precise source, since the backend
only returns locations that are genuinely bookable. The two could disagree, and
for a doctor bookable only at a clinic they did.

A shared `bookingState` helper now drives both the desktop card and the mobile
bar: any location means bookable, the label comes from the earliest
`next_available_at`, and locations with no capacity yet read as "فعلاً نوبت خالی
ندارد" rather than disabled. With no locations at all it falls back to the
previous `doctor.active` / `free_turn` fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 16:25:37 +03:30
hamedandClaude Opus 4.8 dfcf62735b chore(graphify): rebuild code graph after day-aware locations
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 14:44:51 +03:30
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 f4dd73e55e chore(graphify): rebuild code graph after opening-hours change
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 13:53:31 +03:30
hamedandClaude Opus 4.8 0eb172517f feat(seo): emit openingHoursSpecification per work location
The doctor page listed where a doctor works but never when, so search engines
had no working hours for any location. booking_locations now carries
opening_hours per context, so each MedicalClinic in the Physician JSON-LD gets
its own openingHoursSpecification, matched to the address by uuid.

Verified against the rendered page: the clinic location emits five shifts with
schema.org weekday URLs alongside the availableService entries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 13:53:28 +03:30