Commit ef423a2
Enhance bounty features with new UI, data layers, and crowdfunding support (#663)
* feat: integrate treasury management features and refactor hackathon orchestration and API client architecture.
* chore: update package-lock.json dependencies
* chore: update pre-push husky hook to perform full type-checks and production builds
* refactor: remove DevelopmentStatusModal from global layout
* feat: task-first Winners page, judging UX, private access, treasury receipts/send
Winners: new task-first Winners section (pick winner per prize with engine default, inline stacking confirm, deliberate 'Don't award' + unawarded-funds acknowledgement); /rewards redirects to /winners; staged Pick -> Confirm -> Pay.
Judging: slimmed Results tab to read-only standings + 'Go to Winners'; criterionId name fix; AI scorecards, recommendation thresholds, CSV judge import, tracks + custom questions wizard sections; validation + empty-state polish.
Public: private + password access gate, community links, card private badge. Treasury: receipts + Send funds. Removed the stacking toggle from prize setup.
* feat(bounty): ModeTab + SubmissionModelTab for the Configure wizard (#599) (#611)
The net-new bounty UI with no hackathon analog: the two-axis mode picker and
the mode-conditional submission settings that drive all six combinations.
- modeSchema.ts: plain taxonomy unions (entryType x claimType), the
computeBountyModeLabel helper, and getModeFields — the mode -> field matrix
derived functionally from the publish gate (validateTwoAxisMode) so it cannot
drift from the backend.
- submissionModelSchema.ts: makeSubmissionModelSchema(mode), a mode-aware Zod
factory whose required fields and the >=2 floors (maxApplicants for open
competition, shortlistSize for application competition) mirror the server gate.
- ModeTab.tsx: entry x claim picker, a winners stepper (1-3) for competitions,
and a live computed mode label.
- SubmissionModelTab.tsx: renders each field per the matrix (required / optional
/ hidden) and shows submissionVisibility read-only, forced by the mode
(HIDDEN_UNTIL_DEADLINE for competitions).
Standalone components (props: mode, onSave, onContinue, initialData, isLoading);
they wire into the wizard shell + routes in #597 / #598.
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596) (#612)
Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.
- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
cancel / select-winners / submit-signed / poll) plus useEscrowOp +
useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.
Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.
* feat(bounty): wizard shell + step/draft machinery (#598) (#613)
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)
Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.
- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
cancel / select-winners / submit-signed / poll) plus useEscrowOp +
useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.
Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.
* feat(bounty): wizard shell + step/draft machinery (#598)
Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.
- components/organization/bounties/new/constants.ts: StepKey
(scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
resume via useDraft, and transformBountyFromApi (sections -> form state;
winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
steps + draft + per-step save, persisting ?draftId= for resume, and threading
the chosen mode from ModeTab into SubmissionModelTab.
Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.
* feat(bounty): Scope + Reward + Review tabs and Zod schemas (#600) (#614)
Completes the editable surface of the bounty Configure wizard, dropping the
three remaining tabs into the seams the shell (#598) left.
- tabs/schemas/scopeSchema.ts: title, description, optional GitHub issue
url/number, optional project/window.
- tabs/schemas/rewardSchema.ts: makeRewardSchema(claimType) — exactly one tier
for single claim, 1-3 for a competition; amounts > 0, unique positions
including position 1 (mirrors the publish gate's deriveWinnerDistribution).
- lib/utils/bounty-escrow.ts: adapts the bounty reward shape to reuse the
hackathon prize-pool math (getTotalPrizePoolForFunding, buildWinnerDistribution,
2.5% PLATFORM_FEE) rather than duplicating it.
- tabs/ScopeTab.tsx: scope form.
- tabs/RewardTab.tsx: currency + mode-driven prize tiers (field array sized to
the winner count) with a live prize-pool / fee / total preview.
- tabs/ReviewTab.tsx: per-section summary, validation summary, funding totals,
and a publish CTA disabled until every section validates.
- NewBountyTab.tsx + constants.ts: wire the three tabs into the wizard; the form
snapshot now uses the per-tab form schema types.
Reward currency is collected in the Reward step (the backend section that
persists it) rather than Scope, so it round-trips. The publish action is a
placeholder pending the escrow publish flow (#601); the disabled-until-valid
gate is wired here.
* feat(bounty): use-bounty-publish (escrow publish via shared runner) (#601) (#615)
* feat(bounty): Scope + Reward + Review tabs and Zod schemas (#600)
Completes the editable surface of the bounty Configure wizard, dropping the
three remaining tabs into the seams the shell (#598) left.
- tabs/schemas/scopeSchema.ts: title, description, optional GitHub issue
url/number, optional project/window.
- tabs/schemas/rewardSchema.ts: makeRewardSchema(claimType) — exactly one tier
for single claim, 1-3 for a competition; amounts > 0, unique positions
including position 1 (mirrors the publish gate's deriveWinnerDistribution).
- lib/utils/bounty-escrow.ts: adapts the bounty reward shape to reuse the
hackathon prize-pool math (getTotalPrizePoolForFunding, buildWinnerDistribution,
2.5% PLATFORM_FEE) rather than duplicating it.
- tabs/ScopeTab.tsx: scope form.
- tabs/RewardTab.tsx: currency + mode-driven prize tiers (field array sized to
the winner count) with a live prize-pool / fee / total preview.
- tabs/ReviewTab.tsx: per-section summary, validation summary, funding totals,
and a publish CTA disabled until every section validates.
- NewBountyTab.tsx + constants.ts: wire the three tabs into the wizard; the form
snapshot now uses the per-tab form schema types.
Reward currency is collected in the Reward step (the backend section that
persists it) rather than Scope, so it round-trips. The publish action is a
placeholder pending the escrow publish flow (#601); the disabled-until-valid
gate is wired here.
* feat(bounty): use-bounty-publish (escrow publish via shared runner) (#601)
Wires the bounty publish action, mirroring use-hackathon-publish.
- hooks/use-bounty-publish.ts: builds PublishBountyEscrowDto (ownerAddress,
tokenAddress via getTokenAddress('USDC'), budget = sum of tier amounts,
submissionDeadline as unix from the draft deadline, applicationCreditCost,
winnerDistribution via the shared buildBountyWinnerDistribution, fundingMode)
and drives it with useEscrowOpRunner: MANAGED returns PENDING_CONFIRM then
polls; EXTERNAL signs the returned XDR via signXdrWithKit then submits + polls.
On COMPLETED the bounty has moved draft_awaiting_funding -> open. Pre-flight
resumes an in-flight op, short-circuits an already-published bounty, and runs a
MANAGED USDC balance check (pool + 2.5% fee).
- NewBountyTab.tsx: replace the Review placeholder with the real publish() and
wire isPublishing into the CTA.
Treasury funding (sourceWalletId) is omitted until the backend treasury-parity
issue (boundless-nestjs #314) lands; MANAGED + EXTERNAL are supported. The
funding-source picker + progress modal remain a follow-up; the hook exposes the
escrow phase/error/txHash they need.
* feat(bounty): routes + organization bounty list page (#597) (#616)
Adds the organizer bounty routes, mirroring the hackathon route tree, and the
published-list data needed by the list page.
- app/(landing)/organizations/[id]/bounties/page.tsx: list page with a Drafts
section (resume links + status badges + mode label / section count) and a
Published section (status badges + reward), plus a "Host a bounty" CTA.
- .../bounties/new/page.tsx: renders <NewBountyTab organizationId={id} />.
- .../bounties/drafts/[draftId]/page.tsx: renders
<NewBountyTab organizationId={id} draftId={draftId} />.
- features/bounties/api/core.ts + use-bounties.ts: listOrganizationBounties +
useOrganizationBounties for the root list (the backend root GET has no
response DTO, so the row shape is projected to OrganizationBountyListItem).
The pages mount the existing wizard shell (#598); the list separates drafts
(draft / draft_awaiting_funding) from published bounties so they don't
double-list.
* feat(bounty): sidebar nav entry + Post Bounty quick action (#602) (#617)
Adds a Bounties menu item (/organizations/{orgId}/bounties) and a Post Bounty
quick action (/organizations/{orgId}/bounties/new) to OrganizationSidebar, so
organizers can reach the bounty list + Configure wizard.
Codegen reconcile: re-ran npm run codegen against the v2 backend; the committed
lib/api/generated/schema.d.ts already matches (BountyDraftResponseDto +
UpdateBountyDraftDto present, no drift), so no schema change is needed.
* feat(bounty): wizard enhancements + hackathon-style org bounty list (#618)
* feat(bounty): wizard enhancements (resources step, currency, reputation, nav)
- Resources: new optional Resources step (links + PDF/DOC/PPT/MD uploads),
mirroring the hackathon resources tab; never blocks publish. Reuses a now
configurable ResourceFileUpload (folder/tags/accepted types props; unique
input id per row).
- Reward currency: dropdown of USDC (default) / XLM (disabled) with real token
logos, replacing the free-text field.
- Reputation: per-category minimum floor (development highest); the organizer
can raise it but not drop below the category baseline.
- Navigation: Back button on every step after the first.
- Scope: category chips + searchable country dropdown with flags + markdown
description; GitHub issue URL required only for development.
- Publish: redirect to the organizer's bounty list once publish finalizes.
- Dev-only "Fill with mock" button to populate every section at once.
* feat(bounty): hackathon-style org bounty list + delete-draft confirm
- Rebuild the organization bounty list page in the hackathon style: sticky
header with stats, Published/Drafts tabs, search + sort, and a banner-less
reward-focused card grid (draft cards show a progress bar + resume link).
- Deleting a draft now opens a confirmation modal (DeleteBountyDraftDialog)
instead of deleting on the first click.
- Expose `_count.submissions` on the org bounty list item for the cards.
* Feat/crowdfunding (#620)
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)
Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.
- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
cancel / select-winners / submit-signed / poll) plus useEscrowOp +
useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.
Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.
* feat(bounty): wizard shell + step/draft machinery (#598)
Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.
- components/organization/bounties/new/constants.ts: StepKey
(scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
resume via useDraft, and transformBountyFromApi (sections -> form state;
winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
steps + draft + per-step save, persisting ?draftId= for resume, and threading
the chosen mode from ModeTab into SubmissionModelTab.
Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.
* feat: implement multi-step crowdfunding campaign wizard with milestone management
* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking
- Redesigned public listing (ProjectCard) and detail page with proper
lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
contributions) with shared header showing milestone X/Y progress and
Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
"paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
milestone status copy and tone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: update lockfile dependencies for package-lock.json
---------
Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Feat/crowdfunding (#642)
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)
Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.
- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
cancel / select-winners / submit-signed / poll) plus useEscrowOp +
useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.
Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.
* feat(bounty): wizard shell + step/draft machinery (#598)
Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.
- components/organization/bounties/new/constants.ts: StepKey
(scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
resume via useDraft, and transformBountyFromApi (sections -> form state;
winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
steps + draft + per-step save, persisting ?draftId= for resume, and threading
the chosen mode from ModeTab into SubmissionModelTab.
Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.
* feat: implement multi-step crowdfunding campaign wizard with milestone management
* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking
- Redesigned public listing (ProjectCard) and detail page with proper
lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
contributions) with shared header showing milestone X/Y progress and
Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
"paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
milestone status copy and tone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: update lockfile dependencies for package-lock.json
* refactor: standardize API error extraction to support array-based messages across crowdfunding components
* refactor: restructure StoryStep inputs, enable sidebar navigation, and update campaign wizard validation logic
---------
Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Feat/crowdfunding (#644)
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)
Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.
- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
cancel / select-winners / submit-signed / poll) plus useEscrowOp +
useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.
Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.
* feat(bounty): wizard shell + step/draft machinery (#598)
Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.
- components/organization/bounties/new/constants.ts: StepKey
(scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
resume via useDraft, and transformBountyFromApi (sections -> form state;
winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
steps + draft + per-step save, persisting ?draftId= for resume, and threading
the chosen mode from ModeTab into SubmissionModelTab.
Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.
* feat: implement multi-step crowdfunding campaign wizard with milestone management
* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking
- Redesigned public listing (ProjectCard) and detail page with proper
lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
contributions) with shared header showing milestone X/Y progress and
Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
"paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
milestone status copy and tone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: update lockfile dependencies for package-lock.json
* refactor: standardize API error extraction to support array-based messages across crowdfunding components
* refactor: restructure StoryStep inputs, enable sidebar navigation, and update campaign wizard validation logic
* feat: replace textarea with AnnouncementEditor and add markdown rendering for campaign project details
---------
Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Feat/crowdfunding (#648)
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)
Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.
- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
cancel / select-winners / submit-signed / poll) plus useEscrowOp +
useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.
Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.
* feat(bounty): wizard shell + step/draft machinery (#598)
Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.
- components/organization/bounties/new/constants.ts: StepKey
(scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
resume via useDraft, and transformBountyFromApi (sections -> form state;
winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
steps + draft + per-step save, persisting ?draftId= for resume, and threading
the chosen mode from ModeTab into SubmissionModelTab.
Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.
* feat: implement multi-step crowdfunding campaign wizard with milestone management
* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking
- Redesigned public listing (ProjectCard) and detail page with proper
lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
contributions) with shared header showing milestone X/Y progress and
Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
"paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
milestone status copy and tone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: update lockfile dependencies for package-lock.json
* refactor: standardize API error extraction to support array-based messages across crowdfunding components
* refactor: restructure StoryStep inputs, enable sidebar navigation, and update campaign wizard validation logic
* feat: replace textarea with AnnouncementEditor and add markdown rendering for campaign project details
* fix: useCampaign routes UUID params to fetchCampaignById
Post-create redirect lands on /me/crowdfunding/{uuid}. The hook was
always calling the slug endpoint which rejected UUIDs. Now detects
UUID format and uses the correct /api/crowdfunding/{id} endpoint.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: auth-gate voting/contribute + branded fallback banner
- VotePanel: unauthenticated users see "Sign in to vote" instead of
the yes/no buttons
- Public page: "Back this project" replaced with "Sign in to back this
project" link for unauthenticated visitors
- Fallback banner (no banner set): full-height Boundless-branded SVG
with dot grid, concentric arcs in brand colour, and faint wordmark
instead of the flat zinc gradient div
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Feat/crowdfunding (#650)
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)
Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.
- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
cancel / select-winners / submit-signed / poll) plus useEscrowOp +
useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.
Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.
* feat(bounty): wizard shell + step/draft machinery (#598)
Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.
- components/organization/bounties/new/constants.ts: StepKey
(scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
resume via useDraft, and transformBountyFromApi (sections -> form state;
winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
steps + draft + per-step save, persisting ?draftId= for resume, and threading
the chosen mode from ModeTab into SubmissionModelTab.
Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.
* feat: implement multi-step crowdfunding campaign wizard with milestone management
* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking
- Redesigned public listing (ProjectCard) and detail page with proper
lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
contributions) with shared header showing milestone X/Y progress and
Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
"paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
milestone status copy and tone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: update lockfile dependencies for package-lock.json
* refactor: standardize API error extraction to support array-based messages across crowdfunding components
* refactor: restructure StoryStep inputs, enable sidebar navigation, and update campaign wizard validation logic
* feat: replace textarea with AnnouncementEditor and add markdown rendering for campaign project details
* fix: useCampaign routes UUID params to fetchCampaignById
Post-create redirect lands on /me/crowdfunding/{uuid}. The hook was
always calling the slug endpoint which rejected UUIDs. Now detects
UUID format and uses the correct /api/crowdfunding/{id} endpoint.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: auth-gate voting/contribute + branded fallback banner
- VotePanel: unauthenticated users see "Sign in to vote" instead of
the yes/no buttons
- Public page: "Back this project" replaced with "Sign in to back this
project" link for unauthenticated visitors
- Fallback banner (no banner set): full-height Boundless-branded SVG
with dot grid, concentric arcs in brand colour, and faint wordmark
instead of the flat zinc gradient div
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: unify campaign description rendering logic to prioritize details over description fields across project components
---------
Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add tabbed navigation to campaign page for overview, milestones, and supporters sections
* refactor: enhance milestone detail page with status-specific feedback views and improved header metadata
* feat: add polling to campaign query and improve cache invalidation across crowdfunding hooks
* feat(bounty): participant data layer (escrow client + hooks) (#643)
Add the builder/participant data layer to features/bounties, mirroring the
hackathon participant scope and reusing the shared escrow runner. The visible
builder UI (marketplace, detail, apply/submit/withdraw, my-bounties) consumes
this.
- participant-escrow-client: on-chain apply/submit/withdraw-application/
withdraw-submission/contribute + participant op poll + submit-signed
(the no-org-prefix /api/bounties/{id}/escrow/* routes)
- participant-client: public list/detail, v2 application records
(apply/edit/withdraw/me), competition join/leave
- use-participant hooks: useBountiesList/useBounty/useMyBountyApplication,
useApply/Edit/WithdrawApplication, useJoin/LeaveCompetition, and escrow-op
hooks (useSubmitBounty/useWithdrawSubmission/useContributeToBounty/
useApplyToBountyEscrow/useWithdrawApplicationEscrow) driven through the
runner, default MANAGED
- use-escrow: EscrowOpScope is now organizer | participant; the runner routes
op-poll/submit-signed to the participant URLs
- keys/types/index: participant query keys, type aliases, public exports
MyBountyApplication is hand-typed until boundless-nestjs #331 lands and codegen
runs; useMyBountyActivity is deferred until the participant dashboard (#332).
Closes #621
* feat(bounty): public bounty marketplace (discover/list) (#645)
* feat(bounty): participant data layer (escrow client + hooks)
Add the builder/participant data layer to features/bounties, mirroring the
hackathon participant scope and reusing the shared escrow runner. The visible
builder UI (marketplace, detail, apply/submit/withdraw, my-bounties) consumes
this.
- participant-escrow-client: on-chain apply/submit/withdraw-application/
withdraw-submission/contribute + participant op poll + submit-signed
(the no-org-prefix /api/bounties/{id}/escrow/* routes)
- participant-client: public list/detail, v2 application records
(apply/edit/withdraw/me), competition join/leave
- use-participant hooks: useBountiesList/useBounty/useMyBountyApplication,
useApply/Edit/WithdrawApplication, useJoin/LeaveCompetition, and escrow-op
hooks (useSubmitBounty/useWithdrawSubmission/useContributeToBounty/
useApplyToBountyEscrow/useWithdrawApplicationEscrow) driven through the
runner, default MANAGED
- use-escrow: EscrowOpScope is now organizer | participant; the runner routes
op-poll/submit-signed to the participant URLs
- keys/types/index: participant query keys, type aliases, public exports
MyBountyApplication is hand-typed until boundless-nestjs #331 lands and codegen
runs; useMyBountyActivity is deferred until the participant dashboard (#332).
Closes #621
* feat(bounty): public bounty marketplace (discover/list)
Replace the /coming-soon placeholder at /bounties with a real public
marketplace, mirroring the hackathon browse and wired to the participant
data layer (#621).
- route app/(landing)/bounties/page.tsx + bounties metadata entry
- BountiesPage: search + status + mode filters, infinite scroll,
loading/empty/error states
- BountyCard: mode badge (plain label), status, reward, organization,
application-window date; links to /bounties/[id]
- BountiesFiltersHeader + colocated useInfiniteBounties (infinite query
over listBounties)
Status + search filter server-side; mode narrows client-side (the public
list endpoint doesn't filter on mode). Category filter and a card submission
deadline are omitted because BountyPublicDto exposes neither — small backend
follow-ups.
Closes #622
* feat(bounty): bounty detail page (/bounties/[id]) (#646)
* feat(bounty): participant data layer (escrow client + hooks)
Add the builder/participant data layer to features/bounties, mirroring the
hackathon participant scope and reusing the shared escrow runner. The visible
builder UI (marketplace, detail, apply/submit/withdraw, my-bounties) consumes
this.
- participant-escrow-client: on-chain apply/submit/withdraw-application/
withdraw-submission/contribute + participant op poll + submit-signed
(the no-org-prefix /api/bounties/{id}/escrow/* routes)
- participant-client: public list/detail, v2 application records
(apply/edit/withdraw/me), competition join/leave
- use-participant hooks: useBountiesList/useBounty/useMyBountyApplication,
useApply/Edit/WithdrawApplication, useJoin/LeaveCompetition, and escrow-op
hooks (useSubmitBounty/useWithdrawSubmission/useContributeToBounty/
useApplyToBountyEscrow/useWithdrawApplicationEscrow) driven through the
runner, default MANAGED
- use-escrow: EscrowOpScope is now organizer | participant; the runner routes
op-poll/submit-signed to the participant URLs
- keys/types/index: participant query keys, type aliases, public exports
MyBountyApplication is hand-typed until boundless-nestjs #331 lands and codegen
runs; useMyBountyActivity is deferred until the participant dashboard (#332).
Closes #621
* feat(bounty): public bounty marketplace (discover/list)
Replace the /coming-soon placeholder at /bounties with a real public
marketplace, mirroring the hackathon browse and wired to the participant
data layer (#621).
- route app/(landing)/bounties/page.tsx + bounties metadata entry
- BountiesPage: search + status + mode filters, infinite scroll,
loading/empty/error states
- BountyCard: mode badge (plain label), status, reward, organization,
application-window date; links to /bounties/[id]
- BountiesFiltersHeader + colocated useInfiniteBounties (infinite query
over listBounties)
Status + search filter server-side; mode narrows client-side (the public
list endpoint doesn't filter on mode). Category filter and a card submission
deadline are omitted because BountyPublicDto exposes neither — small backend
follow-ups.
Closes #622
* feat(bounty): bounty detail page (/bounties/[id])
The builder hub: shows the bounty, the caller's status, and a mode-aware
entry CTA. Wired to the participant data layer (#621).
- route app/(landing)/bounties/[id]/page.tsx
- BountyDetail: markdown description, prize tiers, mode/status badges,
organization, reward pool + eligibility sidebar (reputation minimum /
application window / max applicants / shortlist); loading + not-found
- BountyEntryCta: mode-aware CTA — Claim (open+single), Join (open+
competition), Apply (application). Gated/explained when not accepting,
the application window closed, or already applied; shows the caller's
application status via useMyBountyApplication
The actual entry execution (forms / on-chain op) ships in #624; the CTA is
gated + labeled and hands off to it. applicationCreditCost is not in
BountyPublicDto so it's omitted from the eligibility panel.
Closes #623
* feat(bounty): apply / join / claim flow + edit/withdraw (mode-aware) (#647)
Fill the entry execution the detail-page CTA hands off to (#623), wired to
the participant data layer (#621). Covers all six modes.
- applicationSchema: mode-aware zod validation + body builders (light:
proposalShort 100-300 words + estimatedDays + <=3 links; full: proposalFull
500-2000 words + qualifications >=50 chars + <=6 links + optional video)
- BountyApplicationForm: conditional fields per entry type with live word
count; reused for create + edit
- BountyEntryDialog: mode-aware modal — Apply (POST v2/applications) / Edit
(PATCH); Join (POST v2/competition/join); Claim (on-chain apply escrow op,
MANAGED, with progress + reputation pre-check). Wallet-gated.
- BountyEntryCta: opens the dialog and, for an active application, exposes
Edit + Withdraw (application), Leave (competition), or on-chain Withdraw
(single claim) behind a two-step confirm
Closes #624
* feat(bounty): submit work (on-chain anchor) + withdraw submission (#649)
After entry (claim/join/selection) the builder submits their deliverable,
anchored on-chain via the participant escrow runner (#621). Mirrors the
hackathon submission anchor.
- BountySubmitPanel (detail sidebar, shown when eligible: claimed/joined/
SELECTED/SHORTLISTED): contentUri deliverable input -> submit escrow op
(useSubmitBounty, MANAGED) with anchor progress (preparing -> anchoring ->
confirmed) + tx-hash explorer link
- Withdraw submission via useWithdrawSubmission behind a two-step confirm
- Wallet-gated; guarded by entry eligibility
Persistent submission state across reloads is session-local until the #332
my-submission read lands in the schema; the submission-deadline gate is
enforced on-chain (not in BountyPublicDto).
Closes #625
* feat(bounty): builder "my bounties" activity + rewards receipt (#651)
The builder's /me surfaces for bounty applications, submissions, and reward
receipts, consuming the participant dashboard (#332) + earnings (#335).
- data layer: useMyBountyApplications / useMyBountySubmissions (the deferred
useMyBountyActivity) via the legacy axios api (hand-typed rows, retry:false,
degrading to empty until #332 lands in the schema)
- /me/bounties page: Applications + Submissions tabs with status/progress
badges; won submissions show the reward amount + a payout tx-hash link;
rows link to the detail page
- sidebar: "My Bounties" nav entry
- /me/earnings: the page already renders breakdown.bounties + activities
generically (so #335 surfaces them); add a "View tx" link to reward
activities (txHash cast until codegen)
Closes #626
* ci: auto-close linked issues on merge to any base branch (#652)
GitHub's built-in Closes/Fixes/Resolves auto-close only fires for PRs
merged into the default branch. Feature PRs here merge into integration
branches (feat/t-replace, etc.), leaving linked issues open. This adds a
pull_request_target workflow that parses the merged PR body and closes
the referenced same-repo issues on any base branch.
* feat(bounty): codegen refresh + retire hand-typed participant casts (#627) (#653)
The participant gap endpoints (applications/me, my-activity, results) have
landed in v2, so regenerate the OpenAPI schema and replace the two
hand-typed casts (MyBountyApplication, my-activity dashboard rows) with
their generated DTO aliases. Refresh openapi.snapshot.json so offline/CI
codegen matches. Nav entries (marketplace + /me sidebar) already shipped.
* feat: add template selection to hackathon generation dialog with new hook and UI component
* feat(bounty): submission page, marketplace redesign, and organizer requirements (#662)
* feat(bounty): submission metadata types, category filter, and wizard requirement toggles
Refresh the generated OpenAPI schema for the new public-bounty fields
(claimedBy, category, submissionDeadline, submissionRequirements) and the
submit-op metadata. Add the category query param to the marketplace list
client, the per-bounty my-submission read + hook, and the organizer
requirement toggles in the Configure wizard's submission step. Flatten the
category reputation baseline to 0 for testing and let the wizard accept a
0 floor.
* feat(bounty): marketplace card redesign, category tabs, and detail display
Bounty cards now show the organizer logo, category, a live due-date
countdown, and the USDC token logo (title only, no markdown bleed). Add a
category tab bar to the marketplace and mirror the same details on the
detail page, plus a mode-explainer tooltip. Single-claim bounties render a
'Claimed by' card linking to the claimant profile, and the application
withdraw button is gated while a submission is anchored.
* feat(bounty): dedicated submit page with metadata and media upload
Replace the single-input submit panel with a /bounties/[id]/submit page:
primary submission link plus optional documentation, tweet, and demo video
links and a drag-and-drop media uploader. Required fields follow the
bounty's organizer-configured requirements; on success it returns to the
detail page. The sidebar panel now routes here (new tab) and reflects the
submitted/withdraw state.
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Nnaji Benjamin <60315147+Benjtalkshow@users.noreply.github.com>
Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>1 parent 2cb7127 commit ef423a2
324 files changed
Lines changed: 135521 additions & 15442 deletions
File tree
- .claude
- .github/workflows
- .husky
- app
- (landing)
- bounties
- [id]
- submit
- crowdfunding
- [slug]
- milestones
- [id]
- new
- hackathons
- [slug]
- components
- header
- sidebar
- tabs/contents
- submissions
- submit
- preview/[orgId]/[draftId]
- organizations
- [id]
- bounties
- drafts/[draftId]
- new
- hackathons
- [hackathonId]
- judging
- participants
- rewards
- settings
- winners
- drafts/[draftId]
- new
- treasury
- receipts/[receiptId]
- projects/[slug]
- judge/[hackathonId]/submissions/[submissionId]
- me
- bounties
- crowdfunding
- [slug]
- components
- contributions
- edit
- components
- milestones
- [milestoneIndex]
- new
- earnings
- partners/contribute/[token]
- components
- auth
- bounties
- detail
- entry
- submit
- marketplace
- crowdfunding
- new
- steps
- hackathons
- overview
- submissions
- judge
- landing-page
- hackathon
- me/bounties
- organization
- bounties
- new
- tabs
- schemas
- cards/ReviewSubmissionModal
- hackathons
- details
- judging
- new
- tabs
- components
- review
- schemas
- rewards
- settings
- tabs
- MembersTab
- treasury
- project-details/project-sidebar
- providers
- features
- bounties
- api
- crowdfunding
- api
- components
- hackathons
- api
- projects
- api
- components
- types
- treasury
- hooks
- hackathon
- lib
- api
- generated
- hackathons
- user
- auth
- config
- crowdfunding
- providers
- stores
- utils
- wallet
- types
- hackathon
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
25 | 29 | | |
26 | 30 | | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | 31 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | 6 | | |
13 | | - | |
14 | | - | |
15 | | - | |
| 7 | + | |
| 8 | + | |
16 | 9 | | |
17 | | - | |
18 | 10 | | |
19 | | - | |
20 | | - | |
| 11 | + | |
21 | 12 | | |
22 | 13 | | |
23 | | - | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
| 2 | + | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | | - | |
| 6 | + | |
6 | 7 | | |
7 | | - | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | | - | |
11 | | - | |
| 10 | + | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | | - | |
16 | | - | |
| 14 | + | |
0 commit comments