Skip to content

feat(revamp): Block C — funding signal (closes #42)#54

Merged
sacha-l merged 1 commit intodevelopfrom
revamp/block-c-funding-signal
Apr 23, 2026
Merged

feat(revamp): Block C — funding signal (closes #42)#54
sacha-l merged 1 commit intodevelopfrom
revamp/block-c-funding-signal

Conversation

@sacha-l
Copy link
Copy Markdown
Collaborator

@sacha-l sacha-l commented Apr 22, 2026

Block C of the Phase 1 revamp — single issue. Teams can declare they're looking for funding.

Closes #42.

Journey slice (per spec §12)

"I can flag that we're looking for a grant." Team member opens project → Overview tab → clicks Edit → toggles is_seeking, picks type + amount range + short description → signs SIWS → "Looking for a grant · 30k–60k USD" badge renders on the Overview.

Summary

Schema + API + UI shipped together in one commit since all three layers are small and the feature doesn't make sense without all of them.

  • Schema. New project_funding_signals table — 1:1 with projects but stored as a separate table so future history tracking doesn't need another migration. CHECK on funding_type enum (grant | bounty | pre_seed | seed | other), description length ≤ 500, partial index on is_seeking = true.
  • API. GET /api/m2-program/:id/funding-signal (public, returns a default no-signal shape when no row exists). PATCH same path gated by requireTeamMemberOrAdmin. SIWS statement Update funding signal for <project> on Stadium added to the valid statement list.
  • UI. FundingSignalBadge renders when isSeeking=true; EditFundingSignalModal with switch, select, inline-validated fields, SIWS sign + PATCH. Both rendered on the Overview tab of the project detail page.
  • Mock fixtures. Plata Mia (grant, 30k–60k USD) and Kleo Protocol (seed, 200k-500k USD) pre-seeded so preview mode shows the populated badge state.

Test plan

Automated:

  • cd server && npm test → 29/29 (7 new + 22 existing).
  • cd client && npm run build → clean.

Playwright (auto-verifiable):

  • On /m2-program/plata-mia-15ac43, Overview tab shows a "Looking for a grant · 30k–60k USD" badge.
  • On a project without a seeded signal, Overview tab shows no badge and no edit-funding-signal affordance (for un-authenticated visitors).
  • GET /api/m2-program/<any-project-id>/funding-signal returns { data: { isSeeking: false, ... } } when no row exists.
  • GET /api/m2-program/plata-mia-15ac43/funding-signal returns the seeded signal with isSeeking: true, fundingType: "grant".

Manual SIWS QA:

  • Connect team-member wallet → "Set funding signal" / "Edit funding signal" button appears → modal → set is_seeking = true, type = grant, amountRange = "30k–60k USD", description = "looking for grant" → sign → badge appears on Overview without page reload.
  • Description > 500 chars → inline error; no network call.
  • Toggle is_seeking OFF → save → badge disappears (row updated with is_seeking = false, previous metadata retained on server).
  • Non-team-member wallet → edit button hidden.
  • Admin wallet on a project they're not a member of → edit button visible (admins can edit).

Out of scope (per spec)

  • Partner-side "who sees this / matching" (Phase 2+).
  • History / audit log of changes (the table-not-column design enables this later; no UI now).
  • Notifications on state change (Phase 2+).

Schema note

The partial index WHERE is_seeking = TRUE is intentional — most projects won't have a signal at all, and the common query is "list projects currently seeking", so an index on that predicate only is lean. Can be removed if query shapes evolve.

@sacha-l sacha-l added enhancement New feature or request revamp-phase-1 Stadium Phase 1 revamp — programs, updates, funding signals, applications labels Apr 22, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stadium Ready Ready Preview, Comment Apr 23, 2026 7:38am

Block C of the Phase 1 revamp. Teams can declare they're looking for
funding (grant / bounty / pre-seed / seed / other) with an optional
amount range and short description. One row per project, updated in
place. Partner-side discovery is deliberately out of scope.

Phase 1 revamp Block C (single-issue block), issue #42.
See docs/stadium-revamp-phase-1-spec.md §4.4 and §5 Issue 7.

Server:
- supabase/migrations/20260422020000_create_project_funding_signals.sql
  — one-row-per-project table with CHECK on funding_type enum and
  description length ≤ 500; partial index on is_seeking = true.
- server/api/repositories/funding-signal.repository.js —
  getByProject + upsert (by project_id).
- server/api/services/funding-signal.service.js — thin wrap.
- server/api/controllers/project.controller.js — getFundingSignal
  (public, 404 on unknown project, default shape when no row),
  updateFundingSignal (requireTeamMemberOrAdmin, trims inputs, 422
  on validation failure).
- server/api/routes/m2-program.routes.js — GET + PATCH endpoints.
- server/api/utils/validation.js — validateFundingSignal +
  ALLOWED_FUNDING_TYPES constant.
- server/api/middleware/auth.middleware.js — adds SIWS statement
  + regex pattern for "Update funding signal for <project> on Stadium".
- 7 new unit tests covering GET 404/default/hit and PATCH
  404/invalid-type/too-long-description/happy-path/clear-toggle.

Client:
- client/src/lib/api.ts — ApiFundingSignal type +
  api.getFundingSignal + api.updateFundingSignal with mock-mode
  fallbacks.
- client/src/lib/mockFundingSignals.ts (new) — seeded for Plata Mia
  and Kleo Protocol so the badge renders in preview mode.
- client/src/lib/siwsUtils.ts — new 'update-funding-signal' action
  producing the statement that matches the server-side regex.
- client/src/components/project/FundingSignalBadge.tsx (new) —
  renders a small "Looking for <type> · <amount>" badge + optional
  description when is_seeking = true; null when not.
- client/src/components/project/EditFundingSignalModal.tsx (new) —
  Switch for is_seeking, Select for type, inline-validated fields
  (amount range ≤ 100 chars, description ≤ 500), SIWS sign + PATCH.
- client/src/pages/ProjectDetailsPage.tsx — fetches funding signal
  alongside the project; renders badge + edit affordance at the top
  of the Overview tab; mounts the modal.

Validation strategy (per spec §10):
- Description bound (500) identical on client and server.
- funding_type enum identical on client and server.
- isSeeking is boolean-coerced server-side.

Verification:
- server/npm test: 29/29 passing (7 new + 22 existing).
- client/npm run build: clean (pre-existing warnings only).
@sacha-l sacha-l force-pushed the revamp/block-c-funding-signal branch from e18947f to 3511ac9 Compare April 23, 2026 07:38
@sacha-l sacha-l marked this pull request as ready for review April 23, 2026 07:52
@sacha-l sacha-l merged commit c4250b7 into develop Apr 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request revamp-phase-1 Stadium Phase 1 revamp — programs, updates, funding signals, applications

Projects

None yet

Development

Successfully merging this pull request may close these issues.

revamp-P1-07: funding signal — data model + API + UI

1 participant