docs: add agenda estimated-time field design spec

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-07 16:12:19 +08:00
parent 96453ae197
commit 7bd27153ab

View File

@@ -0,0 +1,82 @@
# Agenda Estimated Time Field — Design Spec
**Date:** 2026-05-07
**Status:** Approved
## Problem
The agenda submission form has no way for attendees to indicate how long their session will take. The backend has no dedicated field for this, so the value must live inside the description.
## Goal
Add a required "Estimated Time (minutes)" number input to the agenda **submit** form. Before sending to the backend, append the value as plain Chinese text to the end of the description. The edit form is unchanged.
## Approach
Separate submit schema (Option A): a new `agendaSubmitSchema` extends the existing `agendaItemSchema` with an `estimatedTime` field. The `submitAgenda` server action uses this schema and handles concatenation. The `editAgenda` action and its schema are untouched.
## Schema changes
**File:** `src/lib/schemas/agenda.ts`
Add alongside `agendaItemSchema`:
```ts
export const agendaSubmitSchema = agendaItemSchema.extend({
estimatedTime: z.coerce.number().int().min(1, '请填写预计时间').max(999, '时间最多 999 分钟')
});
export type AgendaSubmitSchema = typeof agendaSubmitSchema;
```
## Server action changes
**File:** `src/routes/(app)/events/[eventId]/+page.server.ts`
`submitAgenda` action:
- Validate with `superValidate(request, zod(agendaSubmitSchema))`
- After validation, build the full description before base64-encoding:
```ts
const fullDescription = `${fd.description}\n\n预计时间${fd.estimatedTime} 分钟`;
description: Buffer.from(fullDescription).toString('base64')
```
- All other logic (blocking rules, pending limit, API call) is unchanged.
`editAgenda` action: no changes — continues to use `agendaItemSchema`.
## UI changes
**Files:** `src/lib/components/AgendaDialog.svelte`, `src/lib/components/AgendaMyList.svelte`, `src/routes/(app)/events/[eventId]/+page.server.ts`
Both submit and edit dialogs receive the same `agendaForm` instance from `load` (via `AgendaMyList`). Since `agendaSubmitSchema` is a superset of `agendaItemSchema`, the single form is initialised with `agendaSubmitSchema`. The `editAgenda` action reads only `agenda_id`/`name`/`description` from raw `FormData` and is unaffected by the extra field.
**`+page.server.ts` (load):**
- `agendaForm` is initialised with `submitSchema` and typed as `SuperValidated<AgendaSubmitFormData>`.
**`AgendaMyList.svelte`:**
- `formData` prop type changes from `SuperValidated<AgendaItemFormData>` to `SuperValidated<AgendaSubmitFormData>`.
**`AgendaDialog.svelte`:**
- `formData` prop type changes from `SuperValidated<AgendaItemFormData>` to `SuperValidated<AgendaSubmitFormData>`.
- A number input is rendered below the description field, **only when `mode === 'submit'`**:
- Label: `预计时间(分钟)`
- `type="number"`, `min="1"`, `max="999"`, `name="estimatedTime"`
- Bound to `$form.estimatedTime`
- Inline error via `$errors.estimatedTime`
## Display
The appended text becomes a new Markdown paragraph (blank line separator `\n\n`) rendered by the existing `marked` pipeline. No display-layer changes are needed.
Example stored description (decoded):
```
这是我的议程描述。
预计时间30 分钟
```
## Out of scope
- Edit mode: no parsing of existing estimated time, no display as a separate field
- Admin agenda pages: no changes
- Any changes to how decoded descriptions render