Site pages and AI tasks.
Gitea CI/CD / build (push) Successful in 1m40s

This commit is contained in:
Clive
2026-08-20 14:58:52 +10:00
parent 152a998311
commit e5d1446791
51 changed files with 2876 additions and 30 deletions
+47
View File
@@ -0,0 +1,47 @@
# Task 03 — Request Demo page with MailPit form
- **Status:** Done — 2026-08-20
- **Depends on:** 01
- **Size:** M
## Goal
Create the **Request Demo** page at `/RequestDemo` with a form that emails its submission to MailPit (`tools.host.domain:1025`, recipient `[email protected]`) via the existing `MailSender`. Same send/success/error pattern as the Contact page (Task 02).
## Files
- Create: `plushealthtech/Pages/RequestDemo.cshtml`
- Create: `plushealthtech/Pages/RequestDemo.cshtml.cs`
## Steps
1. **PageModel** (`RequestDemoModel : PageModel`)
- Inject `MailSender` (+ logger).
- `[BindProperty]` fields with DataAnnotations:
- `Name` — `[Required]`, `[StringLength(200)]`
- `Email` — `[Required]`, `[EmailAddress]`, `[StringLength(320)]`
- `Organization` — `[Required]`, `[StringLength(200)]`
- `PracticeType` — select: Healthcare system, Hospital, Clinic, Veterinary practice, Other (optional)
- `ProductsOfInterest` — select: Clinical Decision Support, Patient Management, Veterinary Solutions, Multiple / not sure (optional)
- `Message` — `[StringLength(5000)]` (optional)
- `Success` / `Error` flags, `OnGet` reset.
- `OnPost()` same contract as Task 02: validate → build plain-text `Field: value` body → `SendAsync($"New demo request — {Organization}", body)` → success flag; SMTP failure → generic error banner + log.
2. **View** (`RequestDemo.cshtml`)
- `@page`, `@model RequestDemoModel`, `ViewData["Title"] = "Request Demo"`.
- Marketing-flavored hero (one-line value prop, 2–3 trust bullets like "FHIR®-ready" / "24/7 clinical support" — reuse Index hero metrics) + the form card, Tailwind styling consistent with the site.
- `@Html.AntiforgeryToken()`, per-field validation spans, success/error rendering identical in behavior to Contact.
- Close with a secondary CTA: "Prefer to talk? Visit the Contact page." → `/Contact`.
## Acceptance criteria
- [x] `GET /RequestDemo` renders; build green.
- [x] Required fields enforced; selects render all options.
- [x] Valid submit → success panel shown; MailPit shows the message from `[email protected]` to `[email protected]` with subject `New demo request — {Organization}` (e2e verified 2026-08-20, ahead of Task 13).
- [x] With MailPit down → friendly error banner, exception in app log, no stack trace in the browser.
## Notes
- Antiforgery: the form uses `asp-page="/RequestDemo"`, which auto-injects `__RequestVerificationToken` — the explicit `@Html.AntiforgeryToken()` from the spec is unnecessary and would duplicate the field (same approach as the Contact page).
- SMTP-down path verified by running the app with `Smtp__Host=127.0.0.1 Smtp__Port=1` (env override, no config change): banner rendered, `SmtpException (SocketException 10061)` logged with sender context, response body clean.
- Validation confirmed over HTTP: empty POST → "required" messages on Name/Email/Organization only; bad email → "not a valid e-mail address"; both selects render their full option lists with a placeholder.