Skip to content

feat: add opportunity type selector to coordinator edit form#755

Closed
nadavosa wants to merge 4 commits into
developfrom
753-opportunity-type-change
Closed

feat: add opportunity type selector to coordinator edit form#755
nadavosa wants to merge 4 commits into
developfrom
753-opportunity-type-change

Conversation

@nadavosa

@nadavosa nadavosa commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

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".

  • Adds a "Change type" action to the OpportunityHeader profile card, opening a dialog (reuses the existing useStatusDialog/ChangeStatusDialog machinery already used for status changes).
  • New useUpdateOpportunityType hook (mirrors useUpdateOpportunityStatus) with its own narrow request type — sends PATCH { volunteerType }, doesn't depend on ApiOpportunityPatch having volunteerType yet, so this isn't blocked on SDK PR landing event page #138 publishing for typecheck purposes.
  • Per-option descriptions in the dialog cover what issue feat: allow changing opportunity type in dashboard profile (accompanying / regular / event) #753 asked for: switching to Accompanying explains that accompanying details need to be added afterward; switching away from Accompanying notes that existing accompanying details stop being used.
  • EN/DE translations added.

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 OpportunityDetails edit form (buried further down the page) instead of the profile header the issue asked for, had a stale isEventType bug (computed from the initial opportunity prop, 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

  1. SDK PR feat: add volunteerType to ApiOpportunityPatch sdk#138 (adds volunteerType to ApiOpportunityPatch) — no longer a hard blocker for this PR's typecheck, since the new PATCH payload type is defined locally, but still needed for be#731 to land without its as unknown as cast.
  2. BE PR feat: allow changing opportunity type via PATCH be#731 (handles the field server-side)

Closes #753

Test plan

  • Open an opportunity in the coordinator dashboard → profile page
  • "Volunteering type" row shows a "Change type" action, same as "Current status"
  • Opening it shows Accompanying / Regular / Events with descriptions
  • Selecting a new type and saving sends PATCH { volunteerType }
  • The header updates to show the new type after saving
  • Both English and German labels/descriptions render correctly
  • yarn typecheck and yarn lint pass

🤖 Generated with Claude Code

nadavosa and others added 3 commits July 2, 2026 16:40
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 ivannissimrch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 nadavosa left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self-review notes from going back through this PR (flagging before it's ready to re-request review, once the conflicts are resolved):

  1. Merge conflicts — GitHub shows this PR as conflicting with develop. Needs a rebase before anyone can review the current diff meaningfully.

  2. useOpportunityTypeDialog.tsinitial: opportunity.volunteerType as OpportunityType casts with no fallback for a missing/undefined volunteerType. Compare with useOpportunityStatusDialog, which normalizes via SDK_TO_MANUAL[status] ?? OpportunityManualStatusType.NEW. OpportunityHeader.tsx itself treats volunteerType as possibly falsy (opportunity.volunteerType ? ... : undefined), so if an opportunity has no type set yet, opening "Change type" would initialize selected to undefined with no option pre-selected — worth adding an explicit fallback for consistency.

  3. BecomeVolunteer.tsx change is unrelated scope — the diff swaps Subpage.DATA_PROTECTIONSubpage.DATA_PRIVACY and 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: allow changing opportunity type in dashboard profile (accompanying / regular / event)

4 participants