Skip to content

fix(hackathons): route draft deletion to org-scoped endpoint#433

Merged
Benjtalkshow merged 4 commits into
boundlessfi:mainfrom
ryzen-xp:fix/draft-deletion-endpoint-mismatch
Mar 4, 2026
Merged

fix(hackathons): route draft deletion to org-scoped endpoint#433
Benjtalkshow merged 4 commits into
boundlessfi:mainfrom
ryzen-xp:fix/draft-deletion-endpoint-mismatch

Conversation

@ryzen-xp

@ryzen-xp ryzen-xp commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

What's completed:

  • Added deleteDraft() in lib/api/hackathons/draft.ts targeting the org-scoped route DELETE /organizations/:orgId/hackathons/draft/:draftId
  • Refactored useDeleteHackathon hook to accept a type param ('draft' | 'hackathon') and route to the correct API function
  • Updated HackathonsPage (page.tsx) to track and forward the resource type through the full deletion flow

Problem:

Both draft and drafts (singular and plural) paths return 404 — the backend DELETE endpoint for draft deletion does not exist. All frontend changes are complete and correct; unblocked only by backend implementing the route.

Screencast.From.2026-03-04.08-55-44.mp4

Close #416

Summary by CodeRabbit

  • New Features
    • Deletion now supports both draft and published hackathons.
  • Bug Fixes
    • Delete flow correctly distinguishes drafts vs published items.
    • Confirmation preserves item title and shows a post-delete toast with the specific item name.
    • Improved delete click handlers to ensure the correct item type is removed.

@vercel

vercel Bot commented Mar 3, 2026

Copy link
Copy Markdown

@ryzen-xp is attempting to deploy a commit to the Threadflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Mar 3, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Added type-aware deletion for hackathons: the UI, deletion hook, and API now distinguish between 'draft' and 'hackathon' and route deletes to the correct endpoint accordingly.

Changes

