Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 31 additions & 62 deletions components/organization/bounties/new/NewBountyTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { toast } from 'sonner';

import { Tabs, TabsContent } from '@/components/ui/tabs';
import { BoundlessButton } from '@/components/buttons';
import { useBountySteps } from '@/hooks/use-bounty-steps';
import { useBountyDraft } from '@/hooks/use-bounty-draft';
import ScopeTab from './tabs/ScopeTab';
import ModeTab from './tabs/ModeTab';
import SubmissionModelTab from './tabs/SubmissionModelTab';
import RewardTab from './tabs/RewardTab';
import ReviewTab from './tabs/ReviewTab';
import type { ModeSelection } from './tabs/schemas/modeSchema';
import {
BountyFormData,
Expand All @@ -24,33 +26,6 @@ interface NewBountyTabProps {
draftId?: string;
}

/** Placeholder for a wizard section whose tab lands in #600 (Scope / Reward). */
function SectionPlaceholder({
title,
description,
onContinue,
}: {
title: string;
description: string;
onContinue?: () => void;
}) {
return (
<div className='space-y-6'>
<div className='rounded-lg border border-dashed border-zinc-800 bg-zinc-900/30 p-6'>
<h3 className='text-sm font-medium text-white'>{title}</h3>
<p className='mt-1 text-sm text-zinc-500'>{description}</p>
</div>
{onContinue && (
<div className='flex justify-end'>
<BoundlessButton type='button' size='lg' onClick={onContinue}>
Continue
</BoundlessButton>
</div>
)}
</div>
);
}

/**
* Bounty Configure wizard orchestrator. Wires the step navigation (URL-driven),
* the draft state (lazy create + per-section PATCH + resume), and the section
Expand Down Expand Up @@ -206,11 +181,11 @@ export default function NewBountyTab({
<Tabs value={activeTab} className='w-full'>
<div className='px-6 py-6 md:px-20'>
<TabsContent value='scope' className='mt-0'>
{/* TODO(#600): replace with ScopeTab (title/description/github/...). */}
<SectionPlaceholder
title='Scope'
description='The Scope tab (title, description, GitHub issue) lands in #600.'
<ScopeTab
onSave={createSaveHandler('scope', 'mode')}
onContinue={() => navigateToStep('mode')}
initialData={stepData.scope}
isLoading={loadingStates.scope}
/>
</TabsContent>

Expand All @@ -234,41 +209,35 @@ export default function NewBountyTab({
</TabsContent>

<TabsContent value='reward' className='mt-0'>
{/* TODO(#600): replace with RewardTab (currency + prize tiers). */}
<SectionPlaceholder
title='Reward'
description='The Reward tab (currency + prize tiers) lands in #600.'
<RewardTab
mode={
stepData.mode
? {
claimType: stepData.mode.claimType,
winnerCount: stepData.mode.winnerCount,
}
: undefined
}
onSave={createSaveHandler('reward', 'review')}
onContinue={() => navigateToStep('review')}
initialData={stepData.reward}
isLoading={loadingStates.reward}
/>
</TabsContent>

<TabsContent value='review' className='mt-0'>
{/* TODO(#600/#601): replace with ReviewTab + publish/funding flow. */}
<div className='space-y-6'>
<div className='rounded-lg border border-dashed border-zinc-800 bg-zinc-900/30 p-6'>
<h3 className='text-sm font-medium text-white'>
Review &amp; publish
</h3>
<p className='mt-1 text-sm text-zinc-500'>
The review summary and the publish + funding flow land in #600
/ #601.
</p>
</div>
<div className='flex justify-end gap-3'>
<BoundlessButton
type='button'
variant='outline'
size='lg'
onClick={saveDraft}
disabled={isSavingDraft}
>
{isSavingDraft ? 'Saving...' : 'Save draft'}
</BoundlessButton>
<BoundlessButton type='button' size='lg' disabled>
Publish (coming in #601)
</BoundlessButton>
</div>
</div>
<ReviewTab
allData={stepData}
onEdit={navigateToStep}
onSaveDraft={saveDraft}
isSavingDraft={isSavingDraft}
// TODO(#601): wire the real publish + funding flow. For now the
// CTA enables once every section is valid, then reports that
// publishing lands in #601.
onPublish={() => {
toast.info('Publishing lands in #601 (escrow publish flow).');
}}
/>
</TabsContent>
</div>
</Tabs>
Expand Down
15 changes: 6 additions & 9 deletions components/organization/bounties/new/constants.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import type { ModeFormData } from './tabs/schemas/modeSchema';
import type { SubmissionModelFormData } from './tabs/schemas/submissionModelSchema';
import type {
BountyRewardSection,
BountyScopeSection,
} from '@/features/bounties';
import type { ScopeFormData } from './tabs/schemas/scopeSchema';
import type { RewardFormData } from './tabs/schemas/rewardSchema';

export type StepStatus = 'pending' | 'active' | 'completed';

Expand All @@ -25,15 +23,14 @@ export const STEP_ORDER: StepKey[] = [
];

/**
* In-progress wizard form snapshot. The four editable sections use the #599
* form schemas where they exist (mode, submission) and the generated section
* types otherwise (scope, reward — refined by the dedicated tabs in #600).
* In-progress wizard form snapshot, one entry per editable section, each typed
* by its tab's form schema.
*/
export interface BountyFormData {
scope?: BountyScopeSection;
scope?: ScopeFormData;
mode?: ModeFormData;
submission?: SubmissionModelFormData;
reward?: BountyRewardSection;
reward?: RewardFormData;
}

/**
Expand Down
Loading