Atlas-Bounty: Fix Hackathon Draft Deletion Failure (#416) - #422
Conversation
… claim functionality, and update earnings data structure for improved clarity and performance.
|
Someone is attempting to deploy a commit to the Threadflow Team on Vercel. A member of the Team first needs to authorize it. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a draft-aware hackathon deletion flow (isDraft flag + deleteDraft API) and implements a new client-side Earnings dashboard with typed API endpoints and a sidebar navigation item. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant EarningsPage as "Earnings Page"
participant API as "API Layer"
participant Backend as "Backend Server"
User->>EarningsPage: Navigate to /me/earnings
EarningsPage->>EarningsPage: mount → show loading state
EarningsPage->>API: getUserEarnings()
API->>Backend: GET /user/earnings
Backend->>API: 200 OK (EarningsData)
API->>EarningsPage: GetEarningsResponse (data)
EarningsPage->>EarningsPage: render cards, breakdown, activities
EarningsPage->>User: display dashboard
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
hooks/hackathon/use-delete-hackathon.ts (1)
29-37:⚠️ Potential issue | 🟡 MinorMake auth/validation copy draft-aware.
With draft deletion now supported, hardcoded “hackathons” / “Hackathon ID” messages are inaccurate for draft flows.
💡 Suggested fix
const deleteHackathonAction = useCallback(async () => { + const targetPlural = isDraft ? 'drafts' : 'hackathons'; + const targetSingular = isDraft ? 'Draft' : 'Hackathon'; + if (!isAuthenticated) { - toast.error('Please sign in to delete hackathons'); + toast.error(`Please sign in to delete ${targetPlural}`); throw new Error('Authentication required'); } if (!organizationId || !hackathonId) { - toast.error('Organization ID and Hackathon ID are required'); - throw new Error('Organization ID and Hackathon ID are required'); + const idError = `Organization ID and ${targetSingular} ID are required`; + toast.error(idError); + throw new Error(idError); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@hooks/hackathon/use-delete-hackathon.ts` around lines 29 - 37, The current auth/validation error messages use hardcoded "hackathons"/"Hackathon ID" and aren't draft-aware; update the checks in the block that references isAuthenticated, organizationId, and hackathonId to produce contextual messages depending on the draft flow (e.g., use an isDraft boolean or existing draft flag in scope). Replace static strings like 'Please sign in to delete hackathons' and 'Organization ID and Hackathon ID are required' with conditional messages such as 'Please sign in to delete this hackathon draft' vs 'Please sign in to delete this hackathon' and similarly for the ID validation (or create a small helper like getEntityLabel(isDraft) and use it in the toast.error and thrown Error messages). Ensure you update both toast.error and thrown Error text and reference the existing variables isAuthenticated, organizationId, and hackathonId (and the draft flag) so messages reflect draft vs published flows.app/(landing)/organizations/[id]/hackathons/page.tsx (1)
100-114:⚠️ Potential issue | 🟡 MinorDraft deletes can show incorrect/duplicate toast copy.
onSuccess/onErrorstill hardcode “Hackathon”, while the hook already emits draft-aware toasts. This can show wrong wording for drafts and double-toast users.💡 Suggested fix
const { isDeleting, deleteHackathon } = useDeleteHackathon({ organizationId, hackathonId: hackathonToDelete?.id || '', isDraft: hackathonToDelete?.isDraft || false, onSuccess: () => { - // Refresh the hackathons list after successful deletion refetchAll(); - toast.success('Hackathon deleted successfully', { - description: `"${hackathonToDelete?.title}" has been permanently deleted.`, - }); - }, - onError: error => { - toast.error('Failed to delete hackathon', { - description: error, - }); }, });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(landing)/organizations/[id]/hackathons/page.tsx around lines 100 - 114, The component is duplicating toast messages that the useDeleteHackathon hook already emits; remove the hardcoded toast calls in the onSuccess and onError callbacks to avoid wrong/double toasts. In the useDeleteHackathon call (symbols: useDeleteHackathon, onSuccess, onError, hackathonToDelete), keep the success callback to perform non-UI side-effects like refetchAll() but delete the toast.success call (including the description that references hackathonToDelete.title), and remove the toast.error call from onError so the hook’s draft-aware error toast is the only user-facing message.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@app/`(landing)/organizations/[id]/hackathons/page.tsx:
- Around line 100-114: The component is duplicating toast messages that the
useDeleteHackathon hook already emits; remove the hardcoded toast calls in the
onSuccess and onError callbacks to avoid wrong/double toasts. In the
useDeleteHackathon call (symbols: useDeleteHackathon, onSuccess, onError,
hackathonToDelete), keep the success callback to perform non-UI side-effects
like refetchAll() but delete the toast.success call (including the description
that references hackathonToDelete.title), and remove the toast.error call from
onError so the hook’s draft-aware error toast is the only user-facing message.
In `@hooks/hackathon/use-delete-hackathon.ts`:
- Around line 29-37: The current auth/validation error messages use hardcoded
"hackathons"/"Hackathon ID" and aren't draft-aware; update the checks in the
block that references isAuthenticated, organizationId, and hackathonId to
produce contextual messages depending on the draft flow (e.g., use an isDraft
boolean or existing draft flag in scope). Replace static strings like 'Please
sign in to delete hackathons' and 'Organization ID and Hackathon ID are
required' with conditional messages such as 'Please sign in to delete this
hackathon draft' vs 'Please sign in to delete this hackathon' and similarly for
the ID validation (or create a small helper like getEntityLabel(isDraft) and use
it in the toast.error and thrown Error messages). Ensure you update both
toast.error and thrown Error text and reference the existing variables
isAuthenticated, organizationId, and hackathonId (and the draft flag) so
messages reflect draft vs published flows.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
app/(landing)/organizations/[id]/hackathons/page.tsxapp/me/earnings/page.tsxcomponents/app-sidebar.tsxhooks/hackathon/use-delete-hackathon.tslib/api/hackathons/draft.tslib/api/user/earnings.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@hooks/hackathon/use-delete-hackathon.ts`:
- Around line 29-30: Remove any trailing whitespace and fix formatting on the
line that declares the variable targetLabel (const targetLabel = isDraft ?
'draft' : 'hackathon';) so it matches project Prettier rules; run prettier
--write (or your editor's formatter) on use-delete-hackathon.ts to apply the
formatting changes and ensure no extra spaces or inconsistent quotes remain.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
app/(landing)/organizations/[id]/hackathons/page.tsxhooks/hackathon/use-delete-hackathon.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- app/(landing)/organizations/[id]/hackathons/page.tsx
There was a problem hiding this comment.
🧹 Nitpick comments (2)
hooks/hackathon/use-delete-hackathon.ts (2)
17-26: Consider using const arrow function per coding guidelines.The hook uses a function declaration, but coding guidelines prefer const arrow functions with explicit type annotations.
♻️ Proposed refactor
-export function useDeleteHackathon({ +export const useDeleteHackathon = ({ organizationId, hackathonId, isDraft = false, onSuccess, onError, -}: UseDeleteHackathonOptions) { +}: UseDeleteHackathonOptions) => {As per coding guidelines: "Prefer const arrow functions with explicit type annotations over function declarations".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@hooks/hackathon/use-delete-hackathon.ts` around lines 17 - 26, Change the function declaration useDeleteHackathon(...) to a const arrow function with an explicit return type annotation matching its current signature (keep UseDeleteHackathonOptions for the params type), e.g. declare const useDeleteHackathon: (opts: UseDeleteHackathonOptions) => ReturnType and implement the body unchanged (preserve state hooks isDeleting/setIsDeleting and error state). Ensure you export the const and keep any existing named imports/usages intact.
36-40: Consider conditional validation fororganizationId.The validation requires
organizationIdeven whenisDraft = false, butdeleteHackathon(hackathonId)doesn't use it. This may cause unnecessary errors for callers who don't haveorganizationIdavailable when deleting published hackathons.♻️ Proposed fix for conditional validation
- if (!organizationId || !hackathonId) { - const idError = `Organization ID and ${isDraft ? 'Draft' : 'Hackathon'} ID are required`; + if ((isDraft && !organizationId) || !hackathonId) { + const idError = isDraft + ? 'Organization ID and Draft ID are required' + : 'Hackathon ID is required'; toast.error(idError); throw new Error(idError); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@hooks/hackathon/use-delete-hackathon.ts` around lines 36 - 40, The current validation block forces organizationId even for non-draft deletes; change it to require organizationId only when isDraft is true and always require hackathonId: check hackathonId first and if missing show toast.error/throw, and if isDraft && !organizationId show toast.error/throw; update the idError messages accordingly so deleteHackathon(hackathonId) callers without organizationId can proceed when isDraft is false. Ensure you modify the validation surrounding isDraft, organizationId, hackathonId, toast.error and the thrown Error to reflect the conditional checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@hooks/hackathon/use-delete-hackathon.ts`:
- Around line 17-26: Change the function declaration useDeleteHackathon(...) to
a const arrow function with an explicit return type annotation matching its
current signature (keep UseDeleteHackathonOptions for the params type), e.g.
declare const useDeleteHackathon: (opts: UseDeleteHackathonOptions) =>
ReturnType and implement the body unchanged (preserve state hooks
isDeleting/setIsDeleting and error state). Ensure you export the const and keep
any existing named imports/usages intact.
- Around line 36-40: The current validation block forces organizationId even for
non-draft deletes; change it to require organizationId only when isDraft is true
and always require hackathonId: check hackathonId first and if missing show
toast.error/throw, and if isDraft && !organizationId show toast.error/throw;
update the idError messages accordingly so deleteHackathon(hackathonId) callers
without organizationId can proceed when isDraft is false. Ensure you modify the
validation surrounding isDraft, organizationId, hackathonId, toast.error and the
thrown Error to reflect the conditional checks.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
hooks/hackathon/use-delete-hackathon.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
hooks/hackathon/use-delete-hackathon.ts (1)
7-13: ModelUseDeleteHackathonOptionsas a discriminated union.Line 8 makes
organizationIdrequired even whenisDraftis false, while draft-only requirements are enforced at runtime. This weakens type guarantees and forces non-draft callers to pass unused data.♻️ Suggested type-safe shape
-interface UseDeleteHackathonOptions { - organizationId: string; - hackathonId: string; - isDraft?: boolean; - onSuccess?: () => void; - onError?: (error: string) => void; -} +type UseDeleteHackathonOptions = + | { + isDraft: true; + organizationId: string; + hackathonId: string; + onSuccess?: () => void; + onError?: (error: string) => void; + } + | { + isDraft?: false; + organizationId?: string; + hackathonId: string; + onSuccess?: () => void; + onError?: (error: string) => void; + };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@hooks/hackathon/use-delete-hackathon.ts` around lines 7 - 13, Change the flat UseDeleteHackathonOptions interface into a discriminated union so organizationId is only required for draft deletions: define one variant { isDraft: true; organizationId: string; hackathonId: string; onSuccess?: () => void; onError?: (error: string) => void } and another for non-draft { isDraft?: false; hackathonId: string; onSuccess?: () => void; onError?: (error: string) => void }, then update usages of UseDeleteHackathonOptions/ isDraft checks in the delete hook to rely on the discriminant instead of runtime assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@hooks/hackathon/use-delete-hackathon.ts`:
- Around line 32-45: Precondition checks (isAuthenticated, hackathonId, isDraft
&& !organizationId) currently throw before the try/catch so setError/onError are
never invoked and the draft error message is mislabeled; update the checks
inside the same try block or, instead of throwing directly, call setError(error)
and invoke onError(error) (if provided) and return early after showing toast so
hook error state/callbacks run; also change the hackathonId toast/text to use
"Draft ID" when isDraft is true (use the isDraft flag to pick the correct
label). Ensure you modify the code paths referencing isAuthenticated,
hackathonId, isDraft, organizationId, setError and onError accordingly.
---
Nitpick comments:
In `@hooks/hackathon/use-delete-hackathon.ts`:
- Around line 7-13: Change the flat UseDeleteHackathonOptions interface into a
discriminated union so organizationId is only required for draft deletions:
define one variant { isDraft: true; organizationId: string; hackathonId: string;
onSuccess?: () => void; onError?: (error: string) => void } and another for
non-draft { isDraft?: false; hackathonId: string; onSuccess?: () => void;
onError?: (error: string) => void }, then update usages of
UseDeleteHackathonOptions/ isDraft checks in the delete hook to rely on the
discriminant instead of runtime assertions.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
hooks/hackathon/use-delete-hackathon.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@hooks/hackathon/use-delete-hackathon.ts`:
- Around line 52-54: TypeScript loses the narrowed type for organizationId in
the ternary call; when isDraft is true the earlier runtime check guarantees
organizationId is present, so call deleteDraft with a non-null assertion on
organizationId (use organizationId!) in the branch that calls deleteDraft,
leaving the deleteHackathon(hackathonId) branch unchanged; reference the isDraft
flag and the deleteDraft/deleteHackathon calls to locate the ternary expression.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
hooks/hackathon/use-delete-hackathon.ts
| const response = isDraft | ||
| ? await deleteDraft(organizationId, hackathonId) | ||
| : await deleteHackathon(hackathonId); |
There was a problem hiding this comment.
Fix TypeScript error: organizationId may be undefined.
The pipeline fails because TypeScript cannot narrow organizationId after destructuring the discriminated union. Although the runtime check at lines 48-50 ensures organizationId exists when isDraft is true, TypeScript loses this narrowing context.
Use a non-null assertion since the preceding validation guarantees organizationId is defined in the draft branch:
🐛 Proposed fix
const response = isDraft
- ? await deleteDraft(organizationId, hackathonId)
+ ? await deleteDraft(organizationId!, hackathonId)
: await deleteHackathon(hackathonId);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const response = isDraft | |
| ? await deleteDraft(organizationId, hackathonId) | |
| : await deleteHackathon(hackathonId); | |
| const response = isDraft | |
| ? await deleteDraft(organizationId!, hackathonId) | |
| : await deleteHackathon(hackathonId); |
🧰 Tools
🪛 GitHub Actions: CI/CD Pipeline
[error] 53-53: TypeScript error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. (Occurred during 'npm run type-check' / 'tsc --noEmit')
🪛 GitHub Check: Code Quality & Linting
[failure] 53-53:
Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@hooks/hackathon/use-delete-hackathon.ts` around lines 52 - 54, TypeScript
loses the narrowed type for organizationId in the ternary call; when isDraft is
true the earlier runtime check guarantees organizationId is present, so call
deleteDraft with a non-null assertion on organizationId (use organizationId!) in
the branch that calls deleteDraft, leaving the deleteHackathon(hackathonId)
branch unchanged; reference the isDraft flag and the deleteDraft/deleteHackathon
calls to locate the ternary expression.
Benjtalkshow
left a comment
There was a problem hiding this comment.
@Fankouzu
Issues in this repository are intended for humans, not bots. This PR will be closed.
Overview
Resolved the issue where hackathon drafts could not be deleted due to an API endpoint mismatch between drafts and published hackathons.
Key Changes
deleteDrafttolib/api/hackathons/draft.tstargeting the correct organization-scoped route.useDeleteHackathonto support both draft and published hackathon deletions via anisDraftparameter.Impact
Payout Information
Address: 0xa5F1e2596DC1e878a6a039f41330d9A97c771bE9
Summary by CodeRabbit
New Features
Improvements