Commit Graph

21 Commits

Author SHA1 Message Date
soroush.asadi 21769deda6 fix(admin): show error toast instead of success when savePost fails
CI/CD / CI · dotnet build (push) Successful in 1m34s
CI/CD / Deploy · drsousan (push) Successful in 31s
api() returns null on HTTP error; the save block now checks the return
value before closing the modal and showing the success toast.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 22:11:20 +03:30
soroush.asadi 5ae6bb03a2 fix: resolve two build errors — siteBaseUrl self-reference + ForwardedHeaders
CI/CD / CI · dotnet build (push) Successful in 11m58s
CI/CD / Deploy · drsousan (push) Successful in 13s
- Index.cshtml: siteBaseUrl was referencing itself as fallback; replaced
  with literal default "https://draletaha.ir"
- Program.cs: removed UseForwardedHeaders call — ForwardedHeadersOptions
  unavailable in this SDK config; SITE_BASE_URL env var handles base URL

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-08 23:33:38 +03:30
soroush.asadi d02a5963cf fix: HTTPS URLs in sitemap, robots, canonical + og:image on homepage
CI/CD / CI · dotnet build (push) Failing after 5m22s
CI/CD / Deploy · drsousan (push) Has been skipped
- Add UseForwardedHeaders middleware so Request.Scheme = "https" behind nginx
- Add SITE_BASE_URL env var fallback for sitemap.xml, robots.txt, and all
  Razor page canonical/og URLs — set it to https://draletaha.ir in .env
- Add og:image to homepage using hero photo
- Add SITE_BASE_URL to docker-compose.yml environment block

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-08 22:30:55 +03:30
soroush.asadi 22d0ecb330 feat: doctor reply + diagnosis + tracking code per health request
CI/CD / CI · dotnet build (push) Successful in 45s
CI/CD / Deploy · drsousan (push) Successful in 28s
Backend:
- HealthRequest model: TrackingCode (DR-XXXXXX), Diagnosis,
  DoctorReply, RepliedAt fields
- Runtime migration: ALTER TABLE adds 4 new columns to existing DB
- POST /api/health-request: auto-generates tracking code, returns it
- PUT /api/health-requests/{id}/reply: doctor sets diagnosis + reply
- GET /api/health-request/track/{code}: public lookup by tracking code
- GET /api/health-requests?phone=: filter history by phone number

Admin panel:
- Request table shows tracking code column (gold badge)
- Detail modal (680px): tracking code header, patient info, full message
- Previous doctor reply shown in green box if exists
- Reply form: diagnosis input + textarea for doctor message
- History panel: all requests from same phone, click to switch
- 'پاسخ / مشاهده' button opens reply modal directly

Frontend:
- After form submit: shows tracking code in green box to user
  (format: DR-XXXXXX, stays visible 8 seconds)
- Box auto-hides and form resets after timeout

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 22:03:00 +03:30
soroush.asadi 1e51df406b fix: cropper mime bug + loadSiteIdentity crash + logo|name header
CI/CD / CI · dotnet build (push) Successful in 37s
CI/CD / Deploy · drsousan (push) Successful in 29s
1. applyCrop() — mime variable was declared INSIDE toBlob callback
   but used as an argument to toBlob() (outer scope) → ReferenceError.
   Fix: declare _mime, _quality, _ext BEFORE out.toBlob() call.

2. loadSiteIdentity() — crashed when identity section had no rows
   (data was null/non-array). Fix: safe Array.isArray guard + catch.

3. Header logo: show logo image + | + site name side by side
   when logo is configured (was showing one OR the other).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 18:15:51 +03:30
soroush.asadi 5d6a4a630d fix: preserve original file type on upload — never convert PNG to JPG
CI/CD / CI · dotnet build (push) Successful in 53s
CI/CD / Deploy · drsousan (push) Successful in 28s
Problem: cropper always called out.toBlob(..., 'image/jpeg') regardless
of the original file type, silently converting PNGs to JPGs.

Fix:
- openCropper() now stores file.type and file.name on the cropper object
- applyCrop() uses the stored mime type for toBlob() and the filename
- Quality param only passed for lossy formats (jpeg/webp), not for PNG/GIF
- uploadImage() accept list expanded: svg, ico allowed
- Server-side: .svg and .ico added to allowed extensions

