-
-
Notifications
You must be signed in to change notification settings - Fork 19
Add task statuses #3057
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add task statuses #3057
Conversation
WalkthroughThis update introduces a comprehensive task board status system, including database migrations for status enums, templates, and enhanced task list metadata. The frontend is refactored to support new status-based workflows, including new board views (status-grouped), interactive drag-and-drop for lists and tasks, inline editing, and template-driven board creation. Types and API utilities are expanded accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant BoardForm
participant StatusTemplates
participant Supabase
participant BoardView
User->>BoardForm: Open create board dialog
BoardForm->>StatusTemplates: Fetch available templates
StatusTemplates-->>BoardForm: Return templates
User->>BoardForm: Select template & submit
BoardForm->>Supabase: Create board with template_id
Supabase-->>BoardForm: Board created, lists auto-generated via trigger
BoardForm-->>BoardView: Show new board with lists by status
sequenceDiagram
participant User
participant BoardView
participant EnhancedTaskList
participant Supabase
User->>BoardView: Drag task to new list/status
BoardView->>EnhancedTaskList: onDragEnd
EnhancedTaskList->>Supabase: Update task list/status, archive if needed
Supabase-->>EnhancedTaskList: Success/failure
EnhancedTaskList-->>BoardView: Invalidate queries, update UI
Suggested labels
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsxOops! Something went wrong! :( ESLint: 9.28.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@typescript-eslint/parser' imported from /eslint.config.mjs apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-summary.tsxOops! Something went wrong! :( ESLint: 9.28.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@typescript-eslint/parser' imported from /eslint.config.mjs apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/kanban.tsxOops! Something went wrong! :( ESLint: 9.28.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@typescript-eslint/parser' imported from /eslint.config.mjs
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
🔭 Outside diff range comments (1)
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx (1)
113-124
:⚠️ Potential issueEnhance delete error handling and cache invalidation
The delete function should provide user feedback on errors and invalidate relevant queries for consistency.
async function handleDelete() { try { setIsLoading(true); const supabase = createClient(); - await supabase.from('workspace_boards').delete().eq('id', board.id); + const { error } = await supabase + .from('workspace_boards') + .delete() + .eq('id', board.id); + + if (error) throw error; + + // Invalidate workspace boards list + queryClient.invalidateQueries({ queryKey: ['workspace-boards'] }); router.push('../'); } catch (error) { console.error('Failed to delete board:', error); + toast({ + title: 'Failed to delete board', + description: error instanceof Error ? error.message : 'Please try again', + variant: 'destructive', + }); } finally { setIsLoading(false); } }🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 117-117: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L117
Added line #L117 was not covered by tests
🧹 Nitpick comments (21)
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-summary.tsx (1)
137-137
: Spacing adjustment looks good.The reduced gap provides a more compact layout for the board summary cards.
Note: Static analysis indicates this line isn't covered by tests, though CSS changes typically don't require direct test coverage.
🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 137-137: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-summary.tsx#L137
Added line #L137 was not covered by testsapps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/enhanced-task-list.tsx (2)
76-81
: Consider using icon components instead of emojis for better cross-platform consistency.Emojis may render differently across platforms and browsers, potentially causing UI inconsistencies. Consider using icon components from your UI library for better control and accessibility.
-const statusIcons = { - not_started: '⚪', - active: '🔵', - done: '🟢', - closed: '🟣', -}; +import { Circle, CircleCheck, CircleDot, CircleX } from '@tuturuuu/ui/icons'; + +const statusIcons = { + not_started: <Circle className="h-4 w-4 text-gray-400" />, + active: <CircleDot className="h-4 w-4 text-blue-500" />, + done: <CircleCheck className="h-4 w-4 text-green-500" />, + closed: <CircleX className="h-4 w-4 text-purple-500" />, +};
370-393
: Extract inline SVG to a reusable icon component.The inline SVG for the hidden tasks indicator should be extracted to maintain consistency with other icons and improve code organization.
Create a new icon component:
// In your icons directory export const EyeOff = ({ className, ...props }) => ( <svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24" {...props} > <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L8.465 8.465m1.413 1.413L18.75 18.75m-7.036-7.036L12 12m-1.036-1.036L9.465 9.465m9.193 9.193L20.75 20.75M4.222 4.222l16.556 16.556" /> </svg> );Then use it in the component:
-<svg - className="h-6 w-6 text-dynamic-purple/60" - fill="none" - stroke="currentColor" - viewBox="0 0 24 24" -> - <path - strokeLinecap="round" - strokeLinejoin="round" - strokeWidth={2} - d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L8.465 8.465m1.413 1.413L18.75 18.75m-7.036-7.036L12 12m-1.036-1.036L9.465 9.465m9.193 9.193L20.75 20.75M4.222 4.222l16.556 16.556" - /> -</svg> +<EyeOff className="h-6 w-6 text-dynamic-purple/60" />apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/status-grouped-board.tsx (3)
36-50
: Document the default value for hideTasksMode in the interface.The
hideTasksMode
prop defaults totrue
but this isn't clear from the interface definition. Consider adding JSDoc or adjusting the type definition for clarity.interface Props { lists: TaskList[]; tasks: Task[]; boardId: string; onUpdate: () => void; + /** Whether to hide individual tasks (defaults to true) */ hideTasksMode?: boolean; }
154-205
: Add documentation for the optimistic update strategy.The optimistic updates improve UX but the strategy should be documented for maintainability.
Add a comment before the function:
+ /** + * Handles drag over events with optimistic updates for immediate visual feedback. + * Updates are reverted in onDragEnd if the operation is cancelled or fails. + */ function onDragOver(event: DragOverEvent) {
346-358
: Extract inline SVG to maintain consistency.Similar to the previous file, this inline SVG should be extracted to a reusable component.
Create an icon component for the board structure icon and import it instead of using inline SVG.
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx (2)
26-28
: Remove unnecessary comment.The comment about the Supabase client adds no value and should be removed.
const handleUpdate = async () => { - // const supabase = createClient(); // Not needed for current implementation - // Refresh both tasks and lists🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 26-27: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L26-L27
Added lines #L26 - L27 were not covered by tests
36-69
: Eliminate duplicate code in the switch statement.The default case duplicates the 'status-grouped' case. Use fall-through to avoid repetition.
const renderView = () => { switch (currentView) { case 'status-grouped': - return ( - <StatusGroupedBoard - lists={board.lists} - tasks={board.tasks} - boardId={board.id} - onUpdate={handleUpdate} - hideTasksMode={true} - /> - ); - case 'kanban': - return ( - <KanbanBoard - boardId={board.id} - tasks={board.tasks} - isLoading={false} - /> - ); - case 'list': - return <ListView board={board} />; default: return ( <StatusGroupedBoard lists={board.lists} tasks={board.tasks} boardId={board.id} onUpdate={handleUpdate} hideTasksMode={true} /> ); + case 'kanban': + return ( + <KanbanBoard + boardId={board.id} + tasks={board.tasks} + isLoading={false} + /> + ); + case 'list': + return <ListView board={board} />; } };🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 36-69: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L36-L69
Added lines #L36 - L69 were not covered by testsapps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task-list.tsx (1)
40-45
: Consider using proper icons for better accessibilityWhile emojis work, consider using proper SVG icons from your icon library for better accessibility, consistency, and professional appearance. Icons would also scale better and support theming.
Example implementation:
-const statusIcons = { - not_started: '⚪', - active: '🔵', - done: '🟢', - closed: '🟣', -}; +import { Circle, PlayCircle, CheckCircle2, XCircle } from '@tuturuuu/ui/icons'; + +const statusIcons = { + not_started: Circle, + active: PlayCircle, + done: CheckCircle2, + closed: XCircle, +};Then update the usage:
-<span className="text-sm">{statusIcon}</span> +{(() => { + const Icon = statusIcons[column.status] || Circle; + return <Icon className="h-4 w-4 text-muted-foreground" />; +})()}apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/form.tsx (3)
37-39
: Remove unnecessary ESLint disable commentThe
onFinish
parameter is actually used in the component (lines 104, 120), so the ESLint disable comment is unnecessary.- // eslint-disable-next-line no-unused-vars onFinish?: (data: z.infer<typeof FormSchema>) => void;
47-52
: Consider making template icons more flexibleThe
templateIcons
mapping uses hardcoded template names, which could break if template names change in the database. Consider using a more flexible approach.-const templateIcons = { - 'Basic Kanban': Crown, - 'Software Development': Users, - 'Content Creation': FileText, - 'Sales Pipeline': TrendingUp, -}; +const templateIcons: Record<string, typeof Crown> = { + 'Basic Kanban': Crown, + 'Software Development': Users, + 'Content Creation': FileText, + 'Sales Pipeline': TrendingUp, +}; + +// Or better, include icon type in template data from backend
91-132
: Consider migrating edit functionality to React QueryThe form uses React Query mutation for creating boards but legacy fetch API for editing. Consider creating a
useUpdateBoard
mutation hook for consistency and better error handling.This would provide consistent error handling, loading states, and cache invalidation across both operations. Would you like me to help create the
useUpdateBoard
mutation hook?apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx (1)
65-87
: Optimize statistics calculation with single iterationThe current implementation iterates through tasks multiple times. Consider calculating all statistics in a single pass for better performance, especially with large task lists.
const stats = useMemo(() => { const totalTasks = board.tasks.length; const totalLists = board.lists.length; - const completedTasks = board.tasks.filter((task) => { - const taskList = board.lists.find((list) => list.id === task.list_id); - return taskList?.status === 'done' || taskList?.status === 'closed'; - }).length; - const activeTasks = board.tasks.filter((task) => { - const taskList = board.lists.find((list) => list.id === task.list_id); - return taskList?.status === 'active'; - }).length; + + // Create a map for O(1) list lookups + const listMap = new Map(board.lists.map(list => [list.id, list])); + + // Single pass through tasks + let completedTasks = 0; + let activeTasks = 0; + + board.tasks.forEach(task => { + const taskList = listMap.get(task.list_id); + if (taskList?.status === 'done' || taskList?.status === 'closed') { + completedTasks++; + } else if (taskList?.status === 'active') { + activeTasks++; + } + }); + const completionRate = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0; return { totalTasks, totalLists, completedTasks, activeTasks, completionRate, }; }, [board.tasks, board.lists]);🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 65-112: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L65-L112
Added lines #L65 - L112 were not covered by testsapps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task-list-form.tsx (1)
55-68
: Remove redundant default case for better type safety.Since all values of
TaskBoardStatus
are explicitly handled, the default case is unnecessary and prevents TypeScript from catching missing cases if new statuses are added.function getDefaultColorForStatus(status: TaskBoardStatus): SupportedColor { switch (status) { case 'not_started': return 'GRAY'; case 'active': return 'BLUE'; case 'done': return 'GREEN'; case 'closed': return 'PURPLE'; - default: - return 'GRAY'; } }apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/list-view.tsx (2)
208-247
: Extract priority configuration to reduce render overhead.The
priorityConfig
object is recreated on every render. Extract it as a module-level constant for better performance.Move the configuration outside the component:
+const PRIORITY_CONFIG = { + 1: { + label: 'High', + color: 'text-dynamic-red/80', + bgColor: 'bg-dynamic-red/10', + borderColor: 'border-dynamic-red/30', + }, + 2: { + label: 'Medium', + color: 'text-dynamic-yellow/80', + bgColor: 'bg-dynamic-yellow/10', + borderColor: 'border-dynamic-yellow/30', + }, + 3: { + label: 'Low', + color: 'text-dynamic-green/80', + bgColor: 'bg-dynamic-green/10', + borderColor: 'border-dynamic-green/30', + }, +} as const; export function ListView({ board }: Props) { // ... component code ... function renderPriority(priority: number) { - const priorityConfig = { - 1: { /* ... */ }, - 2: { /* ... */ }, - 3: { /* ... */ }, - }; - - const config = priorityConfig[priority as keyof typeof priorityConfig]; + const config = PRIORITY_CONFIG[priority as keyof typeof PRIORITY_CONFIG]; if (!config) return null;
249-276
: Extract date status configuration for performance.Similar to the priority configuration, the
statusConfig
object is recreated on every call.Extract as a constant:
+const DATE_STATUS_CONFIG = { + overdue: { color: 'text-dynamic-red/80', icon: AlertTriangle }, + today: { color: 'text-dynamic-blue/80', icon: Clock }, + upcoming: { color: 'text-muted-foreground', icon: Calendar }, + completed: { color: 'text-muted-foreground', icon: Calendar }, +} as const; function renderDateCell(date: string | null, isEndDate = false) { if (!date) return null; const status = getDateStatus(date, false); const formattedDate = formatDate(date); - const statusConfig = { - overdue: { color: 'text-dynamic-red/80', icon: AlertTriangle }, - today: { color: 'text-dynamic-blue/80', icon: Clock }, - upcoming: { color: 'text-muted-foreground', icon: Calendar }, - completed: { color: 'text-muted-foreground', icon: Calendar }, - }; - - const config = statusConfig[status]; + const config = DATE_STATUS_CONFIG[status]; const Icon = config.icon;apps/db/supabase/migrations/20250608140008_add_task_statuses.sql (1)
191-198
: Ensure users are informed about automatic task archival.This migration automatically archives all tasks in lists with 'done' or 'closed' status. While logical, this could be unexpected behavior for existing users.
Consider adding a migration note or changelog entry to inform users about this automatic archival behavior. You might also want to add a comment in the migration explaining the rationale.
apps/web/src/lib/task-helper.ts (3)
151-151
: Remove console.log statements before production deployment.The extensive console logging added for debugging should be removed or wrapped in a debug flag to avoid cluttering production logs.
Consider using a debug flag:
- console.log('🔄 Starting moveTask:', { taskId, newListId }); + if (process.env.NODE_ENV === 'development') { + console.log('🔄 Starting moveTask:', { taskId, newListId }); + }Also applies to: 161-161, 165-165, 171-174, 198-198, 202-206
487-491
: Remove console.log statements from mutation hook.Similar to the moveTask function, these debug logs should be removed or conditionally enabled.
Also applies to: 496-497, 518-519, 533-534, 547-548
685-685
: Consider increasing staleTime for relatively static data.Status templates are unlikely to change frequently. Consider increasing the staleTime to reduce unnecessary refetches.
- staleTime: 10 * 60 * 1000, // 10 minutes + staleTime: 60 * 60 * 1000, // 1 hourpackages/types/src/supabase.ts (1)
3477-3477
: Consider adding type safety for thestatuses
field.The
statuses
field uses a genericJson
type, which doesn't provide compile-time type safety. Consider defining a specific interface for the status structure to ensure consistency across templates.You could define a more specific type for the statuses field:
type StatusDefinition = { id: string; name: string; color?: string; position: number; type: 'not_started' | 'active' | 'done' | 'closed'; }; // Then use: statuses: StatusDefinition[];
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
apps/db/supabase/migrations/20250608140008_add_task_statuses.sql
(1 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-client.tsx
(0 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx
(2 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-summary.tsx
(1 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx
(1 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/list-view.tsx
(8 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/enhanced-task-list.tsx
(1 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/kanban.tsx
(6 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/status-grouped-board.tsx
(1 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/status-section.tsx
(1 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task-actions.tsx
(2 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task-list-form.tsx
(2 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task-list.tsx
(5 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task.tsx
(6 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/form.tsx
(2 hunks)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/page.tsx
(1 hunks)apps/web/src/lib/task-helper.ts
(8 hunks)packages/types/src/primitives/TaskBoard.ts
(4 hunks)packages/types/src/supabase.ts
(23 hunks)
💤 Files with no reviewable changes (1)
- apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-client.tsx
🧰 Additional context used
🧬 Code Graph Analysis (4)
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task-list-form.tsx (1)
packages/types/src/primitives/TaskBoard.ts (1)
TaskBoardStatus
(3-3)
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/form.tsx (5)
packages/types/src/primitives/TaskBoard.ts (1)
TaskBoard
(22-32)apps/web/src/lib/task-helper.ts (2)
useStatusTemplates
(678-687)useCreateBoardWithTemplate
(689-719)packages/ui/src/components/ui/sonner.tsx (1)
toast
(29-29)packages/ui/src/components/ui/form.tsx (6)
Form
(181-181)FormField
(184-184)FormItem
(185-185)FormLabel
(186-186)FormControl
(182-182)FormMessage
(187-187)packages/ui/src/components/ui/badge.tsx (1)
Badge
(49-49)
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx (4)
packages/types/src/primitives/TaskBoard.ts (3)
TaskBoard
(22-32)Task
(48-65)TaskList
(34-46)apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task.tsx (1)
Task
(60-60)packages/ui/src/components/ui/badge.tsx (1)
Badge
(49-49)packages/ui/src/components/ui/dropdown-menu.tsx (4)
DropdownMenu
(241-241)DropdownMenuTrigger
(255-255)DropdownMenuContent
(243-243)DropdownMenuItem
(245-245)
apps/web/src/lib/task-helper.ts (2)
packages/types/src/primitives/TaskBoard.ts (4)
TaskBoardStatusTemplate
(5-13)TaskBoard
(22-32)TaskBoardStatus
(3-3)TaskList
(34-46)packages/ui/src/components/ui/sonner.tsx (1)
toast
(29-29)
🪛 GitHub Check: codecov/patch
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-summary.tsx
[warning] 137-137: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-summary.tsx#L137
Added line #L137 was not covered by tests
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/list-view.tsx
[warning] 5-5: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/list-view.tsx#L5
Added line #L5 was not covered by tests
[warning] 14-14: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/list-view.tsx#L14
Added line #L14 was not covered by tests
[warning] 17-17: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/list-view.tsx#L17
Added line #L17 was not covered by tests
[warning] 19-20: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/list-view.tsx#L19-L20
Added lines #L19 - L20 were not covered by tests
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx
[warning] 3-19: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L3-L19
Added lines #L3 - L19 were not covered by tests
[warning] 21-29: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L21-L29
Added lines #L21 - L29 were not covered by tests
[warning] 37-38: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L37-L38
Added lines #L37 - L38 were not covered by tests
[warning] 45-45: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L45
Added line #L45 was not covered by tests
[warning] 49-49: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L49
Added line #L49 was not covered by tests
[warning] 52-53: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L52-L53
Added lines #L52 - L53 were not covered by tests
[warning] 55-55: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L55
Added line #L55 was not covered by tests
[warning] 58-58: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L58
Added line #L58 was not covered by tests
[warning] 60-62: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L60-L62
Added lines #L60 - L62 were not covered by tests
[warning] 65-112: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L65-L112
Added lines #L65 - L112 were not covered by tests
[warning] 117-117: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L117
Added line #L117 was not covered by tests
[warning] 126-142: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L126-L142
Added lines #L126 - L142 were not covered by tests
[warning] 144-249: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L144-L249
Added lines #L144 - L249 were not covered by tests
[warning] 252-276: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L252-L276
Added lines #L252 - L276 were not covered by tests
[warning] 278-325: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-header.tsx#L278-L325
Added lines #L278 - L325 were not covered by tests
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx
[warning] 4-4: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L4
Added line #L4 was not covered by tests
[warning] 6-6: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L6
Added line #L6 was not covered by tests
[warning] 14-16: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L14-L16
Added lines #L14 - L16 were not covered by tests
[warning] 22-23: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L22-L23
Added lines #L22 - L23 were not covered by tests
[warning] 26-27: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L26-L27
Added lines #L26 - L27 were not covered by tests
[warning] 29-34: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L29-L34
Added lines #L29 - L34 were not covered by tests
[warning] 36-69: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L36-L69
Added lines #L36 - L69 were not covered by tests
[warning] 72-72: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L72
Added line #L72 was not covered by tests
[warning] 74-76: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L74-L76
Added lines #L74 - L76 were not covered by tests
[warning] 78-80: apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/_components/board-views.tsx#L78-L80
Added lines #L78 - L80 were not covered by tests
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (28)
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/page.tsx (1)
51-51
: LGTM!Adding the
requireExpansion
prop to show the feature summary in expanded state by default.apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/kanban.tsx (4)
17-25
: Good sensor simplification.Consolidating to a single PointerSensor with activation distance simplifies the drag-and-drop setup while maintaining both mouse and touch support.
Also applies to: 98-102
55-67
: Excellent backward compatibility handling.The column enhancement maintains the
title
property for backward compatibility while adopting the full TaskList objects with their new status and color properties.
225-248
: Smart optimization to prevent unnecessary mutations.Adding the check to only perform the move mutation when the target list differs from the original prevents redundant API calls and potential race conditions.
283-297
: Well-structured status-based sorting.The sorting logic clearly prioritizes lists by status (not_started → active → done → closed) and then by position within each status group, providing a logical board layout.
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task-list.tsx (2)
13-15
: Clean interface extensionThe
Column
interface properly extendsTaskList
, inheriting the necessary properties (color, status, position) as documented.
26-38
: Well-structured color mappingThe
colorClasses
mapping provides consistent styling for all supported colors with appropriate opacity values for borders and backgrounds.apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/form.tsx (1)
188-404
: Excellent template selection implementationThe template selection UI is well-designed with:
- Proper loading states with skeletons
- Clear blank board option
- Accessible radio group implementation
- Informative template previews with color-coded statuses
- Good responsive design with
@container
queriesapps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/task.tsx (7)
1-90
: Well-structured component setup with appropriate imports.The new imports and state management setup align well with the enhanced functionality. Good separation of concerns with dedicated state variables for different UI states.
143-164
: Robust inline editing implementation.Good validation with
trim()
to prevent empty names and proper handling of the optional description field.
179-207
: Clean date handling implementation.Proper use of ISO string format for date storage and correct null handling for date removal.
253-280
: Well-designed priority indicator with good accessibility.Nice touch using
text-gray-900
for the yellow background to ensure proper contrast. The priority labels are clear and user-friendly.
342-387
: Excellent inline editing UX with keyboard shortcuts.The implementation includes thoughtful touches like autoFocus, Enter/Escape key handling, and proper state restoration on cancel.
435-552
: Comprehensive date picker with excellent UX.Great implementation with quick date options covering common use cases and a full calendar for custom dates. The popover positioning and controlled state management are well handled.
756-793
: Safe delete implementation with proper confirmation.Good UX with clear confirmation message showing the task name and loading feedback during the operation.
apps/web/src/app/[locale]/(dashboard)/[wsId]/tasks/boards/[boardId]/status-section.tsx (3)
1-82
: Well-organized status configuration and drag-drop setup.Clean separation of status metadata into dedicated objects. The
useDroppable
integration follows the library's patterns correctly.
95-125
: Clear and informative status header design.Good use of badges to display counts and the conditional "Tasks hidden" indicator provides clear feedback to users.
183-204
: Proper enforcement of closed list limitation.Good implementation of the business rule limiting closed status to one list. The disabled state and explanatory text provide clear feedback to users.
packages/types/src/primitives/TaskBoard.ts (2)
1-21
: Well-designed type system for status workflows.The template-based approach provides good flexibility for different board configurations. The
allow_multiple
field inTaskBoardStatusDefinition
properly supports business rules like the single closed list limitation.
30-56
: Good use of nullable pattern for end_date.The change from
end_date?: string
toend_date?: string | null
properly distinguishes between unset and explicitly cleared dates, which aligns with the date removal functionality in the UI.apps/db/supabase/migrations/20250608140008_add_task_statuses.sql (2)
84-104
:✅ Verification successful
Verify the 'deleted' column exists in task_lists table.
The trigger references a
deleted
column for soft delete functionality, but this column is not defined in the current migration.Run the following script to verify the column exists:
🏁 Script executed:
#!/bin/bash # Description: Check if 'deleted' column exists in task_lists table definition # Search for task_lists table creation or alteration adding deleted column rg -B 5 -A 10 "CREATE TABLE.*task_lists|ALTER TABLE.*task_lists.*ADD.*deleted" --glob "*.sql" # Also check for any soft delete implementations rg "deleted.*BOOLEAN|soft.*delete" --glob "*.sql" -A 2 -B 2Length of output: 2835
Deleted column exists in
task_lists
tableThe
deleted
column is already defined in the initial migration, so theensure_single_closed_list
trigger can safely reference it.• apps/db/supabase/migrations/20230202082703_remote_commit.sql: defines
deleted boolean DEFAULT false
ontask_lists
1-13
:✅ Verification successful
Verify uuid-ossp extension is installed.
The migration uses
uuid_generate_v4()
which requires the uuid-ossp extension.Run the following script to verify the extension exists:
🏁 Script executed:
#!/bin/bash # Description: Check if uuid-ossp extension is created in other migrations # Search for uuid-ossp extension creation rg -A 2 "CREATE EXTENSION.*uuid-ossp" --glob "*.sql" # Also check for the newer gen_random_uuid() function usage as alternative rg "gen_random_uuid" --glob "*.sql"Length of output: 11078
uuid-ossp extension already created
- Verified that
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"
is present inapps/db/supabase/migrations/20230202082703_remote_commit.sql
, souuid_generate_v4()
will work without additional setup.No changes required.
apps/web/src/lib/task-helper.ts (3)
168-169
: Excellent implementation of status-based task archiving.The logic to automatically archive tasks when moved to 'done' or 'closed' lists is a smart feature that maintains data consistency.
594-618
: Good validation for closed status constraint.The implementation correctly enforces that only one list per board can have the 'closed' status, preventing data inconsistency.
663-672
: Good implementation of list grouping by status.The reduce function efficiently groups task lists by their status, making it easy to display status-grouped boards.
packages/types/src/supabase.ts (3)
3504-3511
: Well-designed task list enhancements!The new fields (
color
,position
,status
) are properly typed and nullable, ensuring backward compatibility. The use of the enum type forstatus
provides good type safety.Also applies to: 3522-3523, 3534-3535
3816-3816
: Template relationship properly implemented!The
template_id
field and its foreign key relationship totask_board_status_templates
are correctly configured. The nullable field ensures backward compatibility for existing boards.Also applies to: 3826-3826, 3836-3836, 3861-3867
3216-3217
:❓ Verification inconclusive
Verify the impact of function signature reorderings.
Multiple function signatures have been reordered, which could be breaking changes for existing code. For example:
create_ai_chat
: parameter order changedgenerate_cross_app_token
: parameters reorderedget_daily_income_expense
: both parameters and return fields reorderedPlease ensure that all consumers of these functions have been updated accordingly.
Run the following script to check for potential usage of these functions:
Also applies to: 3223-3226, 3237-3238, 3244-3249
🏁 Script executed:
#!/bin/bash # Description: Search for usage of functions with reordered signatures # Check for create_ai_chat usage echo "=== Checking create_ai_chat usage ===" rg -A 2 "create_ai_chat\s*\(" --type ts --type tsx --type js --type jsx # Check for generate_cross_app_token usage echo -e "\n=== Checking generate_cross_app_token usage ===" rg -A 2 "generate_cross_app_token\s*\(" --type ts --type tsx --type js --type jsx # Check for get_daily_income_expense usage echo -e "\n=== Checking get_daily_income_expense usage ===" rg -A 2 "get_daily_income_expense\s*\(" --type ts --type tsx --type js --type jsx # Check for other affected functions echo -e "\n=== Checking other affected functions ===" rg -A 2 "(get_challenge_stats|get_monthly_income_expense|get_workspace_users|get_workspace_transactions_count)\s*\(" --type ts --type tsx --type js --type jsxLength of output: 920
🏁 Script executed:
#!/bin/bash # Re-run usage search without relying on built-in file type definitions patterns=( "create_ai_chat" "generate_cross_app_token" "get_daily_income_expense" "get_challenge_stats" "get_monthly_income_expense" "get_workspace_users" "get_workspace_transactions_count" ) for p in "${patterns[@]}"; do echo "=== Checking ${p} usage ===" rg -n "${p}\s*\(" --glob "*.ts" --glob "*.tsx" --glob "*.js" --glob "*.jsx" doneLength of output: 1778
Verify external consumers for signature reordering
The following exported functions in packages/types/src/supabase.ts have had their parameters and/or return-value fields reordered, which is a breaking change for any callers relying on positional arguments or tuple-style destructuring:
- create_ai_chat
- generate_cross_app_token
- get_daily_income_expense
- get_challenge_stats
- get_monthly_income_expense
- get_workspace_users
- get_workspace_transactions_count
No internal usage was found within this repo, so please manually confirm that all external clients or dependent packages have updated their calls (and any destructuring of return values) to match the new signatures. Consider adding a migration guide and bumping the major version to clearly communicate these breaking changes.
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Chores
Style