From f59c3b216294a788758d23a1954f714064954065 Mon Sep 17 00:00:00 2001 From: arturasmckwcz Date: Fri, 10 Jul 2026 16:48:48 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix:=20create=20opportunity=20bu?= =?UTF-8?q?tton=20silently=20no-ops?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit detailsMethods used createOpportunityDetailsSchema which requires a `title` field, but `title` lives in headerMethods — so detailsMethods validation always failed and handleCreate returned early without calling createOpportunity. Extract createNewOpportunityDetailsSchema (omits `title`) and use it in NewOpportunity so validation only covers fields that form actually owns. Co-Authored-By: Claude Sonnet 4.6 --- .../Dashboard/NewOpportunity/NewOpportunity.tsx | 14 +++++++------- .../OpportunityDetails/opportunityDetailsSchema.ts | 5 +++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/components/Dashboard/NewOpportunity/NewOpportunity.tsx b/src/components/Dashboard/NewOpportunity/NewOpportunity.tsx index c12ab24d..20e145b8 100644 --- a/src/components/Dashboard/NewOpportunity/NewOpportunity.tsx +++ b/src/components/Dashboard/NewOpportunity/NewOpportunity.tsx @@ -10,8 +10,8 @@ import { } from "@/components/Dashboard/Profile/sections/VolunteerProfile/hooks"; import { createMapping } from "@/components/Dashboard/Profile/sections/VolunteerProfile/mappingUtils"; import { - createOpportunityDetailsSchema, - OpportunityDetailsFormData, + createNewOpportunityDetailsSchema, + NewOpportunityDetailsFormData, } from "@/components/Dashboard/Profile/sections/OpportunityDetails/opportunityDetailsSchema"; import { AccompanyingDetailsEdit } from "@/components/Dashboard/Profile/sections/AccompanyingDetails/AccompanyingDetailsEdit"; import { FormDetails } from "@/components/Dashboard/Profile/sections/shared/styles"; @@ -131,7 +131,7 @@ function toOptionItems(ids: string[], apiItems: ApiLanguageOption[]): OptionItem }); } -function availabilityToTimeslots(availability: OpportunityDetailsFormData["availability"]): [number, string][] { +function availabilityToTimeslots(availability: NewOpportunityDetailsFormData["availability"]): [number, string][] { return (availability ?? []).flatMap(({ weekday, timeSlots }) => timeSlots .filter((ts) => ts.selected) @@ -144,7 +144,7 @@ function availabilityToTimeslots(availability: OpportunityDetailsFormData["avail function buildCreatePayload( headerData: HeaderFormData, - detailsData: OpportunityDetailsFormData, + detailsData: NewOpportunityDetailsFormData, accompData: AccompanyingDetailsFormData | null, apiLanguages: ApiLanguageOption[], apiActivities: ApiLanguageOption[], @@ -225,7 +225,7 @@ function OpportunityDetailsFields({ const { control, formState: { errors }, - } = useFormContext(); + } = useFormContext(); const activityMapping = createMapping(apiActivities); const skillMapping = createMapping(apiSkills); @@ -461,8 +461,8 @@ export function NewOpportunity() { const isEvent = selectedType === VolunteerStateTypeType.EVENTS; // Opportunity details form - const detailsMethods = useForm({ - resolver: zodResolver(createOpportunityDetailsSchema(t)), + const detailsMethods = useForm({ + resolver: zodResolver(createNewOpportunityDetailsSchema(t)), mode: "onChange", defaultValues: { description: "", diff --git a/src/components/Dashboard/Profile/sections/OpportunityDetails/opportunityDetailsSchema.ts b/src/components/Dashboard/Profile/sections/OpportunityDetails/opportunityDetailsSchema.ts index add47898..d7a986f3 100644 --- a/src/components/Dashboard/Profile/sections/OpportunityDetails/opportunityDetailsSchema.ts +++ b/src/components/Dashboard/Profile/sections/OpportunityDetails/opportunityDetailsSchema.ts @@ -26,3 +26,8 @@ export const createOpportunityDetailsSchema = (t: (key: string) => string) => }); export type OpportunityDetailsFormData = z.infer>; + +export const createNewOpportunityDetailsSchema = (t: (key: string) => string) => + createOpportunityDetailsSchema(t).omit({ title: true }); + +export type NewOpportunityDetailsFormData = z.infer>;