diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..390a286 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,12 @@ +{ + "permissions": { + "allow": [ + "Bash(npx tsc *)", + "Bash(git add *)", + "Bash(git commit *)", + "Bash(git push *)", + "Bash(npx eslint *)", + "Bash(npm run *)" + ] + } +} diff --git a/app/(app)/products/[id]/sprint/planning/page.tsx b/app/(app)/products/[id]/sprint/planning/page.tsx index dae6818..dc4aa1f 100644 --- a/app/(app)/products/[id]/sprint/planning/page.tsx +++ b/app/(app)/products/[id]/sprint/planning/page.tsx @@ -5,7 +5,6 @@ import { SessionData, sessionOptions } from '@/lib/session' import { prisma } from '@/lib/prisma' import { SplitPane } from '@/components/split-pane/split-pane' import { PlanningLeft } from '@/components/sprint/planning-left' -import { TaskList } from '@/components/sprint/task-list' import type { Task } from '@/components/sprint/task-list' import { SprintHeader } from '@/components/sprint/sprint-header' import type { SprintStory } from '@/components/sprint/sprint-backlog' diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index c1a9806..bd8650f 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -1,7 +1,5 @@ import Link from 'next/link' import { loginAction } from '@/actions/auth' -import { Button } from '@/components/ui/button' -import { Input } from '@/components/ui/input' import { AuthForm } from '@/components/auth/auth-form' export default function LoginPage() { diff --git a/components/backlog/pbi-list.tsx b/components/backlog/pbi-list.tsx index abd8534..a8e25cf 100644 --- a/components/backlog/pbi-list.tsx +++ b/components/backlog/pbi-list.tsx @@ -24,7 +24,6 @@ import { import { CSS } from '@dnd-kit/utilities' import { toast } from 'sonner' import { Button } from '@/components/ui/button' -import { DemoTooltip } from '@/components/shared/demo-tooltip' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' diff --git a/components/backlog/story-panel.tsx b/components/backlog/story-panel.tsx index 195013f..8d647c4 100644 --- a/components/backlog/story-panel.tsx +++ b/components/backlog/story-panel.tsx @@ -115,8 +115,8 @@ function SortableStoryBlock({ // --- Story detail slide-over --- function StoryDetailSheet({ story, - productId, - pbiId, + productId: _productId, + pbiId: _pbiId, onClose, isDemo, }: { diff --git a/components/settings/role-manager.tsx b/components/settings/role-manager.tsx index 306a830..23fd59b 100644 --- a/components/settings/role-manager.tsx +++ b/components/settings/role-manager.tsx @@ -26,7 +26,7 @@ export function RoleManager({ currentRoles, isDemo }: RoleManagerProps) { function toggle(role: string) { setSelected(prev => { const next = new Set(prev) - next.has(role) ? next.delete(role) : next.add(role) + if (next.has(role)) { next.delete(role) } else { next.add(role) } return next }) setSaved(false) diff --git a/components/split-pane/split-pane.tsx b/components/split-pane/split-pane.tsx index 3cf78f2..c99264a 100644 --- a/components/split-pane/split-pane.tsx +++ b/components/split-pane/split-pane.tsx @@ -19,19 +19,18 @@ export function SplitPane({ minSize = 200, }: SplitPaneProps) { const containerRef = useRef(null) - const [split, setSplit] = useState(defaultSplit) - const [isDragging, setIsDragging] = useState(false) - const [isMobile, setIsMobile] = useState(false) - const [activeTab, setActiveTab] = useState<'left' | 'right'>('left') - - // Load stored split on mount - useEffect(() => { + const [split, setSplit] = useState(() => { + if (typeof window === 'undefined') return defaultSplit const stored = localStorage.getItem(`split-pane:${storageKey}`) if (stored) { const val = parseFloat(stored) - if (!isNaN(val) && val > 0 && val < 100) setSplit(val) + if (!isNaN(val) && val > 0 && val < 100) return val } - }, [storageKey]) + return defaultSplit + }) + const [isDragging, setIsDragging] = useState(false) + const [isMobile, setIsMobile] = useState(false) + const [activeTab, setActiveTab] = useState<'left' | 'right'>('left') // Detect mobile useEffect(() => { diff --git a/components/sprint/sprint-backlog.tsx b/components/sprint/sprint-backlog.tsx index 77e7bac..a74aab0 100644 --- a/components/sprint/sprint-backlog.tsx +++ b/components/sprint/sprint-backlog.tsx @@ -3,7 +3,7 @@ import { useState, useTransition, useEffect } from 'react' import { useRouter } from 'next/navigation' import { - DndContext, DragEndEvent, DragOverEvent, DragStartEvent, DragOverlay, + DndContext, DragEndEvent, KeyboardSensor, PointerSensor, useSensor, useSensors, closestCenter, } from '@dnd-kit/core' import { @@ -101,7 +101,7 @@ interface SprintBacklogLeftProps { selectedStoryId: string | null } -export function SprintBacklogLeft({ sprintId, stories, isDemo, onSelectStory, selectedStoryId }: SprintBacklogLeftProps) { +export function SprintBacklogLeft({ sprintId, stories, isDemo, onSelectStory }: SprintBacklogLeftProps) { const { sprintStoryOrder, initSprint, reorderSprintStories, rollbackSprint, removeStoryFromSprint } = useSprintStore() const [, startTransition] = useTransition() @@ -186,7 +186,7 @@ export function SprintBacklogRight({ sprintId, pbisWithStories, sprintStoryIds, function toggle(pbiId: string) { setCollapsed(prev => { const next = new Set(prev) - next.has(pbiId) ? next.delete(pbiId) : next.add(pbiId) + if (next.has(pbiId)) { next.delete(pbiId) } else { next.add(pbiId) } return next }) } diff --git a/components/sprint/sprint-header.tsx b/components/sprint/sprint-header.tsx index d24c5df..c9bbb8a 100644 --- a/components/sprint/sprint-header.tsx +++ b/components/sprint/sprint-header.tsx @@ -34,7 +34,7 @@ function SaveGoalButton() { return } -export function SprintHeader({ productId, productName, sprint, isDemo, sprintStories }: SprintHeaderProps) { +export function SprintHeader({ productId: _productId, productName, sprint, isDemo, sprintStories }: SprintHeaderProps) { const [editingGoal, setEditingGoal] = useState(false) const [completeOpen, setCompleteOpen] = useState(false) const [decisions, setDecisions] = useState>({}) diff --git a/components/sprint/start-sprint-button.tsx b/components/sprint/start-sprint-button.tsx index 76f6d6b..f0b951c 100644 --- a/components/sprint/start-sprint-button.tsx +++ b/components/sprint/start-sprint-button.tsx @@ -4,7 +4,6 @@ import { useState, useActionState } from 'react' import { useFormStatus } from 'react-dom' import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' -import { Input } from '@/components/ui/input' import { Textarea } from '@/components/ui/textarea' import { Dialog, diff --git a/components/sprint/task-list.tsx b/components/sprint/task-list.tsx index 2cd7c57..a88a7c2 100644 --- a/components/sprint/task-list.tsx +++ b/components/sprint/task-list.tsx @@ -3,7 +3,7 @@ import { useState, useTransition, useEffect, useActionState } from 'react' import { useFormStatus } from 'react-dom' import { - DndContext, DragEndEvent, DragOverlay, DragStartEvent, + DndContext, DragEndEvent, DragOverlay, KeyboardSensor, PointerSensor, useSensor, useSensors, closestCenter, } from '@dnd-kit/core' import { @@ -144,7 +144,7 @@ function CreateSubmitButton() { return } -export function TaskList({ storyId, sprintId, productId, tasks, isDemo }: TaskListProps) { +export function TaskList({ storyId, sprintId, productId: _productId, tasks, isDemo }: TaskListProps) { const { taskOrder, initTasks, reorderTasks, rollbackTasks } = useSprintStore() const [creating, setCreating] = useState(false) const [activeDragId, setActiveDragId] = useState(null) diff --git a/components/todos/todo-list.tsx b/components/todos/todo-list.tsx index 51b1ecc..fa2a5ca 100644 --- a/components/todos/todo-list.tsx +++ b/components/todos/todo-list.tsx @@ -6,8 +6,6 @@ import { toast } from 'sonner' import { Button } from '@/components/ui/button' import { DemoTooltip } from '@/components/shared/demo-tooltip' import { Input } from '@/components/ui/input' -import { Textarea } from '@/components/ui/textarea' -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { createTodoAction, toggleTodoAction, @@ -15,7 +13,6 @@ import { promoteTodoToPbiAction, promoteTodoToStoryAction, } from '@/actions/todos' -import { cn } from '@/lib/utils' interface Todo { id: string diff --git a/eslint.config.mjs b/eslint.config.mjs index 05e726d..c2c6d35 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,6 +5,15 @@ import nextTs from "eslint-config-next/typescript"; const eslintConfig = defineConfig([ ...nextVitals, ...nextTs, + { + rules: { + "@typescript-eslint/no-unused-vars": ["warn", { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + caughtErrorsIgnorePattern: "^_", + }], + }, + }, // Override default ignores of eslint-config-next. globalIgnores([ // Default ignores of eslint-config-next: diff --git a/prisma/neon.md b/prisma/neon.md new file mode 100644 index 0000000..e69de29