Files
Plushealthtech/task/02-contact-page.md
T
Clive e5d1446791
Gitea CI/CD / build (push) Successful in 1m40s
Site pages and AI tasks.
2026-08-20 14:58:52 +10:00

53 lines
3.3 KiB
Markdown

# Task 02 — Contact page with MailPit form
- **Status:** Done — 2026-08-20
- **Depends on:** 01
- **Size:** M
## Goal
Create the **Contact** page at `/Contact` with a form that emails its submission to MailPit (`tools.host.domain:1025`, recipient `[email protected]`) via the existing `MailSender`.
## Files
- Create: `plushealthtech/Pages/Contact.cshtml`
- Create: `plushealthtech/Pages/Contact.cshtml.cs`
## Steps
1. **PageModel** (`ContactModel : PageModel`)
- Inject `MailSender` (+ `ILogger<ContactModel>`).
- `[BindProperty]` fields with DataAnnotations:
- `Name` — `[Required]`, `[StringLength(200)]`
- `Email` — `[Required]`, `[EmailAddress]`, `[StringLength(320)]`
- `Organization` — `[StringLength(200)]` (optional)
- `Phone` — `[StringLength(50)]` (optional)
- `Message` — `[Required]`, `[StringLength(5000)]`
- `public string? Success { get; set; }` and `public string? Error { get; set; }` (simple re-render flags).
- `OnGet()` — reset flags.
- `OnPost()`:
- If `!ModelState.IsValid` → return `Page()` (validation messages re-render).
- Else build a plain-text body: one `Field: value` line per non-empty field, blank line, then the message.
- `await _mailSender.SendAsync($"New contact form message — {Model.Name}", body);`
- On success: `Success = "Thanks — your message has been sent. We'll reply to {Email}."` (re-render page with the panel).
- Catch `SmtpException` (or general `Exception`) → log the exception, set `Error` to a generic "Your message could not be sent right now. Please try again or email us directly." — never surface SMTP details to the user.
2. **View** (`Contact.cshtml`)
- `@page`, `@model ContactModel`, `ViewData["Title"] = "Contact"`.
- Layout consistent with the Index page: light hero (heading + one-line intro), then a single form card (`bg-white p-8 rounded-2xl border border-slate-100 shadow-sm`) with the fields, Tailwind classes matching the site's existing inputs (`rounded-xl`, `border-slate-200`, `focus:border-brand` style), a submit button in brand color (`bg-[#1c8098] hover:bg-[#145f72] rounded-xl`).
- `@Html.AntiforgeryToken()` in the form.
- Validation messages per field (`<span asp-validation-for="...">`); `Success` panel (green, replaces/above the form) and `Error` banner (red) rendered when set.
- A short side note block: "We reply to the email address you provide — nothing else is stored."
## Acceptance criteria
- [x] `GET /Contact` renders with all five fields; build green.
- [x] Empty required fields / invalid email → validation messages, no mail sent.
- [x] Valid submit → success panel shown; MailPit shows the message from `[email protected]` to `[email protected]` with subject `New contact form message — {Name}` (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="/Contact"`, which auto-injects `__RequestVerificationToken` — the explicit `@Html.AntiforgeryToken()` from the spec is unnecessary and would duplicate the field.
- SMTP-down path verified by running the app with `Smtp__Port=1` (env override, no config change): banner rendered, `SmtpException (SocketException 10061)` logged, response body clean.