Wire kanban board component to real boards API #6
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ldraney/pal-e-app!6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "3-kanban-board-ui"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Replace the static card list on
/boards/[slug]with a full interactive kanban board ported from the playground prototype. Adds drag-and-drop (desktop + mobile), board tabs, note-type accent colors, optimistic API mutations, and a dark theme across the entire app.Changes
src/lib/api.ts-- AddmoveItem()function forPATCH /boards/{slug}/items/{id}and updateapiFetchto acceptRequestInitoptionssrc/routes/api/boards/[slug]/items/[id]/+server.ts-- New proxy API route so browser-side code can call the backend move endpointsrc/routes/boards/[slug]/+page.server.ts-- Load both board detail AND boards list (for tabs) viaPromise.allsrc/routes/boards/[slug]/+page.svelte-- Full kanban rewrite: desktop HTML5 DnD, touch long-press drag, tap-to-move fallback, optimistic state updates, note-type color badges (plan/phase/issue/todo/project/repo), project/points/labels badges, Svelte 5 runessrc/routes/+layout.svelte-- Dark theme (bg-[#0a0a14], border-[#1a1a2e])src/routes/+page.svelte-- Dark theme for root pagesrc/routes/boards/+page.svelte-- Dark theme for boards listsrc/app.css-- Add overscroll-behavior and font smoothingTest Plan
/boards-- dark themed grid of board cards/api/boards/{slug}/items/{id}and persistsnpm run check-- 0 errorsnpm run lint-- 0 errorsnpm run build-- succeedsReview Checklist
npm run check-- 0 errors, 0 warnings)npm run lint-- 0 errors)npm run build)<style>blocks -- all styles converted to Tailwind 4 utilitiesRelated
html-playground/4-sprint-board/Replace the static card list on /boards/[slug] with a full kanban board featuring drag-and-drop (desktop HTML5 DnD + touch long-press + tap-to-move), board tabs for navigation between boards, note-type accent colors, and a dark theme matching the playground prototype. - Add moveItem() to api.ts for PATCH /boards/{slug}/items/{id} - Create /api/boards/[slug]/items/[id] proxy route for browser-side calls - Update server loader to return both board detail and boards list - Port drag-and-drop logic from playground with optimistic UI updates - Convert all inline styles to Tailwind 4 utility classes - Use Svelte 5 runes ($state, $derived, $effect, $props) - Add card type differentiation (plan/phase/issue/todo/project/repo colors) - Switch layout, root page, boards list to dark theme (bg-[#0a0a14]) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>PR #6 Review
BLOCKERS
1. Proxy error response leaks internal cluster URL to browser
In
src/routes/api/boards/[slug]/items/[id]/+server.ts(line 26), the catch block forwards the raw error message to the client:The
apiFetchfunction insrc/lib/api.ts(line 54) constructs error messages that include the full internal URL:This means a failed PATCH will return
"API request failed: 404 Not Found (http://pal-e-docs.pal-e-docs.svc.cluster.local:8000/boards/...)"directly to the browser. This leaks the internal Kubernetes service name, namespace, and port.Fix: Replace with a generic message in the proxy catch block:
2. Proxy does not validate
positionfieldIn
+server.tsline 22,body.positionis passed through without validation:While
columnis validated as a non-empty string (line 14-16),positionaccepts any value -- a string, object, array, or negative number would all pass through. The TypeScript type (position?: number) provides no runtime protection.Fix: Add validation:
position: typeof body.position === 'number' ? body.position : undefinedNITS
1.
apiFetchheader spread ordering is fragileBecause
...initspreads afterheaders, any caller passinginit.headerswould silently replace (not merge) the defaultAcceptandContent-Typeheaders. Currently no caller does this, but this is a latent footgun. Consider merging headers explicitly:2.
app.cssuses a rawbodystyle block instead of TailwindThe requirement is "All Tailwind 4 -- no inline
<style>blocks." Thebodyblock insrc/app.css:This is a plain CSS rule, not inline
<style>(so it technically passes), but it could use@layer baseor Tailwind's@applyto stay idiomatic. Minor -- not blocking.3. Ghost card has redundant
box-shadowin both class and styleThe touch ghost element (line 217-218 in the page.svelte) applies
shadow-2xlvia Tailwind class ANDbox-shadow: 0 8px 24px rgba(0,0,0,0.5)in the inline style. The inline style wins, making the Tailwind class dead code.4.
--tab-colorCSS variable set but never usedIn the board tabs (line 239), each tab sets
--tab-color: {DEFAULT_COLOR}in its style attribute, but no Tailwind class or CSS rule referencesvar(--tab-color). The playground used it in<style>selectors, but since those were converted to inline styles, the variable is orphaned.5. Empty
onkeydownhandlersMultiple elements have
onkeydown={() => {}}(lines 290, 327). These exist to suppress a11y warnings about interactive elements needing keyboard handlers, but they provide no actual keyboard interaction. Consider adding Enter/Space handling for keyboard-only users, or at minimum add anaria-labelto communicate the drag-and-drop nature. Non-blocking.SOP COMPLIANCE
3-kanban-board-uireferences Issue #3Closes #3present; playground source referenced.envin.gitignore, no credentials in source<style>blocks -- all styles converted to Tailwind utilities$state,$derived,$effect,$propsthroughoutVERDICT: NOT APPROVED
Two blockers need fixes before merge:
positionfield passthrough in proxy (input validation)The kanban implementation itself is solid -- faithful port from the playground with proper TypeScript typing, optimistic updates with rollback, and clean separation between server and browser code. The five nits above are non-blocking suggestions for follow-up.