-
Notifications
You must be signed in to change notification settings - Fork 0
volunteer update api #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| // Add any exports from your API files here | ||
|
|
||
| export { getExample } from "./getExample"; | ||
| export { updateVolunteer } from "./updateVolunteer"; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,295 @@ | ||||||
| import { createClient } from "../client/supabase/server"; | ||||||
| import type { Tables, TablesUpdate } from "../client/supabase/types"; | ||||||
|
|
||||||
| const ROLE_TYPES = ["prior", "current", "future_interest"] as const; | ||||||
| const COHORT_TERMS = ["fall", "summer", "winter", "spring"] as const; | ||||||
|
|
||||||
| type VolunteerUpdatePayload = Pick< | ||||||
| TablesUpdate<"Volunteers">, | ||||||
| | "name_org" | ||||||
| | "email" | ||||||
| | "phone" | ||||||
| | "pronouns" | ||||||
| | "pseudonym" | ||||||
| | "position" | ||||||
| | "notes" | ||||||
| | "opt_in_communication" | ||||||
| >; | ||||||
|
|
||||||
| type RoleInput = { name: string; type: (typeof ROLE_TYPES)[number] }; | ||||||
| type CohortInput = { year: number; term: (typeof COHORT_TERMS)[number] }; | ||||||
|
|
||||||
| type UpdateVolunteerResult = | ||||||
| | { status: 200; body: { volunteer: Tables<"Volunteers"> } } | ||||||
| | { status: 400 | 404 | 500; body: { error: string } }; | ||||||
|
|
||||||
| type VolunteerValidationResult = { | ||||||
| updates?: Partial<VolunteerUpdatePayload>; | ||||||
| role?: RoleInput; | ||||||
| cohort?: CohortInput; | ||||||
| error?: string; | ||||||
| }; | ||||||
|
|
||||||
| // keep this in sync with allowed patch fields on the volunteers table | ||||||
| const ALLOWED_VOLUNTEER_FIELDS = new Set<keyof VolunteerUpdatePayload>([ | ||||||
| "name_org", | ||||||
| "email", | ||||||
| "phone", | ||||||
| "pronouns", | ||||||
| "pseudonym", | ||||||
| "position", | ||||||
| "notes", | ||||||
| "opt_in_communication", | ||||||
| ]); | ||||||
| const ALLOWED_TOP_LEVEL_FIELDS = new Set<string>([ | ||||||
| ...ALLOWED_VOLUNTEER_FIELDS, | ||||||
| "role", | ||||||
| "cohort", | ||||||
| ]); | ||||||
|
|
||||||
| function validateVolunteerUpdateBody(body: unknown): VolunteerValidationResult { | ||||||
| if (!body || typeof body !== "object" || Array.isArray(body)) { | ||||||
| return { error: "Request body must be a JSON object" }; | ||||||
| } | ||||||
|
|
||||||
| const payload = body as Record<string, unknown>; | ||||||
| const unknownKeys = Object.keys(payload).filter( | ||||||
| (key) => !ALLOWED_TOP_LEVEL_FIELDS.has(key) | ||||||
| ); | ||||||
|
|
||||||
| if (unknownKeys.length > 0) { | ||||||
| return { | ||||||
| error: `Unknown field(s): ${unknownKeys.join(", ")}`, | ||||||
| }; | ||||||
| } | ||||||
|
|
||||||
| // name_org is the only required patchable field; validate it eagerly | ||||||
| const updates: Partial<VolunteerUpdatePayload> = {}; | ||||||
| if ("name_org" in payload) { | ||||||
| const value = payload["name_org"]; | ||||||
| if (value === null || value === undefined) { | ||||||
| return { error: "Field name_org must be provided as a non-empty string" }; | ||||||
|
||||||
| return { error: "Field name_org must be provided as a non-empty string" }; | |
| return { error: "Field name_org cannot be null or undefined" }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When updating a row in the Volunteers table, we need to set the
updated_atfield to the timestamp of the update.