Commit Graph

30 Commits

Author SHA1 Message Date
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 6f39e47aaa ci: backup DB before every deploy, fix deploy conflict error
CI/CD / CI · dotnet build (push) Successful in 25s
CI/CD / Deploy · drsousan (push) Successful in 12s
- Add "Backup database" step that copies drsousan.db out of the
  running container to /opt/drsousan-backups/ before any container
  changes, keeping the last 10 backups
- Replace --force-recreate (broken on this Docker version) with
  explicit docker stop + docker rm before docker compose up

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 08:22:34 +03:30
soroush.asadi e4ad440c15 fix(ci): stop & remove old container before deploying new one
CI/CD / CI · dotnet build (push) Successful in 24s
CI/CD / Deploy · drsousan (push) Successful in 12s
docker compose up --force-recreate only works when Compose owns the
container. If the container was started outside Compose (e.g. manually
via docker restart), Compose can't recreate it and errors with
"container name already in use". Explicitly stopping and removing it
first handles both cases cleanly.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 01:59:16 +03:30
soroush.asadi dd5afde5df fix: add --force-recreate to docker compose deploy step
CI/CD / CI · dotnet build (push) Successful in 23s
CI/CD / Deploy · drsousan (push) Failing after 2s
Without this flag, the deploy fails with "container name already in use"
when a container with the same name exists from a previous run.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 00:04:14 +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 f034f70ae3 fix: lock compose project name to 'drsousan', fix mirrors typo in image ref
CI/CD / CI · dotnet build (push) Successful in 3m21s
CI/CD / Deploy · drsousan (push) Failing after 2s
Prevents runner workspace directory name from being used as project name,
which caused Meezi containers to be treated as orphans and stopped on deploy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 23:41:20 +03:30
soroush.asadi 8fa3131344 ci: scope image prune to drsousan only, never touch other projects
CI/CD / CI · dotnet build (push) Successful in 23s
CI/CD / Deploy · drsousan (push) Successful in 12s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 23:37:06 +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 d5bb724b3f fix:multiline header
CI/CD / CI · dotnet build (push) Successful in 33s
CI/CD / Deploy · drsousan (push) Successful in 12s
2026-05-31 11:01:36 +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 deb37f6935 PLZ 4
CI/CD / CI · dotnet build (push) Successful in 23s
CI/CD / Deploy · drsousan (push) Failing after 1s
2026-05-31 10:56:26 +03:30
soroush.asadi 15dc1189b4 ci: remove Nexus push step, build image locally only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 10:55:28 +03:30
soroush.asadi 07e37fd7c5 plz 2
CI/CD / CI · dotnet build (push) Successful in 42s
CI/CD / Deploy · drsousan (push) Failing after 0s
2026-05-31 10:44:09 +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 0b3ba2875c plz
CI/CD / CI · dotnet build (push) Failing after 1m12s
CI/CD / Deploy · drsousan (push) Has been skipped
2026-05-31 09:44:08 +03:30
soroush.asadi 097f5c2733 g
CI/CD / CI · dotnet build (push) Failing after 1s
CI/CD / Deploy · drsousan (push) Has been skipped
2026-05-31 00:48:51 +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