Skip to content

feat: rework new opportunity page to match profile edit layout#693

Merged
need4deed merged 8 commits into
developfrom
feat/445-new-opportunity-profile-layout
Jun 17, 2026
Merged

feat: rework new opportunity page to match profile edit layout#693
need4deed merged 8 commits into
developfrom
feat/445-new-opportunity-profile-layout

Conversation

@nadavosa

Copy link
Copy Markdown
Collaborator

Summary

  • Replaces the simple card form with the same PageContainer + SectionCard layout used by the opportunity profile page
  • Title is presented in a Wrench section card (same as Opportunity Details on the profile)
  • Contact details are in a ChatsCircle section card, always in edit mode, pre-filled from the current agent's representative
  • Validation uses zod + react-hook-form with the same phone regex and email rules as opportunityContactDetailsSchema
  • Save POSTs { title, contact: { name, phone, email }, agentId } to POST /api/opportunity/ and redirects to the new opportunity's profile on success

Closes #445

Test plan

  • Log in as an agent; click "New Opportunity" from the dashboard
  • Verify the page uses the profile-style section card layout (not the old card form)
  • Verify contact name/phone/email are pre-filled from the logged-in agent's representative
  • Verify title is empty and required; submit without it shows validation error
  • Verify phone/email validation works the same as on the opportunity profile contact section
  • Fill in all fields and submit; confirm redirect to the new opportunity's profile page

🤖 Generated with Claude Code

nadavosa and others added 5 commits June 17, 2026 11:21
Replaces the simple card form with the same ProfilePage section-card
layout used by the opportunity profile. Title and contact details are
presented as SectionCards in edit mode; contact fields are pre-filled
from the current agent's representative on load (keepDirtyValues so
manual edits are not overwritten). Validation uses zod + react-hook-form
with the same phone/email rules as the opportunity contact details schema.
Save POSTs to /api/opportunity/ and redirects to the new opportunity's
profile page on success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contact details are removed from the creation form; the BE will derive
them from the agentId + authenticated user once the SDK/BE support is ready.
Form now just takes a title, POSTs { title, agentId } and redirects to the
new opportunity's profile on success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds:
- Volunteer type toggle (Regular / Accompanying / Event) in the header
  card at the top of the creation form, styled to match the profile
  header's StatusRowField layout; the selected type controls which
  sections appear below.
- Opportunity Details section (description, languages, availability grid
  for Regular, event date+time for Events, activities, skills,
  number of volunteers) — always shown, always in edit mode.
- Accompanying Details section (address, postcode, date, time, refugee
  info, appointment language) — shown only when Accompanying is selected.
- Create flow: POST { title, volunteerType, agentId } then immediately
  PATCH the opportunity details and (if applicable) accompanying details
  using the returned ID, then redirect to the new opportunity's profile.
- Contact details section will follow once the SDK/BE propagates them
  from agentId + authenticated user.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Upgrades need4deed-sdk to v0.0.108 which adds OpportunityFormDataWithAgentSubmitter
- Replaces the two-step create+PATCH flow with a single POST using the new
  SDK type; all form data (title, type, details, availability, accompanying)
  is sent in one request to POST /api/opportunity/
- Adds availabilityToTimeslots helper to convert the AvailabilityGrid format
  to the [weekday, slotId][] timeslots format the new endpoint expects
- Fixes OpportunityTableRow: volunteerNames removed from ApiVolunteerOpportunityGetList
  in v0.0.108; falls back to showing numberOfVolunteers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Upgrade need4deed-sdk to 0.0.109; fix buildCreatePayload for new
  OpportunityLegacyFormDataProps shape (string[] ids, language field,
  opportunity_type "accompanying"|"volunteering" mapping)
- After new opportunity creation redirect to dashboard home instead of
  opportunity profile
- Agent (NGO) home page now shows only their linked opportunities as
  cards plus the create-opportunity button; all other sections (newest
  volunteers, tagged comments, newest opportunities) are coordinator/
  admin only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

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

Review

Overall the approach is solid — three-form aggregation, profile-style layout, role-aware home page, correct SDK upgrade path. A few things worth addressing before merge:

Issues:

  1. AccompanyingDetailsEdit no-op handlers (NewOpportunity.tsx ~line 823): onCancel={() => {}} and onSubmit={() => {}} mean the Cancel and Submit buttons inside that component render and are clickable but do nothing. The agent will click them expecting something to happen. Either suppress those buttons (if AccompanyingDetailsEdit supports that) or document that submission is driven by the outer Create button only.

  2. Empty state missing in AgentOpportunityCards: When opportunities is an empty array (a freshly registered agent with no opportunities yet), the component renders nothing — no message. Add a simple empty-state string so the home page isn't just a button with a blank area below it.

  3. category / category_id sent as "" (buildCreatePayload): These are required fields in OpportunityFormDataWithAgentSubmitter and we're sending empty strings. If the BE rejects blank values here a creation attempt will silently fail. Worth confirming with BE what the correct sentinel is (null? omit entirely? a real default?).

Minor notes:

  • keyToLabel / labelToKey maps are rebuilt on every render in the component body — should be useMemo(() => ..., [apiLanguages]) since they only change when apiLanguages changes.
  • opportunity_type: isAccompanying ? "accompanying" : "volunteering" — events map to "volunteering". The SDK type only has two values so this is correct, but it's worth a short comment that the BE distinguishes events from regular via onetime_date_time.
  • useGetCurrentAgent in AgentOpportunityCards fires two requests (/me/agent/{id}) when we only need the agentId from /me. Not a blocker but a minor over-fetch.

nadavosa and others added 3 commits June 17, 2026 12:09
…tion form

Add hideButtons prop to AccompanyingDetailsEdit; pass it from NewOpportunity
so only the outer Create button drives submission.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@need4deed need4deed merged commit 1dfbebb into develop Jun 17, 2026
1 check passed
@need4deed need4deed deleted the feat/445-new-opportunity-profile-layout branch June 17, 2026 10:11
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: agent can publish an opportunity within the app

2 participants