feat: add opportunity type selector to coordinator edit form#755
feat: add opportunity type selector to coordinator edit form#755nadavosa wants to merge 4 commits into
Conversation
Swaps /{path}/{lang} to /{lang}/{path} and replaces Subpage.DATA_PROTECTION
("data-protection") with Subpage.DATA_PRIVACY ("data-privacy") so both links
resolve to existing pages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Coordinators can now change the type of an opportunity (accompanying / regular / events) from the dashboard's opportunity detail edit form. - Adds volunteerType field to OpportunityDetailsFormData schema - Adds radio-list dropdown in OpportunityDetailsEdit to pick type - Shows current type in read mode in OpportunityDetailsDisplay - Adds en/de translation keys for the three type labels Depends on SDK PR need4deed-org/sdk#138 and BE PR need4deed-org/be#731. Closes #753 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ng status Issue #753 asked for changing the opportunity type "from the opportunity profile page" — the previous commit added it to a buried OpportunityDetails edit form instead, and skipped the accompanying-transition messaging the issue calls for. - Reverts the volunteerType additions to OpportunityDetailsEdit/Display and their schema (isEventType there was also stale w.r.t. the new selector, since it read the original opportunity prop rather than the live field). - Adds a "Change type" action next to "Volunteering type" in OpportunityHeader, reusing the same useStatusDialog/ChangeStatusDialog machinery as "Change status" — no new dialog primitives. - Dedicated useUpdateOpportunityType hook (mirrors useUpdateOpportunityStatus) with its own narrow payload type, so this isn't blocked on SDK PR #138 publishing ApiOpportunityPatch.volunteerType. - Per-option descriptions in the dialog cover the accompanying transitions the issue calls for (prompt to add accompanying details when switching to Accompanying; note that existing accompanying details stop being used when switching away) without adding new form fields.
ivannissimrch
left a comment
There was a problem hiding this comment.
Tested on dev.need4deed.org as admin (opp 821). The dialog works and the PATCH fires to /opportunity/821 with volunteerType, but the change doesn't persist PATCH returns 204 and the refetch still shows the old type. So the BE accepts the request but isn't applying volunteerType yet (be#731 not deployed on dev). FE looks correct can't verify the save end-to-end until be#731 lands.
Minor: the success toast shows even when nothing changed (BE returns 204) should resolve once the handler's in, but worth a glance later.
| <a href={`/${lng}/${Subpage.DATA_PRIVACY}`}>{t("homepage.footer.legal.dataPrivacy")}</a>{" "} | ||
| {t("form.becomeVolunteer.fields.consent.and")}{" "} | ||
| <a href={`/${Subpage.AGREEMENT}/${lng}`}>{t("homepage.footer.legal.agreement")}</a> | ||
| <a href={`/${lng}/${Subpage.AGREEMENT}`}>{t("homepage.footer.legal.agreement")}</a> |
There was a problem hiding this comment.
line 435 and 437 lngis undefined here (the route param islang, not lng), so these render /undefined/data-privacy`. #752 already fixes this by dropping the lang segment might be cleanest to drop these from this PR so the two don't conflict?
nadavosa
left a comment
There was a problem hiding this comment.
Self-review notes from going back through this PR (flagging before it's ready to re-request review, once the conflicts are resolved):
-
Merge conflicts — GitHub shows this PR as conflicting with
develop. Needs a rebase before anyone can review the current diff meaningfully. -
useOpportunityTypeDialog.ts—initial: opportunity.volunteerType as OpportunityTypecasts with no fallback for a missing/undefinedvolunteerType. Compare withuseOpportunityStatusDialog, which normalizes viaSDK_TO_MANUAL[status] ?? OpportunityManualStatusType.NEW.OpportunityHeader.tsxitself treatsvolunteerTypeas possibly falsy (opportunity.volunteerType ? ... : undefined), so if an opportunity has no type set yet, opening "Change type" would initializeselectedtoundefinedwith no option pre-selected — worth adding an explicit fallback for consistency. -
BecomeVolunteer.tsxchange is unrelated scope — the diff swapsSubpage.DATA_PROTECTION→Subpage.DATA_PRIVACYand reorders the URL segments for the consent links. I checked against the actual routes (src/app/[lang]/(static_pages)/data-privacy,.../agreement) and the new code is correct — the old code was pointing at a mismatched path. So this looks like a legitimate fix, just completely unrelated to the opportunity-type feature and not mentioned in the PR description. Worth calling out explicitly (or splitting into its own PR) so it doesn't get lost/attributed to the wrong change.
Summary
Coordinators (and admins) can change an opportunity's type directly from the opportunity profile page, next to "Volunteering type" — same pattern as "Change status".
OpportunityHeaderprofile card, opening a dialog (reuses the existinguseStatusDialog/ChangeStatusDialogmachinery already used for status changes).useUpdateOpportunityTypehook (mirrorsuseUpdateOpportunityStatus) with its own narrow request type — sendsPATCH { volunteerType }, doesn't depend onApiOpportunityPatchhavingvolunteerTypeyet, so this isn't blocked on SDK PR landing event page #138 publishing for typecheck purposes.Not added: new form fields for accompanying details — coordinators fill those in via the existing Accompanying Details section, as today.
Revision history
Original version of this PR added the type selector to the
OpportunityDetailsedit form (buried further down the page) instead of the profile header the issue asked for, had a staleisEventTypebug (computed from the initialopportunityprop, not the live form value, so switching type mid-edit didn't switch the rest of the form), and didn't cover the accompanying-transition behavior. Reworked per review.Dependencies
volunteerTypetoApiOpportunityPatch) — no longer a hard blocker for this PR's typecheck, since the new PATCH payload type is defined locally, but still needed forbe#731to land without itsas unknown ascast.Closes #753
Test plan
PATCH { volunteerType }yarn typecheckandyarn lintpass🤖 Generated with Claude Code