feat: implement GET /api/bounties/:id — bounty detail endpoint#41
feat: implement GET /api/bounties/:id — bounty detail endpoint#41kenchambers wants to merge 1 commit intodevasignhq:mainfrom
Conversation
Closes devasignhq#21 ## Summary Implements the GET /api/bounties/:id endpoint to return full bounty details including creator info, application count, assignee info, and current status. ### Backend (packages/api/src/index.ts) - Added GET /api/bounties/:id route to the Hono server - Proxies to the main DevAsign API (DEVASIGN_API_URL env var) - Forwards Authorization header for authenticated requests - Returns structured 404 when bounty not found - Returns 502 on upstream API failure with descriptive error - Input validated: rejects empty/missing IDs ### Types (packages/mobile/types.ts) - Added optional applicationCount?: number to Bounty interface - Added optional assignee?: { username, avatarUrl } | null to Bounty to represent the assigned developer if one exists ### Frontend (packages/mobile/pages/BountyDetail.tsx) - Replaced MOCK_BOUNTIES.find() with real fetch() to /api/bounties/:id - Added loading and error states for async data fetching - AbortController cleanup on component unmount - Shows applicationCount with pluralisation (e.g. '3 applications') - Shows assignee card with avatar and username when bounty is assigned - Shows 'Unassigned / Open for applications' when status is Open and no assignee exists - 'Apply for Bounty' CTA now only renders for Open, unassigned bounties ### Environment - DEVASIGN_API_URL: upstream API base URL (default: https://api.devasign.com)
🟡 AI Code Review ResultsStatus: Review Recommended 🟡 Merge Score: 75/100🟡 Recommendation: This is a solid feature implementation that successfully creates a new BFF endpoint and a corresponding frontend detail page. The code is well-structured, with good practices like ❌ Rules Violated (3)1. No console.log statements
🟡 Code should not contain console.log statements in production
💡 Code Suggestions (6)🔴 High Priority (2)
💭 Reasoning: Duplicating types across packages leads to maintenance overhead and potential inconsistencies. If the upstream API or the frontend type changes, this inline type will not be updated automatically, leading to silent runtime errors that TypeScript cannot catch. A shared Suggested Code:
💭 Reasoning: Automated tests are essential for ensuring the reliability of the API and preventing regressions. The manual 🟡 Medium Priority (1)
💭 Reasoning: Breaking down large components into smaller, focused ones is a core principle of React development. It makes the code easier to read, test, and reuse, and it isolates state and logic related to specific UI parts. 🔵 Low Priority (3)
💭 Reasoning: This approach is more idiomatic and avoids the non-null assertion, which can suppress legitimate type errors. It makes the intent clearer and is generally considered a safer pattern for conditionally adding properties to an object. Suggested Code:
💭 Reasoning: Displaying specific error messages from the API provides a better user experience and makes debugging easier. A generic 'Failed to load' message can be frustrating for users and developers alike. Suggested Code:
💭 Reasoning: Pull requests should be small and focused on a single, atomic change. This makes them easier to review, test, and merge, reducing the risk of introducing unrelated bugs. 📊 Review Metadata
|
Summary
Closes #21
Implements the
GET /api/bounties/:idendpoint to return full bounty details including creator info, application count, assignee info, and current status.Changes
Backend —
packages/api/src/index.tsGET /api/bounties/:idroute to the Hono serverDEVASIGN_API_URLenv var, defaults tohttps://api.devasign.com)Authorizationheader for authenticated requests404when the bounty is not found502on upstream API failure with a descriptive error message400Types —
packages/mobile/types.tsapplicationCount?: numbertoBountyinterfaceassignee?: { username: string; avatarUrl: string } | nullto represent the assigned developerFrontend —
packages/mobile/pages/BountyDetail.tsxMOCK_BOUNTIES.find()with a realfetch()call to/api/bounties/:idAbortControllercleanup on component unmount3 applications)Openand no assignee existsOpen, unassigned bountiesEnvironment Variable
DEVASIGN_API_URLhttps://api.devasign.comTesting