Result: PNG stays PNG, WebP stays WebP, ICO stays ICO.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 18:06:38 +03:30
soroush.asadi e79ccf7e8c feat: logo and favicon management in admin panel
CI/CD / CI · dotnet build (push) Successful in 41s
CI/CD / Deploy · drsousan (push) Successful in 29s
Admin panel:
- New 'هویت سایت' page under تنظیمات in sidebar
- Upload logo (PNG transparent, 200×60px recommended)
- Upload favicon (PNG/ICO, 32×32 or 64×64px)
- Live preview panel shows how logo looks in header
  and how favicon looks in a browser tab mockup
- Saved to SiteSettings with section='identity', key='logo'/'favicon'

Frontend (_Layout.cshtml):
- Injects AppDbContext to load identity settings per request
- If logo is set: shows <img> in header instead of text
- If favicon is set: uses uploaded file as <link rel="icon">
- Falls back to text / favicon.ico when not configured

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 17:47:49 +03:30
soroush.asadi 81838f75ce fix: unify two reservation forms into one — wire booking to API
CI/CD / CI · dotnet build (push) Successful in 41s
CI/CD / Deploy · drsousan (push) Successful in 29s
Problem: two parallel booking systems:
1. 'رزرو نوبت آنلاین' contact form — never saved data (fake submit)
2. Health section inline form — saved to /api/health-request

Fix:
- Contact form now POSTs to /api/health-request (real save)
- Added ids to all form inputs so JS can read them
- Category auto-detected from service dropdown (سلامت عمومی → health)
- Health section 'درخواست...' buttons now scroll to contact form
  and pre-select the right category — no duplicate inline form
- Removed the duplicate healthFormWrap + submitHealthForm()
- All reservations visible in admin under 'درخواست‌ها'

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 16:51:58 +03:30
soroush.asadi 772df0698c feat: health request detail modal + view button always visible
CI/CD / CI · dotnet build (push) Successful in 3m21s
CI/CD / Deploy · drsousan (push) Successful in 29s
- Every row now has a 'مشاهده' button regardless of handled status
- Opens a modal with: name, phone, email, category, date, status,
  and full message text (no truncation)
- Modal includes 'علامت‌گذاری' button if request is still pending
- Message column in table kept short (truncated) as a preview only

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 16:15:01 +03:30
soroush.asadi e73d47a875 fix: remove apt-get curl install — use bash TCP health check instead
CI/CD / CI · dotnet build (push) Successful in 40s
CI/CD / Deploy · drsousan (push) Successful in 15s
archive.ubuntu.com is unreachable from the build server, causing
apt-get to time out and fail every build. curl was only used for
the HEALTHCHECK. Replace with a zero-dependency bash TCP check:
  bash -c 'echo > /dev/tcp/localhost/8080'
No packages needed, no external network access required.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 16:03:08 +03:30
soroush.asadi b3c4615bc7 fix: replace emoji with hero image in blog sidebar doctor card
CI/CD / CI · dotnet build (push) Successful in 51s
CI/CD / Deploy · drsousan (push) Failing after 5m40s
- Post.cshtml.cs: load hero image, tag from SiteSettings in SetViewDataAsync
- Post.cshtml: show <img> with hero image in .doc-avatar when set,
  fall back to emoji only if no image is configured
