Context
The applicant-facing offer letter and status copy are effectively uneditable by admins: the offer letter lives in raw form config JSON (edited via SQL every season), and most other decision screens are hardcoded in components. Settings shows a preview but has no editor.
Current behavior
- Offer letter:
config.application.pages.offerPage.content rendered by offerPage.tsx with {{...}} templating over app details + lpContext (teams etc.). No editor anywhere; settings preview only renders it.
- Status labels/descriptions:
config.application.status[] — labels feed pickers; description has no consumer; no editor.
- Hardcoded screens (not even SQL-editable): rejected/closed/submitted copy in
MainResultPage.tsx/GenericResult, accepted text in acceptedResult.tsx, submitted celebration in submittedResult.tsx, pending in pendingResult.tsx, decline text in offerPage.tsx.
- Unknown statuses render the raw status id string to the applicant.
Desired behavior
- Editor (natural home: Settings) for the offer-page content and per-status applicant-facing message, with live preview using the existing per-app preview picker.
- Move hardcoded decision copy into per-status config with component defaults as fallback (so unconfigured forms behave exactly as today).
- Support the existing
{{tag}} substitution in edited copy; preview reflects substitutions with a chosen applicant.
Acceptance criteria
Context
The applicant-facing offer letter and status copy are effectively uneditable by admins: the offer letter lives in raw form
configJSON (edited via SQL every season), and most other decision screens are hardcoded in components. Settings shows a preview but has no editor.Current behavior
config.application.pages.offerPage.contentrendered byofferPage.tsxwith{{...}}templating over app details +lpContext(teams etc.). No editor anywhere; settings preview only renders it.config.application.status[]— labels feed pickers;descriptionhas no consumer; no editor.MainResultPage.tsx/GenericResult, accepted text inacceptedResult.tsx, submitted celebration insubmittedResult.tsx, pending inpendingResult.tsx, decline text inofferPage.tsx.Desired behavior
{{tag}}substitution in edited copy; preview reflects substitutions with a chosen applicant.Acceptance criteria