Cohort / File(s) Summary
Page — delete flow
app/(landing)/organizations/[id]/hackathons/page.tsx
Passes a type ('draft'
Hook — delete routing
hooks/hackathon/use-delete-hackathon.ts
Added DeleteType and suppressToast options; hook now calls deleteDraft when type === 'draft' and deleteHackathon otherwise; conditional toast suppression.
API — draft delete
lib/api/hackathons/draft.ts
New deleteDraft(draftId, organizationId) function and DeleteHackathonResponse type; performs organization-scoped DELETE route and normalizes 204 handling.
Barrel export cleanup
lib/api/hackathons/index.ts
Removed re-export of the draft module from the hackathons barrel file.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Page as Page Component
    participant Hook as useDeleteHackathon Hook
    participant API as API Layer
    participant Backend as Backend

    User->>Page: Click delete (draft or published)
    Page->>Page: handleDeleteClick(id, type) — store `hackathonToDelete` with `type`
    Page->>User: Show Delete confirmation
    User->>Page: Confirm deletion
    Page->>Hook: call delete with (id, type, orgId)
    alt type == 'draft'
        Hook->>API: deleteDraft(draftId, organizationId)
        API->>Backend: DELETE /organizations/{orgId}/hackathons/draft/{draftId}
    else type == 'hackathon'
        Hook->>API: deleteHackathon(hackathonId)
        API->>Backend: DELETE /api/hackathons/{id}
    end
    Backend-->>API: 204 / response
    API-->>Hook: success/error
    Hook-->>Page: onSuccess/onError
    Page->>User: show toast using captured title
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Fix hackathon #376: Edits app/(landing)/organizations/[id]/hackathons/page.tsx and touches delete handlers; overlaps with this PR's page-level delete flow changes.

Suggested reviewers

  • 0xdevcollins

Poem

🐰
A draft sat stubborn, would not part,
I hopped in code to play my part.
Type-aware routes now clear the trail,
Drafts hop away — success without fail! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: routing draft deletion to a dedicated org-scoped endpoint instead of the generic endpoint.
Linked Issues check ✅ Passed All coding objectives from issue #416 are met: deleteDraft function implemented, useDeleteHackathon hook refactored with type routing, page.tsx updated to pass type through deletion flow, and no any types used.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #416 requirements. The export removal in index.ts is appropriate housekeeping. No unrelated modifications present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ryzen-xp

ryzen-xp commented Mar 3, 2026

Copy link
Copy Markdown
Contributor Author

Hello @0xdevcollins , Can you help me why this return 404

@0xdevcollins

Copy link
Copy Markdown
Collaborator

Hello @0xdevcollins , Can you help me why this return 404

Okay... I will fix it now

@0xdevcollins

Copy link
Copy Markdown
Collaborator

@ryzen-xp it has been fixed https://stage-api.boundlessfi.xyz/api/organizations/{organizationId}/hackathons/draft/{id}

@ryzen-xp
ryzen-xp marked this pull request as ready for review March 4, 2026 03:40
@ryzen-xp
ryzen-xp requested a review from 0xdevcollins as a code owner March 4, 2026 03:40
@ryzen-xp

ryzen-xp commented Mar 4, 2026

Copy link
Copy Markdown
Contributor Author

Hello @0xdevcollins , Please Review !!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
hooks/hackathon/use-delete-hackathon.ts (1)

19-25: Use const arrow style for this hook export to match TS conventions in this repo.

The hook is currently a function declaration; convert it to a const arrow with an explicit return type for consistency.

As per coding guidelines **/*.{ts,tsx}: “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 19 - 25, Convert the
function declaration export function useDeleteHackathon({...}:
UseDeleteHackathonOptions) to a const arrow export: declare const
useDeleteHackathon: (opts: UseDeleteHackathonOptions) => ReturnType and assign
an arrow function to it, keeping the same parameter destructuring and body;
ensure you add an explicit return type (the hook’s return type used elsewhere in
the codebase) and keep the existing export behavior so references to
useDeleteHackathon continue to work.
lib/api/hackathons/draft.ts (1)

41-45: Avoid duplicating DeleteHackathonResponse across API modules.

This interface is already defined in lib/api/hackathons/core.ts and is structurally identical. Keeping one shared type prevents silent drift.

Proposed refactor
 import api from '../api';
 import { ApiResponse, PaginatedResponse } from '../types';
 import type { HackathonDraft, Hackathon } from '@/types/hackathon';
+import type { DeleteHackathonResponse } from './core';
@@
-export interface DeleteHackathonResponse extends ApiResponse<null> {
-  success: true;
-  message: string;
-  data: null;
-}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/hackathons/draft.ts` around lines 41 - 45, Duplicate interface
DeleteHackathonResponse exists in this module; delete the local declaration and
instead import and reuse the single exported DeleteHackathonResponse from the
core module where it’s defined, or re-export that core type if this module needs
to expose it; ensure any references in this file use the imported type and
update the module exports accordingly to avoid type duplication and drift.
app/(landing)/organizations/[id]/hackathons/page.tsx (1)

167-191: Refactor handleDeleteClick to use early returns and reduce nesting.

The branching works, but flattening this with early returns will make the control flow easier to maintain.

Proposed refactor
 const handleDeleteClick = (
   hackathonId: string,
   type: 'draft' | 'hackathon'
 ) => {
-  if (type === 'hackathon') {
-    const published = publishedHackathons.find(h => h.id === hackathonId);
-    if (published) {
-      setHackathonToDelete({
-        id: hackathonId,
-        title: published.name || 'Untitled Hackathon',
-        type: 'hackathon',
-      });
-      setDeleteDialogOpen(true);
-    }
-  } else {
-    const draft = draftHackathons.find(d => d.id === hackathonId);
-    if (draft) {
-      setHackathonToDelete({
-        id: hackathonId,
-        title: draft.data.information?.name || 'Untitled Hackathon',
-        type: 'draft',
-      });
-      setDeleteDialogOpen(true);
-    }
-  }
+  if (type === 'hackathon') {
+    const published = publishedHackathons.find(h => h.id === hackathonId);
+    if (!published) return;
+    setHackathonToDelete({
+      id: hackathonId,
+      title: published.name || 'Untitled Hackathon',
+      type: 'hackathon',
+    });
+    setDeleteDialogOpen(true);
+    return;
+  }
+
+  const draft = draftHackathons.find(d => d.id === hackathonId);
+  if (!draft) return;
+  setHackathonToDelete({
+    id: hackathonId,
+    title: draft.data.information?.name || 'Untitled Hackathon',
+    type: 'draft',
+  });
+  setDeleteDialogOpen(true);
 };

As per coding guidelines **/*.{js,jsx,ts,tsx}: “Use early returns to improve code clarity”.

🤖 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 167 - 191,
Refactor handleDeleteClick to use early returns: first branch on the type (if
type === 'hackathon') then find the published item via publishedHackathons.find;
if not found return immediately, otherwise call setHackathonToDelete({ id:
hackathonId, title: published.name || 'Untitled Hackathon', type: 'hackathon' })
and setDeleteDialogOpen(true) and return; for the 'draft' path find the draft
from draftHackathons, return if missing, otherwise call setHackathonToDelete({
id: hackathonId, title: draft.data.information?.name || 'Untitled Hackathon',
type: 'draft' }) and setDeleteDialogOpen(true). Ensure no nested if blocks
remain and keep existing variable names (handleDeleteClick, publishedHackathons,
draftHackathons, setHackathonToDelete, setDeleteDialogOpen).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/`(landing)/organizations/[id]/hackathons/page.tsx:
- Around line 203-205: The page is firing a duplicate success toast: remove the
extra toast.success call in this component (the one that shows `"${title}" has
been permanently deleted.`) because useDeleteHackathon already emits the toast
on success; locate and delete that toast.success invocation in the component (or
alternatively modify the call site to pass a flag into useDeleteHackathon to
disable the hook's toast and keep the page toast), referencing the toast.success
line in this file and the useDeleteHackathon hook to ensure only one success
notification is produced.

---

Nitpick comments:
In `@app/`(landing)/organizations/[id]/hackathons/page.tsx:
- Around line 167-191: Refactor handleDeleteClick to use early returns: first
branch on the type (if type === 'hackathon') then find the published item via
publishedHackathons.find; if not found return immediately, otherwise call
setHackathonToDelete({ id: hackathonId, title: published.name || 'Untitled
Hackathon', type: 'hackathon' }) and setDeleteDialogOpen(true) and return; for
the 'draft' path find the draft from draftHackathons, return if missing,
otherwise call setHackathonToDelete({ id: hackathonId, title:
draft.data.information?.name || 'Untitled Hackathon', type: 'draft' }) and
setDeleteDialogOpen(true). Ensure no nested if blocks remain and keep existing
variable names (handleDeleteClick, publishedHackathons, draftHackathons,
setHackathonToDelete, setDeleteDialogOpen).

In `@hooks/hackathon/use-delete-hackathon.ts`:
- Around line 19-25: Convert the function declaration export function
useDeleteHackathon({...}: UseDeleteHackathonOptions) to a const arrow export:
declare const useDeleteHackathon: (opts: UseDeleteHackathonOptions) =>
ReturnType and assign an arrow function to it, keeping the same parameter
destructuring and body; ensure you add an explicit return type (the hook’s
return type used elsewhere in the codebase) and keep the existing export
behavior so references to useDeleteHackathon continue to work.

In `@lib/api/hackathons/draft.ts`:
- Around line 41-45: Duplicate interface DeleteHackathonResponse exists in this
module; delete the local declaration and instead import and reuse the single
exported DeleteHackathonResponse from the core module where it’s defined, or
re-export that core type if this module needs to expose it; ensure any
references in this file use the imported type and update the module exports
accordingly to avoid type duplication and drift.

ℹ️ 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.

Run ID: d789430e-1491-4f49-bb1e-5eaeb389d45d

📥 Commits

Reviewing files that changed from the base of the PR and between d0eb566 and a8a1c78.

📒 Files selected for processing (4)
  • app/(landing)/organizations/[id]/hackathons/page.tsx
  • hooks/hackathon/use-delete-hackathon.ts
  • lib/api/hackathons/draft.ts
  • lib/api/hackathons/index.ts
💤 Files with no reviewable changes (1)
  • lib/api/hackathons/index.ts

Comment thread app/(landing)/organizations/[id]/hackathons/page.tsx
Benjtalkshow

This comment was marked as off-topic.

@Benjtalkshow
Benjtalkshow merged commit d3f5153 into boundlessfi:main Mar 4, 2026
4 of 6 checks passed
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.

Hackathon Draft Deletion Failure (Endpoint Mismatch)

3 participants