- .doc-avatar: circular crop with object-fit:cover, gold border
- doc-title now uses HeroTag from settings (not hardcoded)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 15:15:06 +03:30
soroush.asadi ed25bec200 fix: 3 bugs — beauty icon color, appointments on dashboard, blog image edit
CI/CD / CI · dotnet build (push) Successful in 1m28s
CI/CD / Deploy · drsousan (push) Has been cancelled
1. Beauty category icon: was pink (#C2185B), now uses site primary gold
   (var(--gold) / var(--gold-pale)) to match brand color

2. Dashboard now shows health requests:
   - Two new stat cards: total patients + pending requests (clickable)
   - 'آخرین درخواست‌ها' mini-table showing last 6 requests
   - Sidebar badge updates from dashboard load too
   - loadDashboard() now fetches /api/patients + /api/health-requests

3. Blog image edit fix:
   - applyCrop() now captures inputId/previewId BEFORE closeCropper()
     to prevent any potential race condition when replacing images

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 15:09:46 +03:30
soroush.asadi 3780dcccf2 feat: patient management system + health landing page
CI/CD / CI · dotnet build (push) Successful in 59s
CI/CD / Deploy · drsousan (push) Successful in 1m33s
Backend:
- Patient model: name, phone, email, age, weight, height, gender,
  blood type, disease history, allergies, medications, notes, category
- PatientVisit model: title, content, prescription, visit type,
  visit/next-visit dates, linked to patient (cascade delete)
- HealthRequest model: public form submissions for beauty/health care
- Runtime SQLite migrations for all 3 new tables
- Full CRUD API: /api/patients, /api/patients/{id}/visits,
  /api/health-requests (public POST + admin GET/PUT/DELETE)

Admin panel:
- 'پرونده بیماران' page: list, search, filter by category (beauty/health)
- Patient profile page: personal info + medical history + visits timeline
- Add/edit patient modal with all medical fields
- Add visit modal: type, date, clinical notes, prescription, next visit
- 'درخواست‌ها' page: manage public health requests, mark as handled
- Badge counter for unhandled requests in sidebar

Frontend (SEO):
- New #health-care section with Schema.org MedicalClinic markup
- Two category cards: زیبایی پوست and سلامت عمومی
- Feature lists with checkmarks per category
- Inline request form that submits to /api/health-request
- Mobile responsive (single column on small screens)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 12:27:16 +03:30
soroush.asadi 0765d5d3cd fix: move gallery captions and before/after labels below images
CI/CD / CI · dotnet build (push) Successful in 38s
CI/CD / Deploy · drsousan (push) Successful in 57s
Instead of overlaying text on top of the image (hard to read),
restructure each gallery card to flex-column:
- Image section (.gallery-img-wrap) on top with aspect-ratio:4/3
- Before/After labels row (.ba-labels) below the image, full text visible
- Caption (.gallery-caption) below that, with padding and border

Labels now show full text 'قبل از درمان' / 'بعد از درمان' in a clean
row under the split image — never overlapping, always readable.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 11:47:14 +03:30
soroush.asadi 60141b78f0 fix: cropper modal visible on load — add .cropper-overlay.hidden CSS rule
CI/CD / CI · dotnet build (push) Successful in 38s
CI/CD / Deploy · drsousan (push) Successful in 2m52s
The .hidden class only covered .modal-overlay and .fm-overlay.
Without the rule, display:flex on .cropper-overlay overrode .hidden
and the modal showed immediately on every page load.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 11:22:46 +03:30
soroush.asadi b3467fb663 feat: image cropper in admin + fix ba-label responsive centering
CI/CD / CI · dotnet build (push) Successful in 23s
CI/CD / Deploy · drsousan (push) Successful in 41s
- Admin: all upload buttons now open a crop-before-upload modal
  - Canvas-based cropper (no external library)
  - Ratio presets: 1:1, 4:3, 16:9, 3:4, free
  - Drag to move crop box, drag corners to resize
  - Touch support for mobile
  - Crops client-side then uploads the result
- Frontend gallery: ba-label (قبل/بعد) now:
  - Centered horizontally (block + width 100%)
  - Wraps to multiple lines (white-space:normal)
  - Responsive — never overflows or gets clipped

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 11:01:12 +03:30
soroush.asadi 7f5444085b fix: render before/after gallery images from API with tab filtering
CI/CD / CI · dotnet build (push) Successful in 40s
CI/CD / Deploy · drsousan (push) Failing after 52s
- Gallery section now fetches /api/gallery and renders real items
  instead of hardcoded placeholders
- Before+after pairs render as side-by-side split with قبل/بعد labels
- Single imageUrl items render as a standard gallery card
- Tab buttons now filter items by category via data-cat attribute
- CSS added for .before-after, .ba-half, .ba-divider, .ba-label, .gallery-caption
- Fixes applied to correct file (Index.cshtml Razor page, not root index.html)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-01 23:59:57 +03:30
soroush.asadi 14f902cdad fix: replace dotnet healthcheck with curl probe for reliable self-healing
CI/CD / CI · dotnet build (push) Successful in 35s
CI/CD / Deploy · drsousan (push) Successful in 12s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 19:39:04 +03:30
soroush.asadi 56f1311b3b fix: use mirror.soroushasadi.com for base images in Dockerfile
CI/CD / CI · dotnet build (push) Successful in 23s
CI/CD / Deploy · drsousan (push) Successful in 42s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 10:59:23 +03:30
soroush.asadi f15684f7bc fix: keep doctor name on one line in hero section
CI/CD / CI · dotnet build (push) Failing after 0s
CI/CD / Deploy · drsousan (push) Has been skipped
Removed <br> between name parts and added white-space:nowrap.
Adjusted clamp min from 2.2rem to 1.6rem so it scales down on
small screens without wrapping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 09:49:18 +03:30
soroush.asadi 96e73bf633 first commit
CI/CD / CI · dotnet build (push) Failing after 0s
CI/CD / Deploy · drsousan (push) Has been skipped
2026-05-31 00:42:08 +03:30