@emberai-engg/task-board 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/TaskBoard.tsx","../src/context/TaskBoardProvider.tsx","../src/services/taskBoardService.ts","../src/utils/constants.ts","../src/hooks/useTaskBoard.ts","../src/hooks/useTaskActions.ts","../src/hooks/useShareLink.ts","../src/components/SkeletonPulse.tsx","../src/components/KanbanColumn.tsx","../src/components/TaskCard.tsx","../src/utils/helpers.ts","../src/components/PriorityBadge.tsx","../src/icons/index.tsx","../src/components/TagBadge.tsx","../src/components/UserAvatar.tsx","../src/components/FilterBar.tsx","../src/components/NotificationBell.tsx","../src/components/CreateTaskModal.tsx","../src/components/TaskDetailPanel.tsx","../src/hooks/useTaskDetail.ts","../src/components/MentionText.tsx","../src/components/MentionTextarea.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { DragDropContext, type DropResult } from '@hello-pangea/dnd';\nimport type { Task } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { useTaskBoard } from '../hooks/useTaskBoard';\nimport { useTaskActions } from '../hooks/useTaskActions';\nimport { useShareLink } from '../hooks/useShareLink';\nimport { PREDEFINED_TAGS } from '../utils/constants';\nimport { BoardSkeleton } from './SkeletonPulse';\nimport { KanbanColumn } from './KanbanColumn';\nimport { FilterBar } from './FilterBar';\nimport { NotificationBell } from './NotificationBell';\nimport { CreateTaskModal } from './CreateTaskModal';\nimport { TaskDetailPanel } from './TaskDetailPanel';\nimport { PlusIcon, XIcon, FeedbackIcon } from '../icons';\n\nexport interface TaskBoardProps {\n /** Optional class name for the outer container */\n className?: string;\n /** Optional header content (e.g., feedback link) to render in the header bar */\n headerActions?: React.ReactNode;\n /** Callback when a task detail panel should open */\n onTaskOpen?: (task: Task) => void;\n /** Callback for the Share Feedback button. If not provided, the button is hidden. */\n onShareFeedback?: () => void;\n /** Render function for the task detail panel. If omitted, uses built-in TaskDetailPanel. */\n renderTaskDetail?: (props: { task: Task; onClose: () => void; onUpdate: () => void }) => React.ReactNode;\n /** Render function for the create task modal. If omitted, uses built-in CreateTaskModal. */\n renderCreateTask?: (props: { projectSlug: string; defaultStatus: string; onClose: () => void; onCreate: () => void }) => React.ReactNode;\n}\n\nexport function TaskBoard({\n className = \"\",\n headerActions,\n onTaskOpen,\n onShareFeedback,\n renderTaskDetail,\n renderCreateTask,\n}: TaskBoardProps) {\n const { columns, features, service } = useTaskBoardContext();\n\n const board = useTaskBoard();\n const actions = useTaskActions(board.tasks, board.setTasks, board.fetchTasks);\n const { copiedTaskId, copyShareLink } = useShareLink();\n\n const [selectedTask, setSelectedTask] = useState<Task | null>(null);\n const [createForStatus, setCreateForStatus] = useState(\"\");\n const [filterTags, setFilterTags] = useState<string[]>([]);\n\n // Handle shared task URL (?task=id)\n const [sharedTaskHandled, setSharedTaskHandled] = useState(false);\n useEffect(() => {\n if (sharedTaskHandled || !board.selectedProject || board.boardLoading) return;\n if (typeof window === 'undefined') return;\n const params = new URLSearchParams(window.location.search);\n const taskId = params.get(\"task\");\n if (!taskId) return;\n setSharedTaskHandled(true);\n let cancelled = false;\n (async () => {\n try {\n const task = await service.getTask(taskId);\n if (cancelled) return;\n setSelectedTask(task);\n service.markTaskRead(taskId).catch(() => {});\n const url = new URL(window.location.href);\n url.searchParams.delete(\"task\");\n window.history.replaceState({}, \"\", url.toString());\n } catch {\n if (!cancelled) board.setError(\"Could not open shared task.\");\n }\n })();\n return () => { cancelled = true; };\n }, [board.selectedProject, board.boardLoading, sharedTaskHandled, service]);\n\n // Update URL when project changes\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (board.selectedProject && board.projects.length > 1) {\n const url = new URL(window.location.href);\n url.searchParams.set(\"project\", board.selectedProject);\n window.history.replaceState({}, \"\", url.toString());\n }\n }, [board.selectedProject, board.projects]);\n\n const handleDragEnd = useCallback((result: DropResult) => {\n const { draggableId, source, destination } = result;\n if (!destination) return;\n if (source.droppableId === destination.droppableId && source.index === destination.index) return;\n\n actions.moveTask(\n draggableId,\n source.droppableId,\n destination.droppableId,\n source.index,\n destination.index\n );\n }, [actions]);\n\n const handleTaskClick = (task: Task) => {\n setSelectedTask(task);\n onTaskOpen?.(task);\n actions.markTaskRead(task.id);\n // Optimistically clear unread\n if (task.has_unread) {\n board.setTasks((prev) => {\n const updated = { ...prev };\n const col = updated[task.status];\n if (col) {\n updated[task.status] = col.map((t) =>\n t.id === task.id ? { ...t, has_unread: false } : t\n );\n }\n return updated;\n });\n board.setColumnUnreads((prev) => ({\n ...prev,\n [task.status]: Math.max(0, (prev[task.status] || 0) - 1),\n }));\n }\n };\n\n const handleOpenTaskFromNotification = async (taskId: string, projectSlug: string) => {\n if (board.selectedProject !== projectSlug) {\n board.setSelectedProject(projectSlug);\n }\n try {\n const task = await service.getTask(taskId);\n setSelectedTask(task);\n service.markTaskRead(taskId).catch(() => {});\n } catch {\n board.setError(\"Could not open task.\");\n }\n };\n\n const predefinedValues = PREDEFINED_TAGS.map((p) => p.value);\n\n // Built-in create/detail handlers\n const handleCreateClose = () => setCreateForStatus(\"\");\n const handleCreateDone = () => { board.fetchTasks(); board.showSuccess(\"Task created\"); };\n const handleDetailClose = () => setSelectedTask(null);\n\n return (\n <div className={`flex flex-col h-full ${className}`}>\n {/* Header */}\n <div className=\"mb-4 sm:mb-6 shrink-0\">\n <div className=\"flex items-center justify-between mb-1 sm:mb-2\">\n <h1 className=\"text-2xl sm:text-3xl font-medium text-neutral-900 tracking-tight\">\n Task Board\n </h1>\n <div className=\"flex items-center gap-2\">\n {onShareFeedback && (\n <button\n onClick={onShareFeedback}\n className=\"flex items-center gap-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 px-3 py-2 sm:py-2.5 rounded-lg border border-neutral-200 hover:border-neutral-300 transition-colors\"\n >\n <FeedbackIcon size={16} />\n <span className=\"hidden sm:inline\">Share Feedback</span>\n </button>\n )}\n {headerActions}\n {features.notifications && (\n <NotificationBell onOpenTask={handleOpenTaskFromNotification} />\n )}\n {board.projects.length > 0 && (\n <button\n onClick={() => setCreateForStatus(\"backlog\")}\n className=\"flex items-center gap-1.5 sm:gap-2 text-xs font-semibold text-white bg-[#FF5E00] hover:bg-[#E05200] px-3 sm:px-4 py-2 sm:py-2.5 rounded-lg transition-colors shadow-sm\"\n >\n <PlusIcon size={16} />\n <span className=\"hidden sm:inline\">New Task</span>\n <span className=\"sm:hidden\">New</span>\n </button>\n )}\n </div>\n </div>\n <p className=\"text-neutral-500 font-light text-sm sm:text-lg\">\n Track and manage work across projects.\n </p>\n </div>\n\n {/* Success / Error */}\n {board.successMessage && (\n <div className=\"mb-4 p-3 bg-green-50 border border-green-200 rounded-lg text-green-700 text-sm\">\n {board.successMessage}\n </div>\n )}\n {board.error && (\n <div className=\"mb-4 p-3 bg-red-50 border border-red-200 rounded-lg text-red-600 text-sm flex items-center justify-between\">\n {board.error}\n <button onClick={() => board.setError(\"\")} className=\"text-red-400 hover:text-red-600\">\n <XIcon size={16} />\n </button>\n </div>\n )}\n\n {board.projects.length === 0 ? (\n <div className=\"flex-1 flex items-center justify-center\">\n <div className=\"text-center\">\n <h2 className=\"text-xl font-medium text-neutral-900 mb-2\">No Projects Available</h2>\n <p className=\"text-neutral-500\">You don't have access to any projects yet.</p>\n </div>\n </div>\n ) : (\n <>\n {/* Filter bar */}\n <FilterBar\n projects={board.projects}\n selectedProject={board.selectedProject}\n onSelectProject={board.setSelectedProject}\n filterTags={filterTags}\n onSetFilterTags={setFilterTags}\n />\n\n {/* Board */}\n {board.boardLoading ? (\n <BoardSkeleton />\n ) : (\n <div className=\"flex-1 min-h-0 eb-tb-board-scroll overflow-x-auto overflow-y-hidden pb-4\">\n <DragDropContext onDragEnd={handleDragEnd}>\n <div className=\"flex gap-4 min-w-max h-full\">\n {columns.map((col) => {\n const allColumnTasks = board.tasks[col.key] || [];\n const columnTasks = filterTags.length > 0\n ? allColumnTasks.filter((t) => {\n const taskTags = t.tags || [];\n return filterTags.some((f) => {\n if (f === \"__other__\") return taskTags.some((tag) => !predefinedValues.includes(tag));\n return taskTags.includes(f);\n });\n })\n : allColumnTasks;\n\n return (\n <KanbanColumn\n key={col.key}\n column={col}\n tasks={columnTasks}\n totalCount={board.columnTotals[col.key] || 0}\n unreadCount={board.columnUnreads[col.key] || 0}\n loadingMore={board.loadingMore[col.key] || false}\n onAddTask={() => setCreateForStatus(col.key)}\n onTaskClick={handleTaskClick}\n onTaskShare={(taskId, e) => copyShareLink(taskId, board.selectedProject)}\n copiedTaskId={copiedTaskId}\n onLoadMore={() => board.loadMoreTasks(col.key)}\n />\n );\n })}\n </div>\n </DragDropContext>\n </div>\n )}\n </>\n )}\n\n {/* Create Task Modal — render prop override or built-in */}\n {createForStatus && (\n renderCreateTask\n ? renderCreateTask({\n projectSlug: board.selectedProject,\n defaultStatus: createForStatus,\n onClose: handleCreateClose,\n onCreate: handleCreateDone,\n })\n : <CreateTaskModal\n projectSlug={board.selectedProject}\n defaultStatus={createForStatus}\n onClose={handleCreateClose}\n onCreate={handleCreateDone}\n />\n )}\n\n {/* Task Detail — render prop override or built-in */}\n {selectedTask && (\n renderTaskDetail\n ? renderTaskDetail({\n task: selectedTask,\n onClose: handleDetailClose,\n onUpdate: board.fetchTasks,\n })\n : <TaskDetailPanel\n task={selectedTask}\n projectSlug={board.selectedProject}\n onClose={handleDetailClose}\n onUpdate={board.fetchTasks}\n />\n )}\n </div>\n );\n}\n","import React, { createContext, useContext, useMemo } from 'react';\nimport type { ApiClient, TaskBoardUser, Project, ColumnConfig, PriorityConfig, TagConfig, Task } from '../types';\nimport { TaskBoardService, createTaskBoardService } from '../services/taskBoardService';\nimport { DEFAULT_COLUMNS, DEFAULT_PRIORITIES, PREDEFINED_TAGS } from '../utils/constants';\n\nexport interface TaskBoardConfig {\n /** Axios-like API client with auth headers pre-configured */\n apiClient: ApiClient;\n /** Current logged-in user */\n user: TaskBoardUser;\n /** Available projects (if not provided, derived from user.apps) */\n projects?: Project[];\n /** Column configuration (defaults to 8-column kanban) */\n columns?: ColumnConfig[];\n /** Priority levels (defaults to Critical/High/Medium/Low) */\n priorities?: PriorityConfig[];\n /** Predefined tags (defaults to 6 built-in tags) */\n tags?: TagConfig[];\n /** Base API path (defaults to '/api/v1/taskboard') */\n apiBasePath?: string;\n\n /** Callbacks */\n onTaskCreate?: (task: Task) => void;\n onTaskUpdate?: (task: Task) => void;\n onTaskDelete?: (taskId: string) => void;\n onError?: (error: Error) => void;\n onNavigate?: (path: string) => void;\n\n /** Feature flags */\n features?: {\n dragAndDrop?: boolean;\n comments?: boolean;\n mentions?: boolean;\n notifications?: boolean;\n internalComments?: boolean;\n tags?: boolean;\n sharing?: boolean;\n filters?: boolean;\n unreadIndicators?: boolean;\n };\n}\n\nexport interface TaskBoardContextValue {\n service: TaskBoardService;\n user: TaskBoardUser;\n projects: Project[];\n columns: ColumnConfig[];\n priorities: PriorityConfig[];\n tags: TagConfig[];\n config: TaskBoardConfig;\n features: Required<NonNullable<TaskBoardConfig['features']>>;\n}\n\nconst TaskBoardContext = createContext<TaskBoardContextValue | null>(null);\n\nexport function useTaskBoardContext(): TaskBoardContextValue {\n const ctx = useContext(TaskBoardContext);\n if (!ctx) {\n throw new Error('useTaskBoardContext must be used within a <TaskBoardProvider>');\n }\n return ctx;\n}\n\nexport function TaskBoardProvider({\n children,\n ...config\n}: TaskBoardConfig & { children: React.ReactNode }) {\n const service = useMemo(\n () => createTaskBoardService(config.apiClient, config.apiBasePath),\n [config.apiClient, config.apiBasePath]\n );\n\n const features = useMemo(\n () => ({\n dragAndDrop: config.features?.dragAndDrop ?? true,\n comments: config.features?.comments ?? true,\n mentions: config.features?.mentions ?? true,\n notifications: config.features?.notifications ?? true,\n internalComments: config.features?.internalComments ?? true,\n tags: config.features?.tags ?? true,\n sharing: config.features?.sharing ?? true,\n filters: config.features?.filters ?? true,\n unreadIndicators: config.features?.unreadIndicators ?? true,\n }),\n [config.features]\n );\n\n const value = useMemo<TaskBoardContextValue>(\n () => ({\n service,\n user: config.user,\n projects: config.projects ?? [],\n columns: config.columns ?? DEFAULT_COLUMNS,\n priorities: config.priorities ?? DEFAULT_PRIORITIES,\n tags: config.tags ?? PREDEFINED_TAGS,\n config,\n features,\n }),\n [service, config, features]\n );\n\n return (\n <TaskBoardContext.Provider value={value}>\n {children}\n </TaskBoardContext.Provider>\n );\n}\n","import type {\n ApiClient,\n Project,\n Task,\n TaskDetailResponse,\n ColumnResponse,\n Notification,\n NotificationCountResponse,\n MentionUser,\n Comment,\n CreateTaskPayload,\n UpdateTaskPayload,\n CreateCommentPayload,\n EditCommentPayload,\n} from '../types';\n\nexport interface TaskBoardService {\n // ─── Tasks ───\n listTasks(projectSlug: string, perColumn?: number): Promise<Record<string, ColumnResponse>>;\n listColumnTasks(projectSlug: string, statusKey: string, offset: number, limit: number): Promise<Task[]>;\n getTask(taskId: string): Promise<TaskDetailResponse>;\n createTask(data: CreateTaskPayload): Promise<Task>;\n updateTask(taskId: string, data: UpdateTaskPayload): Promise<Task>;\n deleteTask(taskId: string): Promise<void>;\n markTaskRead(taskId: string): Promise<void>;\n\n // ─── Comments ───\n listComments(taskId: string): Promise<Comment[]>;\n addComment(taskId: string, data: CreateCommentPayload): Promise<Comment>;\n editComment(taskId: string, commentId: string, data: EditCommentPayload): Promise<Comment>;\n deleteComment(taskId: string, commentId: string): Promise<void>;\n\n // ─── Projects ───\n listProjects(): Promise<Project[]>;\n\n // ─── Mentions ───\n searchMentionUsers(query: string): Promise<MentionUser[]>;\n\n // ─── Notifications ───\n getNotificationCount(): Promise<number>;\n listNotifications(limit?: number): Promise<Notification[]>;\n markNotificationRead(notificationId: string): Promise<void>;\n markAllNotificationsRead(): Promise<void>;\n}\n\nexport function createTaskBoardService(\n apiClient: ApiClient,\n basePath: string = '/api/v1/taskboard'\n): TaskBoardService {\n return {\n // ─── Tasks ───\n\n async listTasks(projectSlug, perColumn = 10) {\n const { data } = await apiClient.get<Record<string, ColumnResponse>>(\n `${basePath}/tasks?project_slug=${encodeURIComponent(projectSlug)}&per_column=${perColumn}`\n );\n return data;\n },\n\n async listColumnTasks(projectSlug, statusKey, offset, limit) {\n const { data } = await apiClient.get<Task[]>(\n `${basePath}/tasks/column?project_slug=${encodeURIComponent(projectSlug)}&status_key=${encodeURIComponent(statusKey)}&offset=${offset}&limit=${limit}`\n );\n return data;\n },\n\n async getTask(taskId) {\n const { data } = await apiClient.get<TaskDetailResponse>(`${basePath}/tasks/${taskId}`);\n return data;\n },\n\n async createTask(payload) {\n const { data } = await apiClient.post<Task>(`${basePath}/tasks`, payload);\n return data;\n },\n\n async updateTask(taskId, payload) {\n const { data } = await apiClient.patch<Task>(`${basePath}/tasks/${taskId}`, payload);\n return data;\n },\n\n async deleteTask(taskId) {\n await apiClient.delete(`${basePath}/tasks/${taskId}`);\n },\n\n async markTaskRead(taskId) {\n await apiClient.post(`${basePath}/tasks/${taskId}/read`);\n },\n\n // ─── Comments ───\n\n async listComments(taskId) {\n const { data } = await apiClient.get<Comment[]>(`${basePath}/tasks/${taskId}/comments`);\n return data;\n },\n\n async addComment(taskId, payload) {\n const { data } = await apiClient.post<Comment>(`${basePath}/tasks/${taskId}/comments`, payload);\n return data;\n },\n\n async editComment(taskId, commentId, payload) {\n const { data } = await apiClient.patch<Comment>(\n `${basePath}/tasks/${taskId}/comments/${commentId}`,\n payload\n );\n return data;\n },\n\n async deleteComment(taskId, commentId) {\n await apiClient.delete(`${basePath}/tasks/${taskId}/comments/${commentId}`);\n },\n\n // ─── Projects ───\n\n async listProjects() {\n const { data } = await apiClient.get<Project[]>(`${basePath}/projects`);\n return data;\n },\n\n // ─── Mentions ───\n\n async searchMentionUsers(query) {\n const { data } = await apiClient.get<MentionUser[]>(\n `${basePath}/mentions/users?q=${encodeURIComponent(query)}`\n );\n return data;\n },\n\n // ─── Notifications ───\n\n async getNotificationCount() {\n const { data } = await apiClient.get<NotificationCountResponse>(\n `${basePath}/notifications/count`\n );\n return data.count;\n },\n\n async listNotifications(limit = 30) {\n const { data } = await apiClient.get<Notification[]>(\n `${basePath}/notifications?limit=${limit}`\n );\n return data;\n },\n\n async markNotificationRead(notificationId) {\n await apiClient.patch(`${basePath}/notifications/${notificationId}/read`);\n },\n\n async markAllNotificationsRead() {\n await apiClient.post(`${basePath}/notifications/read-all`);\n },\n };\n}\n","import type { ColumnConfig, PriorityConfig, TagConfig, DescriptionSectionConfig, StructuredDescription } from '../types';\n\nexport const DEFAULT_COLUMNS: ColumnConfig[] = [\n { key: \"backlog\", label: \"Backlog\", color: \"bg-neutral-400\", description: \"Tasks not yet scheduled\" },\n { key: \"blocked\", label: \"Blocked\", color: \"bg-red-500\", description: \"Waiting on a dependency\" },\n { key: \"queued\", label: \"Queued\", color: \"bg-blue-500\", description: \"Scheduled for this sprint\" },\n { key: \"in_progress\", label: \"In Progress\", color: \"bg-amber-500\", description: \"Actively being worked on\" },\n { key: \"in_testing\", label: \"In Testing\", color: \"bg-teal-500\", description: \"Under QA and validation\" },\n { key: \"client_review\", label: \"Client Review\", color: \"bg-purple-500\", description: \"Live & ready for client review\" },\n { key: \"changes_requested\", label: \"Changes Requested\", color: \"bg-orange-500\", description: \"Revisions needed from review\" },\n { key: \"approved\", label: \"Approved\", color: \"bg-green-500\", description: \"Signed off and complete\" },\n];\n\nexport const DEFAULT_PRIORITIES: PriorityConfig[] = [\n { value: \"urgent\", label: \"Critical\", className: \"bg-red-50 text-red-600 border-red-200\" },\n { value: \"high\", label: \"High\", className: \"bg-orange-50 text-orange-600 border-orange-200\" },\n { value: \"medium\", label: \"Medium\", className: \"bg-amber-50 text-amber-600 border-amber-200\" },\n { value: \"low\", label: \"Low\", className: \"bg-neutral-100 text-neutral-500 border-neutral-200\" },\n];\n\nexport const PREDEFINED_TAGS: TagConfig[] = [\n { value: \"traceability\", label: \"Traceability\", className: \"bg-blue-50 text-blue-600 border-blue-200\" },\n { value: \"info-architecture\", label: \"Info Architecture\", className: \"bg-purple-50 text-purple-600 border-purple-200\" },\n { value: \"ui-ux\", label: \"UI/UX\", className: \"bg-pink-50 text-pink-600 border-pink-200\" },\n { value: \"workflow-logic\", label: \"Workflow Logic\", className: \"bg-teal-50 text-teal-600 border-teal-200\" },\n { value: \"legal-reasoning\", label: \"Legal Reasoning\", className: \"bg-amber-50 text-amber-600 border-amber-200\" },\n { value: \"bug-fix\", label: \"Bug Fix\", className: \"bg-red-50 text-red-600 border-red-200\" },\n];\n\nexport const DESCRIPTION_SECTIONS: DescriptionSectionConfig[] = [\n { key: \"problem\", label: \"Problem\" },\n { key: \"user_story\", label: \"User Story\" },\n { key: \"proposed_behavior\", label: \"Proposed Behavior\" },\n { key: \"acceptance_criteria\", label: \"Acceptance Criteria\" },\n { key: \"open_questions\", label: \"Open Questions\" },\n];\n\nexport const EMPTY_DESCRIPTION: StructuredDescription = {\n problem: \"\",\n user_story: \"\",\n proposed_behavior: \"\",\n acceptance_criteria: \"\",\n open_questions: \"\",\n};\n\nexport const POSITION_GAP = 1000;\nexport const DEFAULT_PAGE_SIZE = 10;\nexport const NOTIFICATION_POLL_INTERVAL = 30000;\n","import { useState, useEffect, useCallback, useMemo, useRef } from 'react';\nimport type { Task, TasksByStatus, ColumnTotals, ColumnUnreads, Project } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { DEFAULT_PAGE_SIZE } from '../utils/constants';\n\nexport function useTaskBoard() {\n const { service, user, projects: configProjects, columns, config } = useTaskBoardContext();\n\n const [fetchedProjects, setFetchedProjects] = useState<Project[]>([]);\n\n // Fetch projects from API when none are provided via props\n useEffect(() => {\n if (configProjects.length > 0) return;\n let cancelled = false;\n (async () => {\n try {\n const data = await service.listProjects();\n if (!cancelled) setFetchedProjects(data);\n } catch {\n // Projects endpoint may not exist — fall back to empty\n }\n })();\n return () => { cancelled = true; };\n }, [configProjects, service]);\n\n const projects = configProjects.length > 0 ? configProjects : fetchedProjects;\n\n const [selectedProject, setSelectedProject] = useState(\"\");\n const [tasks, setTasks] = useState<TasksByStatus>({});\n const [columnTotals, setColumnTotals] = useState<ColumnTotals>({});\n const [columnUnreads, setColumnUnreads] = useState<ColumnUnreads>({});\n const [boardLoading, setBoardLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState<Record<string, boolean>>({});\n const [error, setError] = useState(\"\");\n const [successMessage, setSuccessMessage] = useState(\"\");\n\n // Auto-select project from URL or first available\n useEffect(() => {\n if (selectedProject || projects.length === 0) return;\n if (typeof window !== 'undefined') {\n const params = new URLSearchParams(window.location.search);\n const urlProject = params.get(\"project\");\n if (urlProject && projects.find((p) => p.slug === urlProject)) {\n setSelectedProject(urlProject);\n return;\n }\n }\n setSelectedProject(projects[0].slug);\n }, [projects, selectedProject]);\n\n const fetchTasks = useCallback(async () => {\n if (!selectedProject) return;\n setBoardLoading(true);\n try {\n const data = await service.listTasks(selectedProject, DEFAULT_PAGE_SIZE);\n const newTasks: TasksByStatus = {};\n const newTotals: ColumnTotals = {};\n const newUnreads: ColumnUnreads = {};\n for (const key of columns.map((c) => c.key)) {\n const col = data[key];\n if (col) {\n newTasks[key] = col.tasks || [];\n newTotals[key] = col.total || 0;\n newUnreads[key] = col.unread || 0;\n } else {\n newTasks[key] = [];\n newTotals[key] = 0;\n newUnreads[key] = 0;\n }\n }\n setTasks(newTasks);\n setColumnTotals(newTotals);\n setColumnUnreads(newUnreads);\n } catch {\n setError(\"Failed to load tasks\");\n } finally {\n setBoardLoading(false);\n }\n }, [selectedProject, service, columns]);\n\n useEffect(() => { fetchTasks(); }, [fetchTasks]);\n\n const loadMoreTasks = useCallback(async (statusKey: string) => {\n if (!selectedProject || loadingMore[statusKey]) return;\n const current = tasks[statusKey]?.length || 0;\n const total = columnTotals[statusKey] || 0;\n if (current >= total) return;\n\n setLoadingMore((prev) => ({ ...prev, [statusKey]: true }));\n try {\n const newTasks = await service.listColumnTasks(\n selectedProject, statusKey, current, DEFAULT_PAGE_SIZE\n );\n setTasks((prev) => ({\n ...prev,\n [statusKey]: [...(prev[statusKey] || []), ...newTasks],\n }));\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoadingMore((prev) => ({ ...prev, [statusKey]: false }));\n }\n }, [selectedProject, tasks, columnTotals, loadingMore, service, config]);\n\n const successTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n return () => {\n if (successTimeoutRef.current) clearTimeout(successTimeoutRef.current);\n };\n }, []);\n\n const showSuccess = (msg: string) => {\n setSuccessMessage(msg);\n if (successTimeoutRef.current) clearTimeout(successTimeoutRef.current);\n successTimeoutRef.current = setTimeout(() => setSuccessMessage(\"\"), 3000);\n };\n\n return {\n projects,\n selectedProject,\n setSelectedProject,\n tasks,\n setTasks,\n columnTotals,\n columnUnreads,\n setColumnUnreads,\n boardLoading,\n loadingMore,\n error,\n setError,\n successMessage,\n showSuccess,\n fetchTasks,\n loadMoreTasks,\n };\n}\n","import { useCallback, useRef } from 'react';\nimport type { Task, TasksByStatus, CreateTaskPayload, UpdateTaskPayload } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { POSITION_GAP } from '../utils/constants';\n\nexport function useTaskActions(\n tasks: TasksByStatus,\n setTasks: React.Dispatch<React.SetStateAction<TasksByStatus>>,\n fetchTasks: () => Promise<void>,\n) {\n const { service, config } = useTaskBoardContext();\n\n const tasksRef = useRef(tasks);\n tasksRef.current = tasks;\n\n const createTask = useCallback(async (data: CreateTaskPayload): Promise<Task> => {\n const task = await service.createTask(data);\n config.onTaskCreate?.(task);\n await fetchTasks();\n return task;\n }, [service, config, fetchTasks]);\n\n const updateTask = useCallback(async (taskId: string, data: UpdateTaskPayload): Promise<Task> => {\n const task = await service.updateTask(taskId, data);\n config.onTaskUpdate?.(task);\n await fetchTasks();\n return task;\n }, [service, config, fetchTasks]);\n\n const deleteTask = useCallback(async (taskId: string): Promise<void> => {\n await service.deleteTask(taskId);\n config.onTaskDelete?.(taskId);\n await fetchTasks();\n }, [service, config, fetchTasks]);\n\n const markTaskRead = useCallback(async (taskId: string): Promise<void> => {\n service.markTaskRead(taskId).catch(() => {});\n }, [service]);\n\n const moveTask = useCallback(async (\n taskId: string,\n sourceStatus: string,\n destStatus: string,\n sourceIndex: number,\n destIndex: number,\n ) => {\n const currentTasks = tasksRef.current;\n const sourceCol = [...(currentTasks[sourceStatus] || [])];\n const destCol = sourceStatus === destStatus ? sourceCol : [...(currentTasks[destStatus] || [])];\n\n const [movedTask] = sourceCol.splice(sourceIndex, 1);\n if (!movedTask) return;\n\n const updatedTask = { ...movedTask, status: destStatus };\n destCol.splice(destIndex, 0, updatedTask);\n\n // Calculate position\n let newPosition: number;\n if (destCol.length === 1) {\n newPosition = POSITION_GAP;\n } else if (destIndex === 0) {\n newPosition = (destCol[1]?.position ?? POSITION_GAP) - POSITION_GAP;\n } else if (destIndex === destCol.length - 1) {\n newPosition = (destCol[destCol.length - 2]?.position ?? 0) + POSITION_GAP;\n } else {\n const above = destCol[destIndex - 1]?.position ?? 0;\n const below = destCol[destIndex + 1]?.position ?? above + POSITION_GAP * 2;\n newPosition = (above + below) / 2;\n }\n updatedTask.position = newPosition;\n\n // Optimistic update\n const newTasks = { ...currentTasks };\n newTasks[sourceStatus] = sourceCol;\n if (sourceStatus !== destStatus) {\n newTasks[destStatus] = destCol;\n }\n setTasks(newTasks);\n\n // Persist\n try {\n await service.updateTask(taskId, { status: destStatus, position: newPosition });\n } catch {\n fetchTasks();\n }\n }, [setTasks, service, fetchTasks]);\n\n return { createTask, updateTask, deleteTask, markTaskRead, moveTask };\n}\n","import { useState, useCallback } from 'react';\n\nexport function useShareLink() {\n const [copiedTaskId, setCopiedTaskId] = useState<string | null>(null);\n\n const copyShareLink = useCallback((taskId: string, projectSlug: string) => {\n if (typeof window === 'undefined') return;\n const url = new URL(window.location.origin + window.location.pathname);\n url.searchParams.set(\"project\", projectSlug);\n url.searchParams.set(\"task\", taskId);\n navigator.clipboard.writeText(url.toString()).then(() => {\n setCopiedTaskId(taskId);\n setTimeout(() => setCopiedTaskId(null), 2000);\n });\n }, []);\n\n return { copiedTaskId, copyShareLink };\n}\n","import React from 'react';\n\nexport function SkeletonPulse({ className = \"\" }: { className?: string }) {\n return <div className={`animate-pulse rounded bg-neutral-200/60 ${className}`} />;\n}\n\nexport function SkeletonCard() {\n return (\n <div className=\"bg-white rounded-lg border border-neutral-200 p-3 space-y-2.5\">\n <SkeletonPulse className=\"h-4 w-3/4\" />\n <SkeletonPulse className=\"h-4 w-16 rounded-sm\" />\n <SkeletonPulse className=\"h-3 w-full\" />\n <SkeletonPulse className=\"h-3 w-2/3\" />\n <div className=\"flex items-center justify-between pt-1\">\n <SkeletonPulse className=\"h-2.5 w-12\" />\n <SkeletonPulse className=\"h-2.5 w-8\" />\n </div>\n </div>\n );\n}\n\nexport function BoardSkeleton() {\n const cardCounts = [3, 2, 2, 1, 1, 0, 1];\n return (\n <div className=\"flex-1 min-h-0 overflow-hidden pb-4\">\n <div className=\"flex gap-4 min-w-max h-full\">\n {cardCounts.map((count, i) => (\n <div key={i} className=\"w-[280px] flex flex-col shrink-0\">\n <div className=\"flex items-center gap-2 mb-3 px-1\">\n <SkeletonPulse className=\"w-2 h-2 rounded-full\" />\n <SkeletonPulse className=\"h-3 w-20\" />\n </div>\n <div className=\"flex-1 rounded-xl bg-neutral-100/50 p-2 space-y-2\">\n {Array.from({ length: count }).map((_, j) => (\n <SkeletonCard key={j} />\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import React, { useEffect, useRef } from 'react';\nimport { Droppable } from '@hello-pangea/dnd';\nimport type { Task, ColumnConfig } from '../types';\nimport { TaskCard } from './TaskCard';\nimport { SkeletonCard } from './SkeletonPulse';\nimport { PlusIcon } from '../icons';\n\nexport interface KanbanColumnProps {\n column: ColumnConfig;\n tasks: Task[];\n totalCount: number;\n unreadCount: number;\n loadingMore: boolean;\n onAddTask: () => void;\n onTaskClick: (task: Task) => void;\n onTaskShare: (taskId: string, e: React.MouseEvent) => void;\n copiedTaskId: string | null;\n onLoadMore: () => void;\n}\n\nfunction LoadMoreSentinel({ loading, onLoadMore, remaining }: { loading: boolean; onLoadMore: () => void; remaining: number }) {\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const el = sentinelRef.current;\n if (!el) return;\n const observer = new IntersectionObserver(\n ([entry]) => { if (entry.isIntersecting && !loading) onLoadMore(); },\n { threshold: 0.1 }\n );\n observer.observe(el);\n return () => observer.disconnect();\n }, [loading, onLoadMore]);\n\n const skeletonCount = loading ? Math.min(remaining, 10) : 0;\n\n return (\n <div ref={sentinelRef} className=\"space-y-2 pt-2\">\n {Array.from({ length: skeletonCount }).map((_, i) => (\n <SkeletonCard key={i} />\n ))}\n </div>\n );\n}\n\nexport function KanbanColumn({\n column,\n tasks,\n totalCount,\n unreadCount,\n loadingMore,\n onAddTask,\n onTaskClick,\n onTaskShare,\n copiedTaskId,\n onLoadMore,\n}: KanbanColumnProps) {\n return (\n <div className=\"w-[280px] flex flex-col shrink-0 h-full\">\n {/* Column header */}\n <div className=\"mb-3 px-1 shrink-0\">\n <div className=\"flex items-center gap-2\">\n <span className={`w-2 h-2 rounded-full ${column.color}`} />\n <h3 className=\"text-xs font-medium text-neutral-700 uppercase tracking-wide\">{column.label}</h3>\n {unreadCount > 0 && (\n <span className=\"relative group/unread-col w-4 h-4 rounded-full bg-[#FF5E00] text-white text-[9px] font-semibold flex items-center justify-center cursor-default\">\n {unreadCount}\n <span className=\"absolute left-1/2 -translate-x-1/2 top-full mt-1.5 px-2 py-1 text-[10px] font-medium text-white bg-neutral-800 rounded whitespace-nowrap opacity-0 pointer-events-none group-hover/unread-col:opacity-100 transition-opacity duration-75 z-10\">\n {unreadCount} unread {unreadCount === 1 ? \"task\" : \"tasks\"}\n </span>\n </span>\n )}\n <span className=\"text-[10px] text-neutral-400 ml-auto\">{totalCount}</span>\n <button\n onClick={onAddTask}\n className=\"ml-1 p-1 rounded-md text-neutral-400 hover:text-[#FF5E00] hover:bg-[#FF5E00]/10 transition-colors\"\n aria-label={`Add task to ${column.label}`}\n >\n <PlusIcon size={16} />\n </button>\n </div>\n <p className=\"text-[10px] text-neutral-400 mt-0.5 pl-4\">{column.description}</p>\n </div>\n\n {/* Droppable area */}\n <Droppable droppableId={column.key}>\n {(provided, snapshot) => (\n <div\n ref={provided.innerRef}\n {...provided.droppableProps}\n className={`flex-1 rounded-xl p-2 min-h-[120px] overflow-y-auto transition-colors ${\n snapshot.isDraggingOver ? \"bg-[#FF5E00]/5 ring-1 ring-[#FF5E00]/20\" : \"bg-neutral-100/50\"\n }`}\n >\n <div className=\"space-y-2\">\n {tasks.map((task, index) => (\n <TaskCard\n key={task.id}\n task={task}\n index={index}\n onClick={() => onTaskClick(task)}\n onShare={(e) => { e.stopPropagation(); onTaskShare(task.id, e); }}\n copied={copiedTaskId === task.id}\n />\n ))}\n {provided.placeholder}\n </div>\n\n {tasks.length < totalCount && (\n <LoadMoreSentinel\n loading={loadingMore}\n onLoadMore={onLoadMore}\n remaining={totalCount - tasks.length}\n />\n )}\n\n {tasks.length === 0 && (\n <div className=\"flex items-center justify-center h-20 text-xs text-neutral-400\">\n No tasks\n </div>\n )}\n </div>\n )}\n </Droppable>\n </div>\n );\n}\n","import React, { memo } from 'react';\nimport { Draggable } from '@hello-pangea/dnd';\nimport type { Task } from '../types';\nimport { PriorityBadge } from './PriorityBadge';\nimport { TagBadge } from './TagBadge';\nimport { UserAvatar } from './UserAvatar';\nimport { MessageSquareIcon, LinkIcon, CheckIcon } from '../icons';\nimport { formatDate, getDescriptionPreview, hasDescription } from '../utils/helpers';\n\nexport interface TaskCardProps {\n task: Task;\n index: number;\n onClick: () => void;\n onShare: (e: React.MouseEvent) => void;\n copied: boolean;\n}\n\nexport const TaskCard = memo(function TaskCard({ task, index, onClick, onShare, copied }: TaskCardProps) {\n return (\n <Draggable draggableId={task.id} index={index}>\n {(provided, snapshot) => (\n <div\n ref={provided.innerRef}\n {...provided.draggableProps}\n {...provided.dragHandleProps}\n onClick={onClick}\n className={`relative bg-white rounded-lg border p-3.5 cursor-pointer transition-all hover:shadow-md group/card ${\n snapshot.isDragging ? \"shadow-lg ring-2 ring-[#FF5E00]/20\" : \"\"\n } border-neutral-200`}\n >\n {/* Title + priority */}\n <div className=\"flex items-start justify-between gap-2.5\">\n <div className=\"flex items-start gap-1.5 flex-1 min-w-0\">\n {task.has_unread && (\n <span className=\"relative group/unread mt-[5px] w-1.5 h-1.5 rounded-full bg-[#FF5E00] shrink-0 cursor-default\">\n <span className=\"absolute left-1/2 -translate-x-1/2 bottom-full mb-1.5 px-2 py-1 text-[10px] font-medium text-white bg-neutral-800 rounded whitespace-nowrap opacity-0 pointer-events-none group-hover/unread:opacity-100 transition-opacity duration-75\">\n New activity\n </span>\n </span>\n )}\n <h4 className=\"text-[13px] font-medium text-neutral-900 leading-snug line-clamp-2\">\n {task.title}\n </h4>\n </div>\n <PriorityBadge priority={task.priority} />\n </div>\n\n {/* Tags */}\n {task.tags && task.tags.length > 0 && (\n <div className=\"mt-1.5 flex flex-wrap gap-1\">\n {task.tags.slice(0, 3).map((tag) => (\n <TagBadge key={tag} tag={tag} />\n ))}\n {task.tags.length > 3 && (\n <span className=\"text-[8px] text-neutral-400 px-1 py-px\">+{task.tags.length - 3}</span>\n )}\n </div>\n )}\n\n {/* Description preview */}\n {hasDescription(task.description) && (\n <p className=\"mt-2 text-[11px] text-neutral-400 leading-relaxed line-clamp-2\">\n {getDescriptionPreview(task.description)}\n </p>\n )}\n\n {/* Footer */}\n <div className=\"mt-3 flex items-center justify-between pt-2.5 border-t border-neutral-100\">\n <span className=\"text-[10px] text-neutral-400\">{formatDate(task.created_at)}</span>\n <div className=\"flex items-center gap-1.5\">\n <button\n onClick={onShare}\n className=\"opacity-0 group-hover/card:opacity-100 transition-opacity p-0.5 rounded text-neutral-300 hover:text-neutral-500 cursor-pointer\"\n title={copied ? \"Link copied!\" : \"Copy link\"}\n >\n {copied ? <CheckIcon size={12} /> : <LinkIcon size={12} />}\n </button>\n {task.comment_count > 0 && (\n <span className=\"flex items-center gap-0.5 text-[10px] text-neutral-400\">\n <MessageSquareIcon size={12} />\n {task.comment_count}\n </span>\n )}\n {task.created_by_name && (\n <UserAvatar name={task.created_by_name} size=\"xs\" showTooltip />\n )}\n </div>\n </div>\n </div>\n )}\n </Draggable>\n );\n});\n","import type { StructuredDescription, PriorityConfig, TagConfig } from '../types';\nimport { DEFAULT_PRIORITIES, PREDEFINED_TAGS, DESCRIPTION_SECTIONS } from './constants';\n\nexport function getPriorityStyle(priority: string): PriorityConfig {\n return DEFAULT_PRIORITIES.find((p) => p.value === priority) ?? DEFAULT_PRIORITIES[2];\n}\n\nexport function getTagStyle(tag: string): TagConfig {\n const predefined = PREDEFINED_TAGS.find((t) => t.value === tag);\n if (predefined) return predefined;\n const label = tag.charAt(0).toUpperCase() + tag.slice(1).replace(/-/g, \" \");\n return { value: tag, label, className: \"bg-neutral-100 text-neutral-500 border-neutral-200\" };\n}\n\nexport function getInitials(name: string): string {\n return name\n .split(\" \")\n .map((w) => w[0])\n .join(\"\")\n .toUpperCase()\n .slice(0, 2);\n}\n\nexport function parseDate(dateStr: string): Date {\n if (!dateStr) return new Date();\n const d = new Date(dateStr);\n if (isNaN(d.getTime()) && !dateStr.endsWith(\"Z\") && !dateStr.includes(\"+\")) {\n return new Date(dateStr + \"Z\");\n }\n return d;\n}\n\nexport function formatDate(dateStr: string): string {\n if (!dateStr) return \"\";\n const d = parseDate(dateStr);\n return d.toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\" });\n}\n\nexport function formatDateTime(dateStr: string): string {\n if (!dateStr) return \"\";\n const d = parseDate(dateStr);\n return d.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n}\n\nexport function getDescriptionPreview(desc: StructuredDescription | string | undefined): string {\n if (!desc) return \"\";\n if (typeof desc === \"string\") return desc;\n for (const section of DESCRIPTION_SECTIONS) {\n if (desc[section.key]?.trim()) return desc[section.key].trim();\n }\n return \"\";\n}\n\nexport function hasDescription(desc: StructuredDescription | string | undefined): boolean {\n if (!desc) return false;\n if (typeof desc === \"string\") return desc.trim().length > 0;\n return DESCRIPTION_SECTIONS.some((s) => desc[s.key]?.trim());\n}\n\nexport function getUserProjects(\n apps: string[],\n allProjects: { slug: string; name: string }[]\n): { slug: string; name: string }[] {\n if (apps.includes(\"all\")) return allProjects;\n return allProjects.filter((p) => apps.includes(p.slug));\n}\n","import React from 'react';\nimport { getPriorityStyle } from '../utils/helpers';\n\nexport interface PriorityBadgeProps {\n priority: string;\n size?: 'sm' | 'md';\n}\n\nexport function PriorityBadge({ priority, size = 'sm' }: PriorityBadgeProps) {\n const style = getPriorityStyle(priority);\n const sizeClass = size === 'sm'\n ? 'px-1.5 py-0.5 text-[9px]'\n : 'px-2.5 py-1 text-[10px]';\n\n return (\n <span className={`inline-flex items-center font-semibold uppercase tracking-wide rounded border ${style.className} ${sizeClass}`}>\n {style.label}\n </span>\n );\n}\n","import React from 'react';\n\ninterface IconProps {\n className?: string;\n size?: number;\n strokeWidth?: number;\n}\n\nexport const PlusIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" /><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n);\n\nexport const XIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" /><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\nexport const ChevronDownIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n);\n\nexport const MessageSquareIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n);\n\nexport const KanbanIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\" /><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\" /><path d=\"m9 14 2 2 4-4\" />\n </svg>\n);\n\nexport const LinkIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" /><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </svg>\n);\n\nexport const CheckIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\n\nexport const BellIcon: React.FC<IconProps> = ({ className = \"\", size = 24 }) => (\n <svg className={className} width={size} height={size} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.75}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0\" />\n </svg>\n);\n\nexport const FilterIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\" />\n </svg>\n);\n\nexport const PencilIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" />\n </svg>\n);\n\nexport const TrashIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M3 6h18\" /><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" /><path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n </svg>\n);\n\nexport const LockIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" /><path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n);\n\nexport const FeedbackIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" /><path d=\"M8 12h.01\" /><path d=\"M12 12h.01\" /><path d=\"M16 12h.01\" />\n </svg>\n);\n","import React from 'react';\nimport { getTagStyle } from '../utils/helpers';\nimport { XIcon } from '../icons';\n\nexport interface TagBadgeProps {\n tag: string;\n onRemove?: () => void;\n size?: 'sm' | 'md';\n}\n\nexport function TagBadge({ tag, onRemove, size = 'sm' }: TagBadgeProps) {\n const style = getTagStyle(tag);\n const sizeClass = size === 'sm'\n ? 'px-1.5 py-px text-[8px]'\n : 'px-2 py-0.5 text-[10px]';\n\n return (\n <span className={`inline-flex items-center gap-1 font-medium rounded border ${style.className} ${sizeClass}`}>\n {style.label}\n {onRemove && (\n <button onClick={onRemove} className=\"opacity-50 hover:opacity-100 transition-opacity\">\n <XIcon size={size === 'sm' ? 10 : 12} />\n </button>\n )}\n </span>\n );\n}\n","import React from 'react';\nimport { getInitials } from '../utils/helpers';\n\nexport interface UserAvatarProps {\n name: string;\n size?: 'xs' | 'sm' | 'md';\n showTooltip?: boolean;\n className?: string;\n}\n\nconst SIZES = {\n xs: { container: 'w-5 h-5', text: 'text-[8px]' },\n sm: { container: 'w-6 h-6', text: 'text-[9px]' },\n md: { container: 'w-7 h-7', text: 'text-[10px]' },\n};\n\nexport function UserAvatar({ name, size = 'xs', showTooltip = false, className = '' }: UserAvatarProps) {\n const s = SIZES[size];\n const initials = getInitials(name || '?');\n\n return (\n <div className={`relative ${showTooltip ? 'group/avatar' : ''} ${className}`}>\n <div className={`${s.container} rounded-full bg-[#FF5E00] flex items-center justify-center`}>\n <span className={`${s.text} font-medium text-white leading-none`}>{initials}</span>\n </div>\n {showTooltip && (\n <div className=\"absolute bottom-full right-0 mb-1.5 px-2 py-1 text-[10px] font-medium text-white bg-neutral-800 rounded whitespace-nowrap opacity-0 pointer-events-none group-hover/avatar:opacity-100 transition-opacity duration-75\">\n {name}\n </div>\n )}\n </div>\n );\n}\n","import React, { useState, useRef, useEffect } from 'react';\nimport type { Project, TagConfig } from '../types';\nimport { FilterIcon, XIcon, CheckIcon, ChevronDownIcon } from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\nexport interface FilterBarProps {\n projects: Project[];\n selectedProject: string;\n onSelectProject: (slug: string) => void;\n filterTags: string[];\n onSetFilterTags: (tags: string[]) => void;\n}\n\nexport function FilterBar({\n projects,\n selectedProject,\n onSelectProject,\n filterTags,\n onSetFilterTags,\n}: FilterBarProps) {\n const { tags: predefinedTags, features } = useTaskBoardContext();\n const [filterExpanded, setFilterExpanded] = useState(false);\n const filterDropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!filterExpanded) return;\n function handleClick(e: MouseEvent) {\n if (filterDropdownRef.current && !filterDropdownRef.current.contains(e.target as Node)) {\n setFilterExpanded(false);\n }\n }\n document.addEventListener(\"mousedown\", handleClick);\n return () => document.removeEventListener(\"mousedown\", handleClick);\n }, [filterExpanded]);\n\n const toggleTag = (value: string) => {\n onSetFilterTags(\n filterTags.includes(value)\n ? filterTags.filter((t) => t !== value)\n : [...filterTags, value]\n );\n };\n\n return (\n <div className=\"mb-4 shrink-0 flex items-start justify-between gap-3\">\n {/* Project pills */}\n {projects.length > 1 && (\n <div className=\"flex gap-2 flex-nowrap overflow-x-auto eb-tb-no-scrollbar sm:flex-wrap sm:overflow-visible\">\n {projects.map((project) => (\n <button\n key={project.slug}\n onClick={() => onSelectProject(project.slug)}\n className={`shrink-0 px-4 py-2 text-xs font-medium rounded-lg border transition-colors whitespace-nowrap ${\n selectedProject === project.slug\n ? \"bg-[#FF5E00] text-white border-[#FF5E00]\"\n : \"bg-white text-neutral-600 border-neutral-200 hover:border-neutral-300 hover:text-neutral-900\"\n }`}\n >\n {project.name}\n </button>\n ))}\n </div>\n )}\n {projects.length === 1 && (\n <span className=\"text-sm font-medium text-neutral-600\">{projects[0].name}</span>\n )}\n\n {/* Divider */}\n {features.filters && <div className=\"self-stretch w-px bg-neutral-200 shrink-0\" />}\n\n {/* Filter button + dropdown */}\n {features.filters && (\n <div className=\"relative shrink-0\" ref={filterDropdownRef}>\n <button\n onClick={() => setFilterExpanded(!filterExpanded)}\n className={`flex items-center gap-1.5 px-3 py-2 text-xs font-medium rounded-lg border transition-colors ${\n filterTags.length > 0\n ? \"bg-[#FF5E00]/5 border-[#FF5E00]/30 text-[#FF5E00]\"\n : \"bg-white text-neutral-500 border-neutral-200 hover:border-neutral-300 hover:text-neutral-700\"\n }`}\n >\n <FilterIcon size={14} />\n Filter\n {filterTags.length > 0 && (\n <span className=\"min-w-[16px] h-4 flex items-center justify-center rounded-full bg-[#FF5E00] text-white text-[9px] font-bold px-1\">\n {filterTags.length}\n </span>\n )}\n </button>\n\n {filterExpanded && (\n <div className=\"absolute right-0 top-full mt-1.5 w-64 bg-white border border-neutral-200 rounded-lg shadow-lg z-20 animate-in fade-in zoom-in-95 duration-75\">\n <div className=\"px-3 py-2.5 border-b border-neutral-100 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-neutral-700\">Filter by Tags</span>\n {filterTags.length > 0 && (\n <button\n onClick={() => onSetFilterTags([])}\n className=\"text-[10px] font-medium text-[#FF5E00] hover:text-[#E05200] transition-colors\"\n >\n Clear all\n </button>\n )}\n </div>\n <div className=\"py-1\">\n {predefinedTags.map((tag) => {\n const isActive = filterTags.includes(tag.value);\n return (\n <button\n key={tag.value}\n onClick={() => toggleTag(tag.value)}\n className={`w-full flex items-center justify-between px-3 py-2 text-xs hover:bg-neutral-50 transition-colors ${\n isActive ? \"bg-neutral-50\" : \"\"\n }`}\n >\n <span className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${tag.className}`}>\n {tag.label}\n </span>\n {isActive && <CheckIcon size={13} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n );\n })}\n {/* Other — matches custom tags */}\n <button\n onClick={() => toggleTag(\"__other__\")}\n className={`w-full flex items-center justify-between px-3 py-2 text-xs hover:bg-neutral-50 transition-colors border-t border-neutral-100 ${\n filterTags.includes(\"__other__\") ? \"bg-neutral-50\" : \"\"\n }`}\n >\n <span className=\"inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border bg-neutral-100 text-neutral-500 border-neutral-200\">\n Other\n </span>\n {filterTags.includes(\"__other__\") && <CheckIcon size={13} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport type { Notification } from '../types';\nimport { BellIcon } from '../icons';\nimport { UserAvatar } from './UserAvatar';\nimport { SkeletonPulse } from './SkeletonPulse';\nimport { formatDateTime, getInitials } from '../utils/helpers';\nimport { NOTIFICATION_POLL_INTERVAL } from '../utils/constants';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\nexport interface NotificationBellProps {\n onOpenTask: (taskId: string, projectSlug: string) => void;\n}\n\nexport function NotificationBell({ onOpenTask }: NotificationBellProps) {\n const { service, config } = useTaskBoardContext();\n const [open, setOpen] = useState(false);\n const [notifications, setNotifications] = useState<Notification[]>([]);\n const [unreadCount, setUnreadCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const pollRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const fetchCount = useCallback(async () => {\n try {\n const count = await service.getNotificationCount();\n setUnreadCount(count);\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n }, [service, config]);\n\n useEffect(() => {\n fetchCount();\n pollRef.current = setInterval(fetchCount, NOTIFICATION_POLL_INTERVAL);\n return () => { if (pollRef.current) clearInterval(pollRef.current); };\n }, [fetchCount]);\n\n const fetchNotifications = async () => {\n setLoading(true);\n try {\n const data = await service.listNotifications();\n setNotifications(data);\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n } finally { setLoading(false); }\n };\n\n const toggleOpen = () => {\n if (!open) fetchNotifications();\n setOpen(!open);\n };\n\n useEffect(() => {\n if (!open) return;\n function handleClick(e: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) setOpen(false);\n }\n document.addEventListener(\"mousedown\", handleClick);\n return () => document.removeEventListener(\"mousedown\", handleClick);\n }, [open]);\n\n const markAsRead = async (id: string) => {\n try {\n await service.markNotificationRead(id);\n setNotifications((prev) => prev.map((n) => (n.id === id ? { ...n, read: true } : n)));\n setUnreadCount((c) => Math.max(0, c - 1));\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n const markAllRead = async () => {\n try {\n await service.markAllNotificationsRead();\n setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));\n setUnreadCount(0);\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n const handleClick = (n: Notification) => {\n if (!n.read) markAsRead(n.id);\n setOpen(false);\n onOpenTask(n.task_id, n.project_slug);\n };\n\n return (\n <div ref={dropdownRef} className=\"relative\">\n <button\n onClick={toggleOpen}\n className=\"relative flex items-center justify-center w-9 h-9 rounded-lg border border-neutral-200 hover:border-neutral-300 hover:bg-neutral-50 transition-colors\"\n title=\"Notifications\"\n >\n <BellIcon size={16} className=\"text-neutral-600\" />\n {unreadCount > 0 && (\n <span className=\"absolute -top-1 -right-1 min-w-[16px] h-4 px-1 flex items-center justify-center rounded-full bg-[#FF5E00] text-white text-[9px] font-bold\">\n {unreadCount > 99 ? \"99+\" : unreadCount}\n </span>\n )}\n </button>\n\n {open && (\n <div className=\"absolute right-0 mt-2 w-[360px] bg-white rounded-xl shadow-xl border border-neutral-200 z-50 overflow-hidden\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-neutral-100\">\n <h3 className=\"text-sm font-medium text-neutral-900\">Notifications</h3>\n {unreadCount > 0 && (\n <button onClick={markAllRead} className=\"text-[11px] font-medium text-[#FF5E00] hover:text-[#E05200] transition-colors\">\n Mark all as read\n </button>\n )}\n </div>\n <div className=\"max-h-[400px] overflow-y-auto\">\n {loading ? (\n <div className=\"px-4 py-6 space-y-3\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex gap-3 animate-pulse\">\n <div className=\"w-8 h-8 rounded-full bg-neutral-200 shrink-0\" />\n <div className=\"flex-1 space-y-1.5\">\n <SkeletonPulse className=\"h-3 w-3/4\" />\n <SkeletonPulse className=\"h-2.5 w-full\" />\n <SkeletonPulse className=\"h-2 w-16\" />\n </div>\n </div>\n ))}\n </div>\n ) : notifications.length === 0 ? (\n <div className=\"px-4 py-10 text-center\">\n <BellIcon size={32} className=\"text-neutral-300 mx-auto mb-2\" />\n <p className=\"text-xs text-neutral-400\">No notifications yet</p>\n </div>\n ) : (\n notifications.map((n) => (\n <button\n key={n.id}\n onClick={() => handleClick(n)}\n className={`w-full flex items-start gap-3 px-4 py-3 text-left hover:bg-neutral-50 transition-colors border-b border-neutral-50 last:border-b-0 ${\n !n.read ? \"bg-[#FF5E00]/[0.03]\" : \"\"\n }`}\n >\n <div className=\"w-8 h-8 rounded-full bg-[#FF5E00] text-white text-[10px] font-semibold flex items-center justify-center shrink-0 mt-0.5\">\n {getInitials(n.actor_name)}\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-xs text-neutral-700 leading-relaxed\">\n <span className=\"font-semibold text-neutral-900\">{n.actor_name}</span>\n {\" mentioned you in \"}\n {n.context === \"description\" ? \"the description of \" : \"a comment on \"}\n <span className=\"font-medium text-neutral-800\">{n.task_title}</span>\n </p>\n {n.snippet && <p className=\"text-[11px] text-neutral-400 mt-0.5 truncate\">{n.snippet}</p>}\n <p className=\"text-[10px] text-neutral-400 mt-1\">{formatDateTime(n.created_at)}</p>\n </div>\n {!n.read && <span className=\"w-2 h-2 rounded-full bg-[#FF5E00] shrink-0 mt-2\" />}\n </button>\n ))\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport type { StructuredDescription, TasksByStatus } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { EMPTY_DESCRIPTION, DESCRIPTION_SECTIONS } from '../utils/constants';\nimport { getPriorityStyle } from '../utils/helpers';\nimport { XIcon, ChevronDownIcon, CheckIcon } from '../icons';\n\nexport interface CreateTaskModalProps {\n projectSlug: string;\n defaultStatus?: string;\n onClose: () => void;\n onCreate: () => void;\n}\n\nexport function CreateTaskModal({\n projectSlug,\n defaultStatus = 'backlog',\n onClose,\n onCreate,\n}: CreateTaskModalProps) {\n const { columns, priorities, tags: predefinedTags, service, config } = useTaskBoardContext();\n\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState<StructuredDescription>({ ...EMPTY_DESCRIPTION });\n const [priority, setPriority] = useState('medium');\n const [taskStatus, setTaskStatus] = useState(defaultStatus);\n const [selectedTags, setSelectedTags] = useState<string[]>([]);\n const [customTag, setCustomTag] = useState('');\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [showColumnDropdown, setShowColumnDropdown] = useState(false);\n const [showPriorityDropdown, setShowPriorityDropdown] = useState(false);\n\n const toggleTag = (tag: string) => {\n setSelectedTags((prev) =>\n prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]\n );\n };\n\n const addCustomTag = () => {\n const tag = customTag.trim().toLowerCase().replace(/\\s+/g, '-');\n if (tag && !selectedTags.includes(tag)) {\n setSelectedTags((prev) => [...prev, tag]);\n }\n setCustomTag('');\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!title.trim()) return;\n\n setLoading(true);\n setError('');\n try {\n const task = await service.createTask({\n project_slug: projectSlug,\n title: title.trim(),\n description,\n priority,\n status: taskStatus,\n tags: selectedTags,\n });\n config.onTaskCreate?.(task);\n onCreate();\n onClose();\n } catch (err: unknown) {\n const apiErr = err as { response?: { data?: { detail?: string } }; message?: string };\n setError(apiErr?.response?.data?.detail || apiErr?.message || 'Failed to create task');\n } finally {\n setLoading(false);\n }\n };\n\n const priorityStyle = getPriorityStyle(priority);\n const statusCol = columns.find((c) => c.key === taskStatus);\n\n return (\n <div\n className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/30 backdrop-blur-sm eb-tb-animate-fade-in\"\n onClick={(e) => e.target === e.currentTarget && onClose()}\n >\n <div className=\"bg-white rounded-2xl shadow-2xl border border-neutral-200 w-[80vw] max-w-[1100px] h-[85vh] flex flex-col eb-tb-animate-zoom-in\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-neutral-100 shrink-0\">\n <h2 className=\"text-lg font-semibold text-neutral-900\">New Task</h2>\n <button\n onClick={onClose}\n className=\"p-1 rounded-md text-neutral-400 hover:text-neutral-600 hover:bg-neutral-100 transition-colors\"\n >\n <XIcon size={20} />\n </button>\n </div>\n\n {/* Body */}\n <form onSubmit={handleSubmit} className=\"flex-1 flex flex-col min-h-0\">\n {error && (\n <div className=\"mx-6 mt-4 p-3 bg-red-50 border border-red-200 rounded-lg text-red-600 text-sm\">\n {error}\n </div>\n )}\n\n <div className=\"flex-1 flex min-h-0 overflow-hidden\">\n {/* Left: Content */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5 border-r border-neutral-100\">\n <div className=\"max-w-2xl\">\n {/* Title */}\n <div className=\"pb-4\">\n <label className=\"text-xs font-medium text-neutral-700 mb-1.5 block\">Title</label>\n <input\n type=\"text\"\n required\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n className=\"w-full px-3 py-2.5 border border-neutral-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50\"\n placeholder=\"What needs to be done?\"\n autoFocus\n />\n </div>\n\n <div className=\"border-t border-neutral-100 pt-4 pb-1\">\n <span className=\"text-[10px] font-semibold text-neutral-400 uppercase tracking-wider\">Description</span>\n </div>\n\n {/* Description Sections */}\n {DESCRIPTION_SECTIONS.map((section, idx) => (\n <div key={section.key} className={`py-3 ${idx < DESCRIPTION_SECTIONS.length - 1 ? 'border-b border-dashed border-neutral-100' : ''}`}>\n <label className=\"text-xs font-medium text-neutral-700 mb-1.5 block\">\n {section.label} <span className=\"text-neutral-400 font-normal\">(optional)</span>\n </label>\n <textarea\n value={description[section.key]}\n onChange={(e) =>\n setDescription((prev) => ({ ...prev, [section.key]: e.target.value }))\n }\n rows={3}\n className=\"w-full px-3 py-2.5 border border-neutral-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 resize-y\"\n placeholder={`Add ${section.label.toLowerCase()}...`}\n />\n </div>\n ))}\n </div>\n </div>\n\n {/* Right: Settings */}\n <div className=\"w-[340px] shrink-0 overflow-y-auto px-5 py-5 bg-neutral-50/30\">\n {/* Column + Priority side by side */}\n <div className=\"grid grid-cols-2 gap-4 mb-5\">\n {/* Column */}\n <div>\n <label className=\"text-[11px] font-semibold text-neutral-500 uppercase tracking-wide mb-2 block\">Column</label>\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowColumnDropdown(!showColumnDropdown)}\n className=\"w-full flex items-center justify-between gap-2 px-3 py-2 text-xs font-medium rounded-lg border border-neutral-200 bg-white hover:border-neutral-300 transition-colors\"\n >\n <div className=\"flex items-center gap-2\">\n <span className={`w-2 h-2 rounded-full ${statusCol?.color ?? 'bg-neutral-400'}`} />\n {statusCol?.label ?? taskStatus}\n </div>\n <ChevronDownIcon size={12} className=\"text-neutral-400\" />\n </button>\n {showColumnDropdown && (\n <div className=\"absolute top-full mt-1 left-0 right-0 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 py-1 eb-tb-animate-zoom-in\">\n {columns.map((col) => (\n <button\n key={col.key}\n type=\"button\"\n onClick={() => { setTaskStatus(col.key); setShowColumnDropdown(false); }}\n className={`w-full flex items-center gap-2 px-3 py-1.5 text-xs hover:bg-neutral-50 text-left ${\n taskStatus === col.key ? 'font-medium bg-neutral-50' : ''\n }`}\n >\n <span className={`w-2 h-2 rounded-full ${col.color}`} />\n {col.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Priority */}\n <div>\n <label className=\"text-[11px] font-semibold text-neutral-500 uppercase tracking-wide mb-2 block\">Priority</label>\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowPriorityDropdown(!showPriorityDropdown)}\n className={`w-full flex items-center justify-between gap-2 px-3 py-2 text-xs font-medium rounded-lg border transition-colors ${priorityStyle.className}`}\n >\n {priorityStyle.label}\n <ChevronDownIcon size={12} className=\"opacity-50\" />\n </button>\n {showPriorityDropdown && (\n <div className=\"absolute top-full mt-1 left-0 right-0 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 py-1 eb-tb-animate-zoom-in\">\n {priorities.map((p) => (\n <button\n key={p.value}\n type=\"button\"\n onClick={() => { setPriority(p.value); setShowPriorityDropdown(false); }}\n className={`w-full flex items-center gap-2 px-3 py-1.5 text-xs hover:bg-neutral-50 text-left ${\n priority === p.value ? 'bg-neutral-50' : ''\n }`}\n >\n <span className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${p.className}`}>\n {p.label}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Tags */}\n <div>\n <label className=\"text-[11px] font-semibold text-neutral-500 uppercase tracking-wide mb-2 block\">Tags</label>\n <div className=\"space-y-1\">\n {predefinedTags.map((tag) => {\n const isSelected = selectedTags.includes(tag.value);\n return (\n <button\n key={tag.value}\n type=\"button\"\n onClick={() => toggleTag(tag.value)}\n className={`w-full flex items-center justify-between px-3 py-2 text-xs rounded-lg border transition-colors text-left ${\n isSelected\n ? 'bg-[#FF5E00]/5 border-[#FF5E00]/30 text-neutral-800'\n : 'bg-white text-neutral-600 border-neutral-200 hover:border-neutral-300'\n }`}\n >\n <span className={`inline-flex items-center px-1.5 py-px text-[10px] font-medium rounded border ${tag.className}`}>\n {tag.label}\n </span>\n {isSelected && <CheckIcon size={13} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n );\n })}\n </div>\n {/* Custom tag input */}\n <div className=\"mt-2.5 flex gap-1.5\">\n <input\n type=\"text\"\n value={customTag}\n onChange={(e) => setCustomTag(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addCustomTag(); } }}\n className=\"flex-1 px-2.5 py-1.5 border border-neutral-200 rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 bg-white\"\n placeholder=\"Custom tag...\"\n />\n <button\n type=\"button\"\n onClick={addCustomTag}\n disabled={!customTag.trim()}\n className=\"px-2.5 py-1.5 text-xs font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors disabled:opacity-40\"\n >\n Add\n </button>\n </div>\n {selectedTags.filter((t) => !predefinedTags.some((p) => p.value === t)).length > 0 && (\n <div className=\"flex gap-1.5 flex-wrap mt-2\">\n {selectedTags\n .filter((t) => !predefinedTags.some((p) => p.value === t))\n .map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-[10px] font-medium bg-neutral-100 text-neutral-500 border border-neutral-200 rounded\"\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => setSelectedTags((prev) => prev.filter((t) => t !== tag))}\n className=\"text-neutral-400 hover:text-neutral-600\"\n >\n <XIcon size={12} />\n </button>\n </span>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-end gap-3 px-6 py-4 border-t border-neutral-100 shrink-0 bg-white\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm text-neutral-600 hover:text-neutral-900 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={loading}\n className=\"px-6 py-2 text-sm font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors disabled:opacity-60\"\n >\n {loading ? 'Creating...' : 'Create Task'}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport type { Task, Comment, ActivityEntry, StructuredDescription } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { useTaskDetail } from '../hooks/useTaskDetail';\nimport { EMPTY_DESCRIPTION, DESCRIPTION_SECTIONS } from '../utils/constants';\nimport { getPriorityStyle, formatDateTime, getInitials, getTagStyle, hasDescription } from '../utils/helpers';\nimport { useShareLink } from '../hooks/useShareLink';\nimport { MentionText } from './MentionText';\nimport { MentionTextarea } from './MentionTextarea';\nimport { SkeletonPulse } from './SkeletonPulse';\nimport { TagBadge } from './TagBadge';\nimport {\n XIcon, ChevronDownIcon, CheckIcon, PlusIcon,\n PencilIcon, TrashIcon, LinkIcon, LockIcon, MessageSquareIcon,\n} from '../icons';\n\nexport interface TaskDetailPanelProps {\n task: Task;\n projectSlug: string;\n onClose: () => void;\n onUpdate: () => void;\n}\n\nexport function TaskDetailPanel({ task, projectSlug, onClose, onUpdate }: TaskDetailPanelProps) {\n const { columns, priorities, tags: predefinedTags, service, config, user, features } = useTaskBoardContext();\n const detail = useTaskDetail(task.id);\n const { copiedTaskId, copyShareLink } = useShareLink();\n\n const [title, setTitle] = useState(task.title);\n const [description, setDescription] = useState<StructuredDescription>(task.description || EMPTY_DESCRIPTION);\n const [priority, setPriority] = useState(task.priority);\n const [taskStatus, setTaskStatus] = useState(task.status);\n const [localTags, setLocalTags] = useState<string[]>(task.tags || []);\n const [pendingTags, setPendingTags] = useState<string[]>([]);\n\n const [saving, setSaving] = useState(false);\n const [editing, setEditing] = useState(false);\n const [newComment, setNewComment] = useState('');\n const [isInternalComment, setIsInternalComment] = useState(false);\n\n const [showPriorityDropdown, setShowPriorityDropdown] = useState(false);\n const [showStatusDropdown, setShowStatusDropdown] = useState(false);\n const [showTagDropdown, setShowTagDropdown] = useState(false);\n const [showOtherTagInput, setShowOtherTagInput] = useState(false);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [showDiscardConfirm, setShowDiscardConfirm] = useState(false);\n const [commentToDelete, setCommentToDelete] = useState<string | null>(null);\n const [editingCommentId, setEditingCommentId] = useState<string | null>(null);\n const [editingCommentContent, setEditingCommentContent] = useState('');\n\n const commentsEndRef = useRef<HTMLDivElement>(null);\n const hasUnsavedChanges = editing && (title !== task.title || JSON.stringify(description) !== JSON.stringify(task.description));\n\n useEffect(() => {\n if (commentsEndRef.current) {\n commentsEndRef.current.scrollIntoView({ behavior: 'smooth' });\n }\n }, [detail.comments]);\n\n const saveField = async (field: string, value: unknown) => {\n setSaving(true);\n try {\n await detail.saveField(field, value);\n onUpdate();\n } finally {\n setSaving(false);\n }\n };\n\n const handleSaveEdit = async () => {\n setSaving(true);\n try {\n const updates: Record<string, unknown> = {};\n if (title.trim() && title !== task.title) updates.title = title.trim();\n if (JSON.stringify(description) !== JSON.stringify(task.description)) updates.description = description;\n if (Object.keys(updates).length > 0) {\n await service.updateTask(task.id, updates as Parameters<typeof service.updateTask>[1]);\n onUpdate();\n }\n } finally {\n setSaving(false);\n setEditing(false);\n }\n };\n\n const handleCancelEdit = () => {\n if (hasUnsavedChanges) {\n setShowDiscardConfirm(true);\n } else {\n setEditing(false);\n }\n };\n\n const handleDiscardChanges = () => {\n setTitle(task.title);\n setDescription(task.description || EMPTY_DESCRIPTION);\n setEditing(false);\n setShowDiscardConfirm(false);\n };\n\n const handleClosePanel = () => {\n if (hasUnsavedChanges) {\n setShowDiscardConfirm(true);\n } else {\n onClose();\n }\n };\n\n const handleDelete = async () => {\n setSaving(true);\n try {\n await service.deleteTask(task.id);\n config.onTaskDelete?.(task.id);\n onUpdate();\n onClose();\n } finally {\n setSaving(false);\n }\n };\n\n const handlePriorityChange = (p: string) => {\n setPriority(p);\n setShowPriorityDropdown(false);\n saveField('priority', p);\n };\n\n const handleStatusChange = (s: string) => {\n setTaskStatus(s);\n setShowStatusDropdown(false);\n saveField('status', s);\n };\n\n const handleAddComment = async () => {\n if (!newComment.trim()) return;\n await detail.addComment(newComment.trim(), isInternalComment);\n setNewComment('');\n setIsInternalComment(false);\n onUpdate();\n };\n\n const handleCommentKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleAddComment();\n }\n };\n\n const handleDeleteComment = async () => {\n if (!commentToDelete) return;\n try {\n await detail.deleteComment(commentToDelete);\n setCommentToDelete(null);\n onUpdate();\n } catch (err: unknown) {\n setCommentToDelete(null);\n }\n };\n\n const startEditingComment = (c: Comment) => {\n setEditingCommentId(c.id);\n setEditingCommentContent(c.content);\n };\n\n const cancelEditingComment = () => {\n setEditingCommentId(null);\n setEditingCommentContent('');\n };\n\n const saveEditedComment = async () => {\n if (!editingCommentId || !editingCommentContent.trim()) return;\n try {\n await detail.editComment(editingCommentId, editingCommentContent.trim());\n setEditingCommentId(null);\n setEditingCommentContent('');\n } catch {\n // error surfaced by hook\n }\n };\n\n const statusCol = columns.find((c) => c.key === taskStatus);\n const priorityStyle = getPriorityStyle(priority);\n const initials = getInitials(task.created_by_name || '?');\n const linkCopied = copiedTaskId === task.id;\n\n const handleShareFromDetail = () => {\n copyShareLink(task.id, projectSlug);\n };\n\n // Merge comments and activity into timeline\n const timeline = [\n ...detail.comments.map((c) => ({ kind: 'comment' as const, date: c.created_at, data: c })),\n ...detail.activity.map((a) => ({ kind: 'activity' as const, date: a.created_at, data: a })),\n ].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());\n\n return (\n <div\n className=\"fixed inset-0 z-[100] flex items-end justify-end bg-black/30 backdrop-blur-md eb-tb-animate-fade-in\"\n onClick={(e) => e.target === e.currentTarget && handleClosePanel()}\n >\n <div\n className=\"bg-white shadow-2xl border-l border-neutral-200 w-full lg:w-[75vw] h-full flex flex-col\"\n style={{ animation: 'eb-tb-slide-in-right 0.15s ease-out' }}\n >\n {/* Top bar */}\n <div className=\"flex items-center gap-2 sm:gap-4 px-4 sm:px-8 py-3 sm:py-4 border-b border-neutral-100 shrink-0\">\n <h2 className=\"flex-1 text-base sm:text-lg font-semibold text-neutral-900 truncate min-w-0\">\n {title}\n </h2>\n <div className=\"flex items-center gap-2 shrink-0\">\n {saving && <span className=\"text-[11px] text-neutral-400 mr-1\">Saving...</span>}\n {editing ? (\n <>\n <button onClick={handleCancelEdit} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 rounded-lg hover:bg-neutral-100 transition-colors\">\n <XIcon size={13} /> Cancel\n </button>\n <button onClick={handleSaveEdit} disabled={saving} className=\"flex items-center gap-1.5 px-4 py-1.5 text-xs font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors disabled:opacity-60\">\n <CheckIcon size={13} /> {saving ? 'Saving...' : 'Save'}\n </button>\n </>\n ) : (\n <>\n {features.sharing && (\n <button onClick={handleShareFromDetail} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 rounded-lg border border-neutral-200 hover:border-neutral-300 transition-colors\">\n {linkCopied ? <><CheckIcon size={13} /> Copied!</> : <><LinkIcon size={13} /> Share</>}\n </button>\n )}\n <button onClick={() => setEditing(true)} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 rounded-lg border border-neutral-200 hover:border-neutral-300 transition-colors\">\n <PencilIcon size={13} /> Edit\n </button>\n <button onClick={() => setShowDeleteConfirm(true)} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 rounded-lg border border-neutral-200 hover:border-neutral-300 transition-colors\">\n <TrashIcon size={13} /> Delete\n </button>\n </>\n )}\n <button onClick={handleClosePanel} className=\"p-1.5 rounded-md text-neutral-400 hover:text-neutral-600 hover:bg-neutral-100 transition-colors ml-1\">\n <XIcon size={16} />\n </button>\n </div>\n </div>\n\n {/* Two-column body */}\n <div className=\"flex-1 flex flex-col md:flex-row min-h-0\">\n {/* Left: Task content */}\n <div className=\"flex-1 overflow-y-auto min-w-0\">\n <div className=\"max-w-2xl px-4 sm:px-8 lg:px-10 py-6 sm:py-8\">\n {/* Title edit */}\n {editing && (\n <div className=\"mb-6\">\n <label className=\"text-[11px] font-medium text-neutral-400 uppercase tracking-wide mb-2 block\">Title</label>\n <input\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n className=\"w-full text-lg font-semibold text-neutral-900 bg-white border border-neutral-200 rounded-lg px-3 py-2 outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 leading-tight\"\n placeholder=\"Task title\"\n autoFocus\n />\n </div>\n )}\n\n {/* Properties grid */}\n <div className={`${editing ? 'mt-0' : 'mt-2'} rounded-lg border border-neutral-100 grid grid-cols-1 sm:grid-cols-2`}>\n {/* Task ID | Creator */}\n <div className=\"flex items-center h-10 px-4 border-b sm:border-r border-neutral-100\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Task ID</span>\n <span className=\"text-[11px] font-mono text-neutral-400 bg-neutral-100 px-1.5 py-0.5 rounded\">\n T-{task.id.slice(-6).toUpperCase()}\n </span>\n </div>\n <div className=\"flex items-center h-10 px-4 border-b border-neutral-100\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Creator</span>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-5 h-5 rounded-full bg-[#FF5E00] flex items-center justify-center\">\n <span className=\"text-[8px] font-medium text-white leading-none\">{initials}</span>\n </div>\n <span className=\"text-xs text-neutral-700\">{task.created_by_name || task.created_by}</span>\n </div>\n </div>\n\n {/* Created | Updated */}\n <div className=\"flex items-center h-10 px-4 border-b sm:border-r border-neutral-100\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Created</span>\n <span className=\"text-xs text-neutral-600\">{formatDateTime(task.created_at)}</span>\n </div>\n <div className=\"flex items-center h-10 px-4 border-b border-neutral-100\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Updated</span>\n <span className=\"text-xs text-neutral-600\">{task.updated_at ? formatDateTime(task.updated_at) : '—'}</span>\n </div>\n\n {/* Status | Priority */}\n <div className=\"flex items-center h-10 px-4 border-b sm:border-r border-neutral-100 hover:bg-neutral-50/50 transition-colors\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Status</span>\n <div className=\"relative\">\n <button\n onClick={() => { setShowStatusDropdown(!showStatusDropdown); setShowPriorityDropdown(false); setShowTagDropdown(false); }}\n className=\"flex items-center gap-1.5 px-2 py-0.5 text-xs font-medium rounded-md hover:bg-neutral-100 transition-colors\"\n >\n <span className={`w-2 h-2 rounded-full ${statusCol?.color ?? 'bg-neutral-400'}`} />\n {statusCol?.label ?? taskStatus}\n <ChevronDownIcon size={12} className=\"text-neutral-400\" />\n </button>\n {showStatusDropdown && (\n <div className=\"absolute top-full mt-1 left-0 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 py-1 w-52 eb-tb-animate-zoom-in\">\n {columns.map((col) => (\n <button key={col.key} onClick={() => handleStatusChange(col.key)} className={`w-full text-left px-3 py-1.5 text-xs hover:bg-neutral-50 flex items-center gap-2 ${taskStatus === col.key ? 'font-medium bg-neutral-50' : ''}`}>\n <span className={`w-2 h-2 rounded-full ${col.color}`} /> {col.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n <div className=\"flex items-center h-10 px-4 border-b border-neutral-100 hover:bg-neutral-50/50 transition-colors\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Priority</span>\n <div className=\"relative\">\n <button\n onClick={() => { setShowPriorityDropdown(!showPriorityDropdown); setShowStatusDropdown(false); setShowTagDropdown(false); }}\n className={`flex items-center gap-1.5 px-2 py-0.5 text-xs font-medium rounded-md transition-colors border ${priorityStyle.className}`}\n >\n {priorityStyle.label}\n <ChevronDownIcon size={12} className=\"opacity-50\" />\n </button>\n {showPriorityDropdown && (\n <div className=\"absolute top-full mt-1 left-0 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 py-1 w-40 eb-tb-animate-zoom-in\">\n {priorities.map((p) => (\n <button key={p.value} onClick={() => handlePriorityChange(p.value)} className={`w-full text-left px-3 py-2 text-xs hover:bg-neutral-50 flex items-center gap-2 ${priority === p.value ? 'bg-neutral-50' : ''}`}>\n <span className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${p.className}`}>{p.label}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Tags — full width */}\n {features.tags && (\n <div className=\"flex items-center min-h-[40px] px-4 border-b border-neutral-100 sm:col-span-2 hover:bg-neutral-50/50 transition-colors\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Tags</span>\n <div className=\"relative flex-1 flex items-center gap-1.5 flex-wrap py-1.5\">\n {localTags.map((tag) => (\n <TagBadge key={tag} tag={tag} size=\"sm\" onRemove={() => {\n const newTags = localTags.filter((t) => t !== tag);\n setLocalTags(newTags);\n saveField('tags', newTags);\n }} />\n ))}\n <button\n onClick={() => {\n if (!showTagDropdown) setPendingTags([...localTags]);\n setShowTagDropdown(!showTagDropdown);\n setShowStatusDropdown(false);\n setShowPriorityDropdown(false);\n }}\n className=\"inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] text-neutral-400 hover:text-neutral-600 rounded border border-dashed border-neutral-300 hover:border-neutral-400 transition-colors\"\n >\n <PlusIcon size={12} /> {showTagDropdown ? 'Close' : 'Edit'}\n </button>\n {showTagDropdown && (\n <div className=\"absolute top-full left-0 mt-1 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 w-56 eb-tb-animate-zoom-in\">\n <div className=\"py-1\">\n {predefinedTags.map((tag) => {\n const isSelected = pendingTags.includes(tag.value);\n return (\n <button key={tag.value} onClick={() => setPendingTags((prev) => isSelected ? prev.filter((t) => t !== tag.value) : [...prev, tag.value])}\n className={`w-full text-left px-3 py-1.5 text-xs hover:bg-neutral-50 flex items-center justify-between ${isSelected ? 'bg-neutral-50' : ''}`}>\n <span className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${tag.className}`}>{tag.label}</span>\n {isSelected && <CheckIcon size={12} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n );\n })}\n {!showOtherTagInput ? (\n <button onClick={() => setShowOtherTagInput(true)} className=\"w-full text-left px-3 py-1.5 text-xs hover:bg-neutral-50 flex items-center justify-between\">\n <span className=\"inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border bg-neutral-100 text-neutral-500 border-neutral-200\">Other</span>\n </button>\n ) : (\n <div className=\"px-3 py-2 bg-neutral-50/50\">\n <div className=\"flex gap-1.5\">\n <input type=\"text\" autoFocus onKeyDown={(e) => {\n if (e.key === 'Enter') { e.preventDefault(); const val = e.currentTarget.value.trim().toLowerCase().replace(/\\s+/g, '-'); if (val && !pendingTags.includes(val)) setPendingTags((prev) => [...prev, val]); e.currentTarget.value = ''; setShowOtherTagInput(false); }\n if (e.key === 'Escape') setShowOtherTagInput(false);\n }} className=\"flex-1 px-2 py-1.5 text-xs border border-neutral-200 rounded-md focus:outline-none focus:ring-1 focus:ring-[#FF5E00]/20 focus:border-[#FF5E00]/50\" placeholder=\"Type a custom tag...\" onClick={(e) => e.stopPropagation()} />\n <button type=\"button\" onClick={() => setShowOtherTagInput(false)} className=\"px-2.5 py-1.5 text-[10px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-md transition-colors\">Add</button>\n </div>\n </div>\n )}\n </div>\n <div className=\"border-t border-neutral-100 px-2 py-2 flex items-center justify-end gap-2\">\n <button onClick={() => { setPendingTags([...localTags]); setShowTagDropdown(false); setShowOtherTagInput(false); }} className=\"px-2.5 py-1 text-[11px] font-medium text-neutral-500 hover:text-neutral-700 transition-colors\">Cancel</button>\n <button onClick={() => { setLocalTags([...pendingTags]); saveField('tags', pendingTags); setShowTagDropdown(false); setShowOtherTagInput(false); }} className=\"px-3 py-1 text-[11px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded transition-colors\">Save</button>\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Description Sections */}\n <div className=\"mt-5 space-y-4\">\n {DESCRIPTION_SECTIONS.map((section) => {\n const val = description[section.key] || '';\n const hasContent = val.trim().length > 0;\n if (!editing && !hasContent) return null;\n return (\n <div key={section.key}>\n <label className=\"text-[11px] font-medium text-neutral-400 uppercase tracking-wide mb-1.5 block\">{section.label}</label>\n {editing ? (\n <MentionTextarea\n value={val}\n onChange={(v) => setDescription((prev) => ({ ...prev, [section.key]: v }))}\n rows={3}\n className=\"w-full px-4 py-2.5 bg-white border border-neutral-200 rounded-lg text-sm leading-relaxed focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 resize-y transition-all placeholder:text-neutral-400\"\n placeholder={`Add ${section.label.toLowerCase()}...`}\n />\n ) : (\n <div className=\"w-full px-3.5 py-2.5 bg-neutral-50/60 border border-neutral-100 rounded-lg text-sm leading-relaxed text-neutral-700 whitespace-pre-wrap\">\n <MentionText text={val} />\n </div>\n )}\n </div>\n );\n })}\n {!editing && !hasDescription(description) && (\n <div className=\"px-3.5 py-4 bg-neutral-50/60 border border-neutral-100 rounded-lg text-sm text-neutral-400 text-center\">\n No description provided.\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Right: Activity panel */}\n {features.comments && (\n <div className=\"w-full md:w-[380px] shrink-0 border-t md:border-t-0 md:border-l border-neutral-100 flex flex-col bg-[#FAFAFA]\">\n <div className=\"px-5 h-12 flex items-center border-b border-neutral-100\">\n <h3 className=\"text-[11px] font-semibold text-neutral-500 uppercase tracking-wide\">\n Activity{detail.commentsLoaded ? ` · ${detail.comments.length + detail.activity.length}` : ''}\n </h3>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4\">\n {!detail.commentsLoaded && (\n <div className=\"space-y-4\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex gap-2.5\">\n <SkeletonPulse className=\"w-7 h-7 rounded-full shrink-0\" />\n <div className=\"flex-1 space-y-1.5\">\n <SkeletonPulse className=\"h-3 w-20\" />\n <SkeletonPulse className=\"h-3 w-full\" />\n </div>\n </div>\n ))}\n </div>\n )}\n\n {detail.commentsLoaded && detail.comments.length === 0 && detail.activity.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"w-10 h-10 rounded-full bg-neutral-100 flex items-center justify-center mb-3\">\n <MessageSquareIcon size={20} className=\"text-neutral-400\" />\n </div>\n <p className=\"text-xs text-neutral-400\">No activity yet</p>\n <p className=\"text-[10px] text-neutral-400 mt-0.5\">Comments and status changes will appear here</p>\n </div>\n )}\n\n <div className=\"space-y-4\">\n {timeline.map((item, i) => {\n if (item.kind === 'comment') {\n const c = item.data as Comment;\n const isOwner = user.username === c.author_id;\n const isEditing = editingCommentId === c.id;\n return (\n <div key={`c-${c.id}`} className={`group/comment flex gap-2.5 ${c.is_internal ? 'pl-2 border-l-2 border-amber-300' : ''}`}>\n <div className={`w-7 h-7 rounded-full flex items-center justify-center shrink-0 mt-0.5 ${c.is_internal ? 'bg-amber-100' : 'bg-neutral-200'}`}>\n <span className={`text-[10px] font-medium ${c.is_internal ? 'text-amber-600' : 'text-neutral-600'}`}>\n {getInitials(c.author_name || '?')}\n </span>\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-0.5\">\n <span className=\"text-[11px] font-semibold text-neutral-700\">{c.author_name}</span>\n {c.is_internal && (\n <span className=\"inline-flex items-center gap-0.5 px-1.5 py-px text-[9px] font-medium text-amber-600 bg-amber-50 border border-amber-200 rounded\">\n <LockIcon size={8} strokeWidth={2.5} /> Internal\n </span>\n )}\n <span className=\"text-[10px] text-neutral-400\">{formatDateTime(c.created_at)}</span>\n {c.edited && (\n <span className=\"text-[9px] text-neutral-400 italic\" title={c.edited_at ? `Edited ${formatDateTime(c.edited_at)}` : 'Edited'}>(edited)</span>\n )}\n {isOwner && (\n <div className={`ml-auto flex items-center gap-0.5 transition-opacity ${isEditing ? 'opacity-100' : 'opacity-0 group-hover/comment:opacity-100'}`}>\n {isEditing ? (\n <>\n <button onClick={saveEditedComment} disabled={!editingCommentContent.trim() || editingCommentContent.trim() === c.content} className=\"p-1 rounded hover:bg-green-50 text-neutral-400 hover:text-green-600 disabled:opacity-30\" title=\"Save edit\"><CheckIcon size={12} strokeWidth={2.5} /></button>\n <button onClick={cancelEditingComment} className=\"p-1 rounded hover:bg-red-50 text-neutral-400 hover:text-red-500\" title=\"Cancel edit\"><XIcon size={12} strokeWidth={2.5} /></button>\n </>\n ) : (\n <>\n <button onClick={() => startEditingComment(c)} className=\"p-1 rounded hover:bg-neutral-100 text-neutral-400 hover:text-neutral-600\" title=\"Edit comment\"><PencilIcon size={11} /></button>\n <button onClick={() => setCommentToDelete(c.id)} className=\"p-1 rounded hover:bg-red-50 text-neutral-400 hover:text-red-500\" title=\"Delete comment\"><TrashIcon size={11} /></button>\n </>\n )}\n </div>\n )}\n </div>\n {isEditing ? (\n <MentionTextarea\n value={editingCommentContent}\n onChange={setEditingCommentContent}\n onKeyDown={(e) => { if (e.key === 'Escape') cancelEditingComment(); if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); saveEditedComment(); } }}\n rows={2}\n className=\"w-full px-2.5 py-1.5 bg-white border border-neutral-300 rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/20 focus:border-[#FF5E00]/50 resize-none\"\n />\n ) : (\n <div className=\"text-xs text-neutral-600 whitespace-pre-wrap leading-relaxed\"><MentionText text={c.content} /></div>\n )}\n </div>\n </div>\n );\n } else {\n const a = item.data as ActivityEntry;\n const fromCol = columns.find((col) => col.key === a.from_status);\n const toCol = columns.find((col) => col.key === a.to_status);\n const isCreated = a.type === 'created';\n return (\n <div key={`a-${a.id}`} className=\"flex gap-2.5\">\n <div className=\"w-7 h-7 rounded-full bg-neutral-100 flex items-center justify-center shrink-0\">\n {isCreated ? <PlusIcon size={12} className=\"text-neutral-400\" /> : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className=\"text-neutral-400\"><path d=\"M5 12h14\"/><path d=\"m12 5 7 7-7 7\"/></svg>\n )}\n </div>\n <div className=\"flex-1 min-w-0\">\n {isCreated ? (\n <p className=\"text-[11px] text-neutral-500\"><span className=\"font-medium text-neutral-700\">{a.user_name}</span>{' created this task'}</p>\n ) : (\n <p className=\"text-[11px] text-neutral-500\">\n <span className=\"font-medium text-neutral-700\">{a.user_name}</span>{' moved from '}\n <span className=\"font-medium text-neutral-700\">{fromCol?.label ?? a.from_status}</span>{' to '}\n <span className=\"font-medium text-neutral-700\">{toCol?.label ?? a.to_status}</span>\n </p>\n )}\n <span className=\"text-[10px] text-neutral-400\">{formatDateTime(a.created_at)}</span>\n </div>\n </div>\n );\n }\n })}\n <div ref={commentsEndRef} />\n </div>\n </div>\n\n {/* Comment input */}\n <div className={`px-5 py-4 pb-5 border-t bg-white transition-colors ${isInternalComment ? 'border-amber-300 bg-amber-50/30' : 'border-neutral-200'}`}>\n <MentionTextarea\n value={newComment}\n onChange={setNewComment}\n onKeyDown={handleCommentKeyDown}\n rows={2}\n className={`w-full px-3 py-2 border rounded-lg text-xs focus:outline-none focus:ring-2 resize-none transition-colors placeholder:text-neutral-400 ${\n isInternalComment\n ? 'bg-amber-50/50 border-amber-200 focus:ring-amber-200/30 focus:border-amber-300'\n : 'bg-neutral-50 border-neutral-200 focus:bg-white focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50'\n }`}\n placeholder={isInternalComment ? 'Write an internal note... (only visible to team)' : 'Write a comment... (type @ to mention someone)'}\n />\n <div className=\"flex items-center justify-between mt-2.5\">\n {features.internalComments && user.is_internal ? (\n <button\n type=\"button\"\n onClick={() => setIsInternalComment(!isInternalComment)}\n className={`flex items-center gap-1.5 text-[11px] font-medium rounded-md px-2 py-1 transition-colors ${\n isInternalComment ? 'bg-amber-100 text-amber-700 border border-amber-200' : 'text-neutral-400 hover:text-neutral-600 hover:bg-neutral-100'\n }`}\n >\n <LockIcon size={12} /> Internal\n </button>\n ) : <div />}\n <button\n onClick={handleAddComment}\n disabled={detail.commentLoading || !newComment.trim()}\n className={`px-4 py-1.5 text-xs font-medium text-white rounded-lg transition-colors disabled:opacity-40 ${\n isInternalComment ? 'bg-amber-500 hover:bg-amber-600' : 'bg-[#FF5E00] hover:bg-[#E05200]'\n }`}\n >\n {detail.commentLoading ? 'Sending...' : isInternalComment ? 'Add Note' : 'Comment'}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Confirmation modals */}\n {showDeleteConfirm && (\n <div className=\"fixed inset-0 z-[110] flex items-center justify-center bg-black/40 eb-tb-animate-fade-in\">\n <div className=\"bg-white rounded-2xl shadow-2xl border border-neutral-200 w-full max-w-sm mx-4 eb-tb-animate-zoom-in\">\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-lg font-medium text-neutral-900\">Delete Task</h2>\n <p className=\"text-sm text-neutral-500\">Are you sure you want to delete <span className=\"font-medium text-neutral-900\">{task.title}</span>? This cannot be undone.</p>\n <div className=\"flex items-center justify-end gap-3\">\n <button onClick={() => setShowDeleteConfirm(false)} className=\"px-4 py-2 text-sm text-neutral-600 hover:text-neutral-900 transition-colors\">Cancel</button>\n <button onClick={handleDelete} disabled={saving} className=\"px-5 py-2 text-sm font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors disabled:opacity-60\">{saving ? 'Deleting...' : 'Delete'}</button>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {commentToDelete && (\n <div className=\"fixed inset-0 z-[110] flex items-center justify-center bg-black/40 eb-tb-animate-fade-in\">\n <div className=\"bg-white rounded-2xl shadow-2xl border border-neutral-200 w-full max-w-sm mx-4 eb-tb-animate-zoom-in\">\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-lg font-medium text-neutral-900\">Delete Comment</h2>\n <p className=\"text-sm text-neutral-500\">Are you sure you want to delete this comment? This cannot be undone.</p>\n <div className=\"flex items-center justify-end gap-3\">\n <button onClick={() => setCommentToDelete(null)} className=\"px-4 py-2 text-sm text-neutral-600 hover:text-neutral-900 transition-colors\">Cancel</button>\n <button onClick={handleDeleteComment} className=\"px-5 py-2 text-sm font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors\">Delete</button>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {showDiscardConfirm && (\n <div className=\"fixed inset-0 z-[110] flex items-center justify-center bg-black/40 eb-tb-animate-fade-in\">\n <div className=\"bg-white rounded-2xl shadow-2xl border border-neutral-200 w-full max-w-sm mx-4 eb-tb-animate-zoom-in\">\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-lg font-medium text-neutral-900\">Unsaved Changes</h2>\n <p className=\"text-sm text-neutral-500\">You have unsaved changes that will be lost. Are you sure you want to discard them?</p>\n <div className=\"flex items-center justify-end gap-3\">\n <button onClick={() => setShowDiscardConfirm(false)} className=\"px-4 py-2 text-sm text-neutral-600 hover:text-neutral-900 transition-colors\">Keep Editing</button>\n <button onClick={() => { handleDiscardChanges(); onClose(); }} className=\"px-5 py-2 text-sm font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors\">Discard</button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport type { Comment, ActivityEntry, TaskDetailResponse, UpdateTaskPayload } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\ninterface ApiError {\n response?: {\n data?: {\n detail?: string;\n };\n };\n message?: string;\n}\n\nfunction getErrorMessage(err: unknown): string {\n const apiErr = err as ApiError;\n return apiErr?.response?.data?.detail || apiErr?.message || 'An error occurred';\n}\n\nexport function useTaskDetail(taskId: string) {\n const { service, config } = useTaskBoardContext();\n\n const [comments, setComments] = useState<Comment[]>([]);\n const [activity, setActivity] = useState<ActivityEntry[]>([]);\n const [commentsLoaded, setCommentsLoaded] = useState(false);\n const [commentLoading, setCommentLoading] = useState(false);\n\n const fetchDetail = useCallback(async () => {\n try {\n const data = await service.getTask(taskId);\n setComments(data.comments || []);\n setActivity(data.activity || []);\n } catch {\n try {\n const comments = await service.listComments(taskId);\n setComments(comments);\n } catch { /* silent */ }\n } finally {\n setCommentsLoaded(true);\n }\n }, [taskId, service]);\n\n useEffect(() => { fetchDetail(); }, [fetchDetail]);\n\n const addComment = async (content: string, isInternal: boolean = false) => {\n setCommentLoading(true);\n try {\n await service.addComment(taskId, { content, is_internal: isInternal });\n await fetchDetail();\n } catch (err) {\n const message = getErrorMessage(err);\n config.onError?.(err instanceof Error ? err : new Error(message));\n } finally { setCommentLoading(false); }\n };\n\n const editComment = async (commentId: string, content: string) => {\n try {\n await service.editComment(taskId, commentId, { content });\n await fetchDetail();\n } catch (err: unknown) {\n const msg = getErrorMessage(err);\n throw new Error(msg);\n }\n };\n\n const deleteComment = async (commentId: string) => {\n try {\n await service.deleteComment(taskId, commentId);\n await fetchDetail();\n } catch (err: unknown) {\n const msg = getErrorMessage(err);\n throw new Error(msg);\n }\n };\n\n const saveField = async (field: string, value: unknown) => {\n await service.updateTask(taskId, { [field]: value } as UpdateTaskPayload);\n };\n\n return {\n comments,\n activity,\n commentsLoaded,\n commentLoading,\n addComment,\n editComment,\n deleteComment,\n saveField,\n refreshDetail: fetchDetail,\n };\n}\n","import React from 'react';\n\nconst MENTION_RE = /(@\\[.*?\\]\\(.*?\\))/g;\nconst MENTION_PARSE = /^@\\[(.*?)\\]\\((.*?)\\)$/;\n\n/** Renders text with @mentions highlighted as styled badges. */\nexport function MentionText({ text, className = \"\" }: { text: string; className?: string }) {\n if (!text) return null;\n\n const parts = text.split(MENTION_RE);\n\n return (\n <span className={className}>\n {parts.map((part, i) => {\n const match = part.match(MENTION_PARSE);\n if (match) {\n return (\n <span\n key={i}\n className=\"inline-flex items-center px-1.5 py-0.5 mx-0.5 bg-[#FF5E00]/10 text-[#FF5E00] rounded text-[11px] font-semibold cursor-default\"\n title={`@${match[2]}`}\n >\n @{match[1]}\n </span>\n );\n }\n return <span key={i}>{part}</span>;\n })}\n </span>\n );\n}\n\n/** Convert stored @[Name](username) to display @Name for textarea */\nexport function toDisplayText(stored: string): string {\n return stored.replace(/@\\[(.*?)\\]\\(.*?\\)/g, '@$1');\n}\n\n/** Convert display @Name back to stored @[Name](username) using a mention map */\nexport function toStoredText(display: string, mentionMap: Map<string, string>): string {\n let result = display;\n mentionMap.forEach((username, name) => {\n result = result.replace(new RegExp(`@${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`, 'g'), `@[${name}](${username})`);\n });\n return result;\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport type { MentionUser } from '../types';\nimport { getInitials } from '../utils/helpers';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { toDisplayText, toStoredText } from './MentionText';\n\nexport interface MentionTextareaProps {\n value: string;\n onChange: (val: string) => void;\n onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n placeholder?: string;\n rows?: number;\n className?: string;\n disabled?: boolean;\n}\n\nexport function MentionTextarea({\n value,\n onChange,\n onKeyDown,\n placeholder = \"\",\n rows = 2,\n className = \"\",\n disabled = false,\n}: MentionTextareaProps) {\n const { service, features } = useTaskBoardContext();\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [mentionQuery, setMentionQuery] = useState<string | null>(null);\n const [mentionStart, setMentionStart] = useState(0);\n const [mentionUsers, setMentionUsers] = useState<MentionUser[]>([]);\n const [selectedIndex, setSelectedIndex] = useState(0);\n const fetchTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const mentionMapRef = useRef<Map<string, string>>(new Map());\n\n // Initialize mention map from existing value\n useEffect(() => {\n const re = /@\\[(.*?)\\]\\((.*?)\\)/g;\n let match;\n while ((match = re.exec(value)) !== null) {\n mentionMapRef.current.set(match[1], match[2]);\n }\n }, []);\n\n // Fetch users when mention query changes\n useEffect(() => {\n if (!features.mentions || mentionQuery === null) {\n setMentionUsers([]);\n return;\n }\n if (fetchTimeoutRef.current) clearTimeout(fetchTimeoutRef.current);\n fetchTimeoutRef.current = setTimeout(async () => {\n try {\n const users = await service.searchMentionUsers(mentionQuery);\n setMentionUsers(users);\n setSelectedIndex(0);\n } catch {\n setMentionUsers([]);\n }\n }, 150);\n return () => { if (fetchTimeoutRef.current) clearTimeout(fetchTimeoutRef.current); };\n }, [mentionQuery, service, features.mentions]);\n\n const displayValue = toDisplayText(value);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newDisplay = e.target.value;\n const stored = toStoredText(newDisplay, mentionMapRef.current);\n onChange(stored);\n\n const cursorPos = e.target.selectionStart;\n const textBefore = newDisplay.slice(0, cursorPos);\n const atIndex = textBefore.lastIndexOf(\"@\");\n\n if (atIndex >= 0) {\n const charBefore = atIndex > 0 ? textBefore[atIndex - 1] : \" \";\n if (charBefore === \" \" || charBefore === \"\\n\" || atIndex === 0) {\n const query = textBefore.slice(atIndex + 1);\n if (!query.includes(\" \") || query.length <= 20) {\n setMentionQuery(query);\n setMentionStart(atIndex);\n return;\n }\n }\n }\n setMentionQuery(null);\n };\n\n const insertMention = (user: MentionUser) => {\n const display = toDisplayText(value);\n const before = display.slice(0, mentionStart);\n const after = display.slice(mentionStart + 1 + (mentionQuery?.length || 0));\n mentionMapRef.current.set(user.name, user.username);\n const newDisplay = before + `@${user.name} ` + after;\n const stored = toStoredText(newDisplay, mentionMapRef.current);\n onChange(stored);\n setMentionQuery(null);\n setTimeout(() => {\n if (textareaRef.current) {\n textareaRef.current.focus();\n const pos = before.length + user.name.length + 2;\n textareaRef.current.setSelectionRange(pos, pos);\n }\n }, 0);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (mentionQuery !== null && mentionUsers.length > 0) {\n if (e.key === \"ArrowDown\") { e.preventDefault(); setSelectedIndex((i) => Math.min(i + 1, mentionUsers.length - 1)); return; }\n if (e.key === \"ArrowUp\") { e.preventDefault(); setSelectedIndex((i) => Math.max(i - 1, 0)); return; }\n if (e.key === \"Enter\" || e.key === \"Tab\") { e.preventDefault(); insertMention(mentionUsers[selectedIndex]); return; }\n if (e.key === \"Escape\") { e.preventDefault(); setMentionQuery(null); return; }\n }\n onKeyDown?.(e);\n };\n\n return (\n <div className=\"relative\">\n <textarea\n ref={textareaRef}\n value={displayValue}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n rows={rows}\n className={className}\n placeholder={placeholder}\n disabled={disabled}\n />\n {mentionQuery !== null && mentionUsers.length > 0 && (\n <div className=\"absolute bottom-full left-0 mb-1 w-64 bg-white border border-neutral-200 rounded-lg shadow-lg z-50 py-1 max-h-48 overflow-y-auto\">\n <div className=\"px-2.5 py-1.5 text-[10px] font-medium text-neutral-400 uppercase tracking-wide\">People</div>\n {mentionUsers.map((user, i) => (\n <button\n key={user.username}\n onClick={() => insertMention(user)}\n className={`w-full flex items-center gap-2.5 px-3 py-2 text-xs text-left hover:bg-neutral-50 ${\n i === selectedIndex ? \"bg-neutral-50\" : \"\"\n }`}\n >\n <div className=\"w-6 h-6 rounded-full bg-[#FF5E00] flex items-center justify-center shrink-0\">\n <span className=\"text-[9px] font-medium text-white\">{getInitials(user.name)}</span>\n </div>\n <div className=\"min-w-0\">\n <div className=\"text-xs font-medium text-neutral-800 truncate\">{user.name}</div>\n <div className=\"text-[10px] text-neutral-400 truncate\">{user.email}</div>\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["useState","useEffect","useCallback","useCallback","useRef","useRef","useCallback","useState","useCallback","jsx","useEffect","useRef","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","TaskCard","jsx","jsxs","useRef","useEffect","useState","useRef","useEffect","jsx","jsxs","useState","useRef","useEffect","useState","useEffect","useCallback","useRef","jsx","jsxs","useState","useRef","useCallback","useEffect","handleClick","useState","jsx","jsxs","useState","useState","useEffect","useRef","useState","useEffect","useCallback","useState","useCallback","comments","useEffect","jsx","jsxs","useState","useEffect","useRef","jsx","jsxs","useRef","useState","useEffect","jsx","jsxs","useState","useRef","useEffect","Fragment","jsx","jsxs","useState","useEffect","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/TaskBoard.tsx","../src/context/TaskBoardProvider.tsx","../src/services/taskBoardService.ts","../src/utils/constants.ts","../src/hooks/useTaskBoard.ts","../src/hooks/useTaskActions.ts","../src/hooks/useShareLink.ts","../src/components/SkeletonPulse.tsx","../src/components/KanbanColumn.tsx","../src/components/TaskCard.tsx","../src/utils/helpers.ts","../src/components/PriorityBadge.tsx","../src/icons/index.tsx","../src/components/TagBadge.tsx","../src/components/UserAvatar.tsx","../src/components/FilterBar.tsx","../src/components/NotificationBell.tsx","../src/components/CreateTaskModal.tsx","../src/components/TaskDetailPanel.tsx","../src/hooks/useTaskDetail.ts","../src/components/MentionText.tsx","../src/components/MentionTextarea.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { DragDropContext, type DropResult } from '@hello-pangea/dnd';\nimport type { Task } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { useTaskBoard } from '../hooks/useTaskBoard';\nimport { useTaskActions } from '../hooks/useTaskActions';\nimport { useShareLink } from '../hooks/useShareLink';\nimport { PREDEFINED_TAGS } from '../utils/constants';\nimport { BoardSkeleton } from './SkeletonPulse';\nimport { KanbanColumn } from './KanbanColumn';\nimport { FilterBar } from './FilterBar';\nimport { NotificationBell } from './NotificationBell';\nimport { CreateTaskModal } from './CreateTaskModal';\nimport { TaskDetailPanel } from './TaskDetailPanel';\nimport { PlusIcon, XIcon, FeedbackIcon } from '../icons';\n\nexport interface TaskBoardProps {\n /** Optional class name for the outer container */\n className?: string;\n /** Optional header content (e.g., feedback link) to render in the header bar */\n headerActions?: React.ReactNode;\n /** Callback when a task detail panel should open */\n onTaskOpen?: (task: Task) => void;\n /** Callback for the Share Feedback button. If not provided, the button is hidden. */\n onShareFeedback?: () => void;\n /** Render function for the task detail panel. If omitted, uses built-in TaskDetailPanel. */\n renderTaskDetail?: (props: { task: Task; onClose: () => void; onUpdate: () => void }) => React.ReactNode;\n /** Render function for the create task modal. If omitted, uses built-in CreateTaskModal. */\n renderCreateTask?: (props: { projectSlug: string; defaultStatus: string; onClose: () => void; onCreate: () => void }) => React.ReactNode;\n}\n\nexport function TaskBoard({\n className = \"\",\n headerActions,\n onTaskOpen,\n onShareFeedback,\n renderTaskDetail,\n renderCreateTask,\n}: TaskBoardProps) {\n const { columns, features, service } = useTaskBoardContext();\n\n const board = useTaskBoard();\n const actions = useTaskActions(board.tasks, board.setTasks, board.fetchTasks);\n const { copiedTaskId, copyShareLink } = useShareLink();\n\n const [selectedTask, setSelectedTask] = useState<Task | null>(null);\n const [createForStatus, setCreateForStatus] = useState(\"\");\n const [filterTags, setFilterTags] = useState<string[]>([]);\n\n // Handle shared task URL (?task=id)\n const [sharedTaskHandled, setSharedTaskHandled] = useState(false);\n useEffect(() => {\n if (sharedTaskHandled || !board.selectedProject || board.boardLoading) return;\n if (typeof window === 'undefined') return;\n const params = new URLSearchParams(window.location.search);\n const taskId = params.get(\"task\");\n if (!taskId) return;\n setSharedTaskHandled(true);\n let cancelled = false;\n (async () => {\n try {\n const task = await service.getTask(taskId);\n if (cancelled) return;\n setSelectedTask(task);\n service.markTaskRead(taskId).catch(() => {});\n const url = new URL(window.location.href);\n url.searchParams.delete(\"task\");\n window.history.replaceState({}, \"\", url.toString());\n } catch {\n if (!cancelled) board.setError(\"Could not open shared task.\");\n }\n })();\n return () => { cancelled = true; };\n }, [board.selectedProject, board.boardLoading, sharedTaskHandled, service]);\n\n // Update URL when project changes\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (board.selectedProject && board.projects.length > 1) {\n const url = new URL(window.location.href);\n url.searchParams.set(\"project\", board.selectedProject);\n window.history.replaceState({}, \"\", url.toString());\n }\n }, [board.selectedProject, board.projects]);\n\n const handleDragEnd = useCallback((result: DropResult) => {\n const { draggableId, source, destination } = result;\n if (!destination) return;\n if (source.droppableId === destination.droppableId && source.index === destination.index) return;\n\n actions.moveTask(\n draggableId,\n source.droppableId,\n destination.droppableId,\n source.index,\n destination.index\n );\n }, [actions]);\n\n const handleTaskClick = (task: Task) => {\n setSelectedTask(task);\n onTaskOpen?.(task);\n actions.markTaskRead(task.id);\n // Optimistically clear unread\n if (task.has_unread) {\n board.setTasks((prev) => {\n const updated = { ...prev };\n const col = updated[task.status];\n if (col) {\n updated[task.status] = col.map((t) =>\n t.id === task.id ? { ...t, has_unread: false } : t\n );\n }\n return updated;\n });\n board.setColumnUnreads((prev) => ({\n ...prev,\n [task.status]: Math.max(0, (prev[task.status] || 0) - 1),\n }));\n }\n };\n\n const handleOpenTaskFromNotification = async (taskId: string, projectSlug: string) => {\n if (board.selectedProject !== projectSlug) {\n board.setSelectedProject(projectSlug);\n }\n try {\n const task = await service.getTask(taskId);\n setSelectedTask(task);\n service.markTaskRead(taskId).catch(() => {});\n } catch {\n board.setError(\"Could not open task.\");\n }\n };\n\n const predefinedValues = PREDEFINED_TAGS.map((p) => p.value);\n\n // Built-in create/detail handlers\n const handleCreateClose = () => setCreateForStatus(\"\");\n const handleCreateDone = () => { board.fetchTasks(); board.showSuccess(\"Task created\"); };\n const handleDetailClose = () => setSelectedTask(null);\n\n return (\n <div className={`flex flex-col h-full ${className}`}>\n {/* Header */}\n <div className=\"mb-4 sm:mb-6 shrink-0\">\n <div className=\"flex items-center justify-between mb-1 sm:mb-2\">\n <h1 className=\"text-2xl sm:text-3xl font-medium text-neutral-900 tracking-tight\">\n Task Board\n </h1>\n <div className=\"flex items-center gap-2\">\n {onShareFeedback && (\n <button\n onClick={onShareFeedback}\n className=\"flex items-center gap-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 px-3 py-2 sm:py-2.5 rounded-lg border border-neutral-200 hover:border-neutral-300 transition-colors\"\n >\n <FeedbackIcon size={16} />\n <span className=\"hidden sm:inline\">Share Feedback</span>\n </button>\n )}\n {headerActions}\n {features.notifications && (\n <NotificationBell onOpenTask={handleOpenTaskFromNotification} />\n )}\n {board.projects.length > 0 && (\n <button\n onClick={() => setCreateForStatus(\"backlog\")}\n className=\"flex items-center gap-1.5 sm:gap-2 text-xs font-semibold text-white bg-[#FF5E00] hover:bg-[#E05200] px-3 sm:px-4 py-2 sm:py-2.5 rounded-lg transition-colors shadow-sm\"\n >\n <PlusIcon size={16} />\n <span className=\"hidden sm:inline\">New Task</span>\n <span className=\"sm:hidden\">New</span>\n </button>\n )}\n </div>\n </div>\n <p className=\"text-neutral-500 font-light text-sm sm:text-lg\">\n Track and manage work across projects.\n </p>\n </div>\n\n {/* Success / Error */}\n {board.successMessage && (\n <div className=\"mb-4 p-3 bg-green-50 border border-green-200 rounded-lg text-green-700 text-sm\">\n {board.successMessage}\n </div>\n )}\n {board.error && (\n <div className=\"mb-4 p-3 bg-red-50 border border-red-200 rounded-lg text-red-600 text-sm flex items-center justify-between\">\n {board.error}\n <button onClick={() => board.setError(\"\")} className=\"text-red-400 hover:text-red-600\">\n <XIcon size={16} />\n </button>\n </div>\n )}\n\n {board.projects.length === 0 ? (\n <div className=\"flex-1 flex items-center justify-center\">\n <div className=\"text-center\">\n <h2 className=\"text-xl font-medium text-neutral-900 mb-2\">No Projects Available</h2>\n <p className=\"text-neutral-500\">You don't have access to any projects yet.</p>\n </div>\n </div>\n ) : (\n <>\n {/* Filter bar */}\n <FilterBar\n projects={board.projects}\n selectedProject={board.selectedProject}\n onSelectProject={board.setSelectedProject}\n filterTags={filterTags}\n onSetFilterTags={setFilterTags}\n />\n\n {/* Board */}\n {board.boardLoading ? (\n <BoardSkeleton />\n ) : (\n <div className=\"flex-1 min-h-0 eb-tb-board-scroll overflow-y-hidden pb-4\">\n <DragDropContext onDragEnd={handleDragEnd}>\n <div className=\"flex gap-4 min-w-max h-full\">\n {columns.map((col) => {\n const allColumnTasks = board.tasks[col.key] || [];\n const columnTasks = filterTags.length > 0\n ? allColumnTasks.filter((t) => {\n const taskTags = t.tags || [];\n return filterTags.some((f) => {\n if (f === \"__other__\") return taskTags.some((tag) => !predefinedValues.includes(tag));\n return taskTags.includes(f);\n });\n })\n : allColumnTasks;\n\n return (\n <KanbanColumn\n key={col.key}\n column={col}\n tasks={columnTasks}\n totalCount={board.columnTotals[col.key] || 0}\n unreadCount={board.columnUnreads[col.key] || 0}\n loadingMore={board.loadingMore[col.key] || false}\n onAddTask={() => setCreateForStatus(col.key)}\n onTaskClick={handleTaskClick}\n onTaskShare={(taskId, e) => copyShareLink(taskId, board.selectedProject)}\n copiedTaskId={copiedTaskId}\n onLoadMore={() => board.loadMoreTasks(col.key)}\n />\n );\n })}\n </div>\n </DragDropContext>\n </div>\n )}\n </>\n )}\n\n {/* Create Task Modal — render prop override or built-in */}\n {createForStatus && (\n renderCreateTask\n ? renderCreateTask({\n projectSlug: board.selectedProject,\n defaultStatus: createForStatus,\n onClose: handleCreateClose,\n onCreate: handleCreateDone,\n })\n : <CreateTaskModal\n projectSlug={board.selectedProject}\n defaultStatus={createForStatus}\n onClose={handleCreateClose}\n onCreate={handleCreateDone}\n />\n )}\n\n {/* Task Detail — render prop override or built-in */}\n {selectedTask && (\n renderTaskDetail\n ? renderTaskDetail({\n task: selectedTask,\n onClose: handleDetailClose,\n onUpdate: board.fetchTasks,\n })\n : <TaskDetailPanel\n task={selectedTask}\n projectSlug={board.selectedProject}\n onClose={handleDetailClose}\n onUpdate={board.fetchTasks}\n />\n )}\n </div>\n );\n}\n","import React, { createContext, useContext, useMemo } from 'react';\nimport type { ApiClient, TaskBoardUser, Project, ColumnConfig, PriorityConfig, TagConfig, Task } from '../types';\nimport { TaskBoardService, createTaskBoardService } from '../services/taskBoardService';\nimport { DEFAULT_COLUMNS, DEFAULT_PRIORITIES, PREDEFINED_TAGS } from '../utils/constants';\n\nexport interface TaskBoardConfig {\n /** Axios-like API client with auth headers pre-configured */\n apiClient: ApiClient;\n /** Current logged-in user */\n user: TaskBoardUser;\n /** Available projects (if not provided, derived from user.apps) */\n projects?: Project[];\n /** Column configuration (defaults to 8-column kanban) */\n columns?: ColumnConfig[];\n /** Priority levels (defaults to Critical/High/Medium/Low) */\n priorities?: PriorityConfig[];\n /** Predefined tags (defaults to 6 built-in tags) */\n tags?: TagConfig[];\n /** Base API path (defaults to '/api/v1/taskboard') */\n apiBasePath?: string;\n\n /** Callbacks */\n onTaskCreate?: (task: Task) => void;\n onTaskUpdate?: (task: Task) => void;\n onTaskDelete?: (taskId: string) => void;\n onError?: (error: Error) => void;\n onNavigate?: (path: string) => void;\n\n /** Feature flags */\n features?: {\n dragAndDrop?: boolean;\n comments?: boolean;\n mentions?: boolean;\n notifications?: boolean;\n internalComments?: boolean;\n tags?: boolean;\n sharing?: boolean;\n filters?: boolean;\n unreadIndicators?: boolean;\n };\n}\n\nexport interface TaskBoardContextValue {\n service: TaskBoardService;\n user: TaskBoardUser;\n projects: Project[];\n columns: ColumnConfig[];\n priorities: PriorityConfig[];\n tags: TagConfig[];\n config: TaskBoardConfig;\n features: Required<NonNullable<TaskBoardConfig['features']>>;\n}\n\nconst TaskBoardContext = createContext<TaskBoardContextValue | null>(null);\n\nexport function useTaskBoardContext(): TaskBoardContextValue {\n const ctx = useContext(TaskBoardContext);\n if (!ctx) {\n throw new Error('useTaskBoardContext must be used within a <TaskBoardProvider>');\n }\n return ctx;\n}\n\nexport function TaskBoardProvider({\n children,\n ...config\n}: TaskBoardConfig & { children: React.ReactNode }) {\n const service = useMemo(\n () => createTaskBoardService(config.apiClient, config.apiBasePath),\n [config.apiClient, config.apiBasePath]\n );\n\n const features = useMemo(\n () => ({\n dragAndDrop: config.features?.dragAndDrop ?? true,\n comments: config.features?.comments ?? true,\n mentions: config.features?.mentions ?? true,\n notifications: config.features?.notifications ?? true,\n internalComments: config.features?.internalComments ?? true,\n tags: config.features?.tags ?? true,\n sharing: config.features?.sharing ?? true,\n filters: config.features?.filters ?? true,\n unreadIndicators: config.features?.unreadIndicators ?? true,\n }),\n [config.features]\n );\n\n const value = useMemo<TaskBoardContextValue>(\n () => ({\n service,\n user: config.user,\n projects: config.projects ?? [],\n columns: config.columns ?? DEFAULT_COLUMNS,\n priorities: config.priorities ?? DEFAULT_PRIORITIES,\n tags: config.tags ?? PREDEFINED_TAGS,\n config,\n features,\n }),\n [service, config, features]\n );\n\n return (\n <TaskBoardContext.Provider value={value}>\n {children}\n </TaskBoardContext.Provider>\n );\n}\n","import type {\n ApiClient,\n Project,\n Task,\n TaskDetailResponse,\n ColumnResponse,\n Notification,\n NotificationCountResponse,\n MentionUser,\n Comment,\n CreateTaskPayload,\n UpdateTaskPayload,\n CreateCommentPayload,\n EditCommentPayload,\n} from '../types';\n\nexport interface TaskBoardService {\n // ─── Tasks ───\n listTasks(projectSlug: string, perColumn?: number): Promise<Record<string, ColumnResponse>>;\n listColumnTasks(projectSlug: string, statusKey: string, offset: number, limit: number): Promise<Task[]>;\n getTask(taskId: string): Promise<TaskDetailResponse>;\n createTask(data: CreateTaskPayload): Promise<Task>;\n updateTask(taskId: string, data: UpdateTaskPayload): Promise<Task>;\n deleteTask(taskId: string): Promise<void>;\n markTaskRead(taskId: string): Promise<void>;\n\n // ─── Comments ───\n listComments(taskId: string): Promise<Comment[]>;\n addComment(taskId: string, data: CreateCommentPayload): Promise<Comment>;\n editComment(taskId: string, commentId: string, data: EditCommentPayload): Promise<Comment>;\n deleteComment(taskId: string, commentId: string): Promise<void>;\n\n // ─── Projects ───\n listProjects(): Promise<Project[]>;\n\n // ─── Mentions ───\n searchMentionUsers(query: string): Promise<MentionUser[]>;\n\n // ─── Notifications ───\n getNotificationCount(): Promise<number>;\n listNotifications(limit?: number): Promise<Notification[]>;\n markNotificationRead(notificationId: string): Promise<void>;\n markAllNotificationsRead(): Promise<void>;\n}\n\nexport function createTaskBoardService(\n apiClient: ApiClient,\n basePath: string = '/api/v1/taskboard'\n): TaskBoardService {\n return {\n // ─── Tasks ───\n\n async listTasks(projectSlug, perColumn = 10) {\n const { data } = await apiClient.get<Record<string, ColumnResponse>>(\n `${basePath}/tasks?project_slug=${encodeURIComponent(projectSlug)}&per_column=${perColumn}`\n );\n return data;\n },\n\n async listColumnTasks(projectSlug, statusKey, offset, limit) {\n const { data } = await apiClient.get<Task[]>(\n `${basePath}/tasks/column?project_slug=${encodeURIComponent(projectSlug)}&status_key=${encodeURIComponent(statusKey)}&offset=${offset}&limit=${limit}`\n );\n return data;\n },\n\n async getTask(taskId) {\n const { data } = await apiClient.get<TaskDetailResponse>(`${basePath}/tasks/${taskId}`);\n return data;\n },\n\n async createTask(payload) {\n const { data } = await apiClient.post<Task>(`${basePath}/tasks`, payload);\n return data;\n },\n\n async updateTask(taskId, payload) {\n const { data } = await apiClient.patch<Task>(`${basePath}/tasks/${taskId}`, payload);\n return data;\n },\n\n async deleteTask(taskId) {\n await apiClient.delete(`${basePath}/tasks/${taskId}`);\n },\n\n async markTaskRead(taskId) {\n await apiClient.post(`${basePath}/tasks/${taskId}/read`);\n },\n\n // ─── Comments ───\n\n async listComments(taskId) {\n const { data } = await apiClient.get<Comment[]>(`${basePath}/tasks/${taskId}/comments`);\n return data;\n },\n\n async addComment(taskId, payload) {\n const { data } = await apiClient.post<Comment>(`${basePath}/tasks/${taskId}/comments`, payload);\n return data;\n },\n\n async editComment(taskId, commentId, payload) {\n const { data } = await apiClient.patch<Comment>(\n `${basePath}/tasks/${taskId}/comments/${commentId}`,\n payload\n );\n return data;\n },\n\n async deleteComment(taskId, commentId) {\n await apiClient.delete(`${basePath}/tasks/${taskId}/comments/${commentId}`);\n },\n\n // ─── Projects ───\n\n async listProjects() {\n const { data } = await apiClient.get<Project[]>(`${basePath}/projects`);\n return data;\n },\n\n // ─── Mentions ───\n\n async searchMentionUsers(query) {\n const { data } = await apiClient.get<MentionUser[]>(\n `${basePath}/mentions/users?q=${encodeURIComponent(query)}`\n );\n return data;\n },\n\n // ─── Notifications ───\n\n async getNotificationCount() {\n const { data } = await apiClient.get<NotificationCountResponse>(\n `${basePath}/notifications/count`\n );\n return data.count;\n },\n\n async listNotifications(limit = 30) {\n const { data } = await apiClient.get<Notification[]>(\n `${basePath}/notifications?limit=${limit}`\n );\n return data;\n },\n\n async markNotificationRead(notificationId) {\n await apiClient.patch(`${basePath}/notifications/${notificationId}/read`);\n },\n\n async markAllNotificationsRead() {\n await apiClient.post(`${basePath}/notifications/read-all`);\n },\n };\n}\n","import type { ColumnConfig, PriorityConfig, TagConfig, DescriptionSectionConfig, StructuredDescription } from '../types';\n\nexport const DEFAULT_COLUMNS: ColumnConfig[] = [\n { key: \"backlog\", label: \"Backlog\", color: \"bg-neutral-400\", description: \"Tasks not yet scheduled\" },\n { key: \"blocked\", label: \"Blocked\", color: \"bg-red-500\", description: \"Waiting on a dependency\" },\n { key: \"queued\", label: \"Queued\", color: \"bg-blue-500\", description: \"Scheduled for this sprint\" },\n { key: \"in_progress\", label: \"In Progress\", color: \"bg-amber-500\", description: \"Actively being worked on\" },\n { key: \"in_testing\", label: \"In Testing\", color: \"bg-teal-500\", description: \"Under QA and validation\" },\n { key: \"client_review\", label: \"Client Review\", color: \"bg-purple-500\", description: \"Live & ready for client review\" },\n { key: \"changes_requested\", label: \"Changes Requested\", color: \"bg-orange-500\", description: \"Revisions needed from review\" },\n { key: \"approved\", label: \"Approved\", color: \"bg-green-500\", description: \"Signed off and complete\" },\n];\n\nexport const DEFAULT_PRIORITIES: PriorityConfig[] = [\n { value: \"urgent\", label: \"Critical\", className: \"bg-red-50 text-red-600 border-red-200\" },\n { value: \"high\", label: \"High\", className: \"bg-orange-50 text-orange-600 border-orange-200\" },\n { value: \"medium\", label: \"Medium\", className: \"bg-amber-50 text-amber-600 border-amber-200\" },\n { value: \"low\", label: \"Low\", className: \"bg-neutral-100 text-neutral-500 border-neutral-200\" },\n];\n\nexport const PREDEFINED_TAGS: TagConfig[] = [\n { value: \"traceability\", label: \"Traceability\", className: \"bg-blue-50 text-blue-600 border-blue-200\" },\n { value: \"info-architecture\", label: \"Info Architecture\", className: \"bg-purple-50 text-purple-600 border-purple-200\" },\n { value: \"ui-ux\", label: \"UI/UX\", className: \"bg-pink-50 text-pink-600 border-pink-200\" },\n { value: \"workflow-logic\", label: \"Workflow Logic\", className: \"bg-teal-50 text-teal-600 border-teal-200\" },\n { value: \"legal-reasoning\", label: \"Legal Reasoning\", className: \"bg-amber-50 text-amber-600 border-amber-200\" },\n { value: \"bug-fix\", label: \"Bug Fix\", className: \"bg-red-50 text-red-600 border-red-200\" },\n];\n\nexport const DESCRIPTION_SECTIONS: DescriptionSectionConfig[] = [\n { key: \"problem\", label: \"Problem\" },\n { key: \"user_story\", label: \"User Story\" },\n { key: \"proposed_behavior\", label: \"Proposed Behavior\" },\n { key: \"acceptance_criteria\", label: \"Acceptance Criteria\" },\n { key: \"open_questions\", label: \"Open Questions\" },\n];\n\nexport const EMPTY_DESCRIPTION: StructuredDescription = {\n problem: \"\",\n user_story: \"\",\n proposed_behavior: \"\",\n acceptance_criteria: \"\",\n open_questions: \"\",\n};\n\nexport const POSITION_GAP = 1000;\nexport const DEFAULT_PAGE_SIZE = 10;\nexport const NOTIFICATION_POLL_INTERVAL = 30000;\n","import { useState, useEffect, useCallback, useMemo, useRef } from 'react';\nimport type { Task, TasksByStatus, ColumnTotals, ColumnUnreads, Project } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { DEFAULT_PAGE_SIZE } from '../utils/constants';\n\nexport function useTaskBoard() {\n const { service, user, projects: configProjects, columns, config } = useTaskBoardContext();\n\n const [fetchedProjects, setFetchedProjects] = useState<Project[]>([]);\n\n // Fetch projects from API when none are provided via props\n useEffect(() => {\n if (configProjects.length > 0) return;\n let cancelled = false;\n (async () => {\n try {\n const data = await service.listProjects();\n if (!cancelled) setFetchedProjects(data);\n } catch {\n // Projects endpoint may not exist — fall back to empty\n }\n })();\n return () => { cancelled = true; };\n }, [configProjects, service]);\n\n const projects = configProjects.length > 0 ? configProjects : fetchedProjects;\n\n const [selectedProject, setSelectedProject] = useState(\"\");\n const [tasks, setTasks] = useState<TasksByStatus>({});\n const [columnTotals, setColumnTotals] = useState<ColumnTotals>({});\n const [columnUnreads, setColumnUnreads] = useState<ColumnUnreads>({});\n const [boardLoading, setBoardLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState<Record<string, boolean>>({});\n const [error, setError] = useState(\"\");\n const [successMessage, setSuccessMessage] = useState(\"\");\n\n // Auto-select project from URL or first available\n useEffect(() => {\n if (selectedProject || projects.length === 0) return;\n if (typeof window !== 'undefined') {\n const params = new URLSearchParams(window.location.search);\n const urlProject = params.get(\"project\");\n if (urlProject && projects.find((p) => p.slug === urlProject)) {\n setSelectedProject(urlProject);\n return;\n }\n }\n setSelectedProject(projects[0].slug);\n }, [projects, selectedProject]);\n\n const fetchTasks = useCallback(async () => {\n if (!selectedProject) return;\n setBoardLoading(true);\n try {\n const data = await service.listTasks(selectedProject, DEFAULT_PAGE_SIZE);\n const newTasks: TasksByStatus = {};\n const newTotals: ColumnTotals = {};\n const newUnreads: ColumnUnreads = {};\n for (const key of columns.map((c) => c.key)) {\n const col = data[key];\n if (col) {\n newTasks[key] = col.tasks || [];\n newTotals[key] = col.total || 0;\n newUnreads[key] = col.unread || 0;\n } else {\n newTasks[key] = [];\n newTotals[key] = 0;\n newUnreads[key] = 0;\n }\n }\n setTasks(newTasks);\n setColumnTotals(newTotals);\n setColumnUnreads(newUnreads);\n } catch {\n setError(\"Failed to load tasks\");\n } finally {\n setBoardLoading(false);\n }\n }, [selectedProject, service, columns]);\n\n useEffect(() => { fetchTasks(); }, [fetchTasks]);\n\n const loadMoreTasks = useCallback(async (statusKey: string) => {\n if (!selectedProject || loadingMore[statusKey]) return;\n const current = tasks[statusKey]?.length || 0;\n const total = columnTotals[statusKey] || 0;\n if (current >= total) return;\n\n setLoadingMore((prev) => ({ ...prev, [statusKey]: true }));\n try {\n const newTasks = await service.listColumnTasks(\n selectedProject, statusKey, current, DEFAULT_PAGE_SIZE\n );\n setTasks((prev) => ({\n ...prev,\n [statusKey]: [...(prev[statusKey] || []), ...newTasks],\n }));\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoadingMore((prev) => ({ ...prev, [statusKey]: false }));\n }\n }, [selectedProject, tasks, columnTotals, loadingMore, service, config]);\n\n const successTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n return () => {\n if (successTimeoutRef.current) clearTimeout(successTimeoutRef.current);\n };\n }, []);\n\n const showSuccess = (msg: string) => {\n setSuccessMessage(msg);\n if (successTimeoutRef.current) clearTimeout(successTimeoutRef.current);\n successTimeoutRef.current = setTimeout(() => setSuccessMessage(\"\"), 3000);\n };\n\n return {\n projects,\n selectedProject,\n setSelectedProject,\n tasks,\n setTasks,\n columnTotals,\n columnUnreads,\n setColumnUnreads,\n boardLoading,\n loadingMore,\n error,\n setError,\n successMessage,\n showSuccess,\n fetchTasks,\n loadMoreTasks,\n };\n}\n","import { useCallback, useRef } from 'react';\nimport type { Task, TasksByStatus, CreateTaskPayload, UpdateTaskPayload } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { POSITION_GAP } from '../utils/constants';\n\nexport function useTaskActions(\n tasks: TasksByStatus,\n setTasks: React.Dispatch<React.SetStateAction<TasksByStatus>>,\n fetchTasks: () => Promise<void>,\n) {\n const { service, config } = useTaskBoardContext();\n\n const tasksRef = useRef(tasks);\n tasksRef.current = tasks;\n\n const createTask = useCallback(async (data: CreateTaskPayload): Promise<Task> => {\n const task = await service.createTask(data);\n config.onTaskCreate?.(task);\n await fetchTasks();\n return task;\n }, [service, config, fetchTasks]);\n\n const updateTask = useCallback(async (taskId: string, data: UpdateTaskPayload): Promise<Task> => {\n const task = await service.updateTask(taskId, data);\n config.onTaskUpdate?.(task);\n await fetchTasks();\n return task;\n }, [service, config, fetchTasks]);\n\n const deleteTask = useCallback(async (taskId: string): Promise<void> => {\n await service.deleteTask(taskId);\n config.onTaskDelete?.(taskId);\n await fetchTasks();\n }, [service, config, fetchTasks]);\n\n const markTaskRead = useCallback(async (taskId: string): Promise<void> => {\n service.markTaskRead(taskId).catch(() => {});\n }, [service]);\n\n const moveTask = useCallback(async (\n taskId: string,\n sourceStatus: string,\n destStatus: string,\n sourceIndex: number,\n destIndex: number,\n ) => {\n const currentTasks = tasksRef.current;\n const sourceCol = [...(currentTasks[sourceStatus] || [])];\n const destCol = sourceStatus === destStatus ? sourceCol : [...(currentTasks[destStatus] || [])];\n\n const [movedTask] = sourceCol.splice(sourceIndex, 1);\n if (!movedTask) return;\n\n const updatedTask = { ...movedTask, status: destStatus };\n destCol.splice(destIndex, 0, updatedTask);\n\n // Calculate position\n let newPosition: number;\n if (destCol.length === 1) {\n newPosition = POSITION_GAP;\n } else if (destIndex === 0) {\n newPosition = (destCol[1]?.position ?? POSITION_GAP) - POSITION_GAP;\n } else if (destIndex === destCol.length - 1) {\n newPosition = (destCol[destCol.length - 2]?.position ?? 0) + POSITION_GAP;\n } else {\n const above = destCol[destIndex - 1]?.position ?? 0;\n const below = destCol[destIndex + 1]?.position ?? above + POSITION_GAP * 2;\n newPosition = (above + below) / 2;\n }\n updatedTask.position = newPosition;\n\n // Optimistic update\n const newTasks = { ...currentTasks };\n newTasks[sourceStatus] = sourceCol;\n if (sourceStatus !== destStatus) {\n newTasks[destStatus] = destCol;\n }\n setTasks(newTasks);\n\n // Persist\n try {\n await service.updateTask(taskId, { status: destStatus, position: newPosition });\n } catch {\n fetchTasks();\n }\n }, [setTasks, service, fetchTasks]);\n\n return { createTask, updateTask, deleteTask, markTaskRead, moveTask };\n}\n","import { useState, useCallback } from 'react';\n\nexport function useShareLink() {\n const [copiedTaskId, setCopiedTaskId] = useState<string | null>(null);\n\n const copyShareLink = useCallback((taskId: string, projectSlug: string) => {\n if (typeof window === 'undefined') return;\n const url = new URL(window.location.origin + window.location.pathname);\n url.searchParams.set(\"project\", projectSlug);\n url.searchParams.set(\"task\", taskId);\n navigator.clipboard.writeText(url.toString()).then(() => {\n setCopiedTaskId(taskId);\n setTimeout(() => setCopiedTaskId(null), 2000);\n });\n }, []);\n\n return { copiedTaskId, copyShareLink };\n}\n","import React from 'react';\n\nexport function SkeletonPulse({ className = \"\" }: { className?: string }) {\n return <div className={`animate-pulse rounded bg-neutral-200/60 ${className}`} />;\n}\n\nexport function SkeletonCard() {\n return (\n <div className=\"bg-white rounded-lg border border-neutral-200 p-3 space-y-2.5\">\n <SkeletonPulse className=\"h-4 w-3/4\" />\n <SkeletonPulse className=\"h-4 w-16 rounded-sm\" />\n <SkeletonPulse className=\"h-3 w-full\" />\n <SkeletonPulse className=\"h-3 w-2/3\" />\n <div className=\"flex items-center justify-between pt-1\">\n <SkeletonPulse className=\"h-2.5 w-12\" />\n <SkeletonPulse className=\"h-2.5 w-8\" />\n </div>\n </div>\n );\n}\n\nexport function BoardSkeleton() {\n const cardCounts = [3, 2, 2, 1, 1, 0, 1];\n return (\n <div className=\"flex-1 min-h-0 overflow-hidden pb-4\">\n <div className=\"flex gap-4 min-w-max h-full\">\n {cardCounts.map((count, i) => (\n <div key={i} className=\"w-[280px] flex flex-col shrink-0\">\n <div className=\"flex items-center gap-2 mb-3 px-1\">\n <SkeletonPulse className=\"w-2 h-2 rounded-full\" />\n <SkeletonPulse className=\"h-3 w-20\" />\n </div>\n <div className=\"flex-1 rounded-xl bg-neutral-100/50 p-2 space-y-2\">\n {Array.from({ length: count }).map((_, j) => (\n <SkeletonCard key={j} />\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import React, { useEffect, useRef } from 'react';\nimport { Droppable } from '@hello-pangea/dnd';\nimport type { Task, ColumnConfig } from '../types';\nimport { TaskCard } from './TaskCard';\nimport { SkeletonCard } from './SkeletonPulse';\nimport { PlusIcon } from '../icons';\n\nexport interface KanbanColumnProps {\n column: ColumnConfig;\n tasks: Task[];\n totalCount: number;\n unreadCount: number;\n loadingMore: boolean;\n onAddTask: () => void;\n onTaskClick: (task: Task) => void;\n onTaskShare: (taskId: string, e: React.MouseEvent) => void;\n copiedTaskId: string | null;\n onLoadMore: () => void;\n}\n\nfunction LoadMoreSentinel({ loading, onLoadMore, remaining }: { loading: boolean; onLoadMore: () => void; remaining: number }) {\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const el = sentinelRef.current;\n if (!el) return;\n const observer = new IntersectionObserver(\n ([entry]) => { if (entry.isIntersecting && !loading) onLoadMore(); },\n { threshold: 0.1 }\n );\n observer.observe(el);\n return () => observer.disconnect();\n }, [loading, onLoadMore]);\n\n const skeletonCount = loading ? Math.min(remaining, 10) : 0;\n\n return (\n <div ref={sentinelRef} className=\"space-y-2 pt-2\">\n {Array.from({ length: skeletonCount }).map((_, i) => (\n <SkeletonCard key={i} />\n ))}\n </div>\n );\n}\n\nexport function KanbanColumn({\n column,\n tasks,\n totalCount,\n unreadCount,\n loadingMore,\n onAddTask,\n onTaskClick,\n onTaskShare,\n copiedTaskId,\n onLoadMore,\n}: KanbanColumnProps) {\n return (\n <div className=\"w-[280px] flex flex-col shrink-0 h-full\">\n {/* Column header */}\n <div className=\"mb-3 px-1 shrink-0\">\n <div className=\"flex items-center gap-2\">\n <span className={`w-2 h-2 rounded-full ${column.color}`} />\n <h3 className=\"text-xs font-medium text-neutral-700 uppercase tracking-wide\">{column.label}</h3>\n {unreadCount > 0 && (\n <span className=\"relative group/unread-col w-4 h-4 rounded-full bg-[#FF5E00] text-white text-[9px] font-semibold flex items-center justify-center cursor-default\">\n {unreadCount}\n <span className=\"absolute left-1/2 -translate-x-1/2 top-full mt-1.5 px-2 py-1 text-[10px] font-medium text-white bg-neutral-800 rounded whitespace-nowrap opacity-0 pointer-events-none group-hover/unread-col:opacity-100 transition-opacity duration-75 z-10\">\n {unreadCount} unread {unreadCount === 1 ? \"task\" : \"tasks\"}\n </span>\n </span>\n )}\n <span className=\"text-[10px] text-neutral-400 ml-auto\">{totalCount}</span>\n <button\n onClick={onAddTask}\n className=\"ml-1 p-1 rounded-md text-neutral-400 hover:text-[#FF5E00] hover:bg-[#FF5E00]/10 transition-colors\"\n aria-label={`Add task to ${column.label}`}\n >\n <PlusIcon size={16} />\n </button>\n </div>\n <p className=\"text-[10px] text-neutral-400 mt-0.5 pl-4\">{column.description}</p>\n </div>\n\n {/* Droppable area */}\n <Droppable droppableId={column.key}>\n {(provided, snapshot) => (\n <div\n ref={provided.innerRef}\n {...provided.droppableProps}\n className={`flex-1 rounded-xl p-2 min-h-[120px] overflow-y-auto transition-colors ${\n snapshot.isDraggingOver ? \"bg-[#FF5E00]/5 ring-1 ring-[#FF5E00]/20\" : \"bg-neutral-100/50\"\n }`}\n >\n <div className=\"space-y-2\">\n {tasks.map((task, index) => (\n <TaskCard\n key={task.id}\n task={task}\n index={index}\n onClick={() => onTaskClick(task)}\n onShare={(e) => { e.stopPropagation(); onTaskShare(task.id, e); }}\n copied={copiedTaskId === task.id}\n />\n ))}\n {provided.placeholder}\n </div>\n\n {tasks.length < totalCount && (\n <LoadMoreSentinel\n loading={loadingMore}\n onLoadMore={onLoadMore}\n remaining={totalCount - tasks.length}\n />\n )}\n\n {tasks.length === 0 && (\n <div className=\"flex items-center justify-center h-20 text-xs text-neutral-400\">\n No tasks\n </div>\n )}\n </div>\n )}\n </Droppable>\n </div>\n );\n}\n","import React, { memo } from 'react';\nimport { Draggable } from '@hello-pangea/dnd';\nimport type { Task } from '../types';\nimport { PriorityBadge } from './PriorityBadge';\nimport { TagBadge } from './TagBadge';\nimport { UserAvatar } from './UserAvatar';\nimport { MessageSquareIcon, LinkIcon, CheckIcon } from '../icons';\nimport { formatDate, getDescriptionPreview, hasDescription } from '../utils/helpers';\n\nexport interface TaskCardProps {\n task: Task;\n index: number;\n onClick: () => void;\n onShare: (e: React.MouseEvent) => void;\n copied: boolean;\n}\n\nexport const TaskCard = memo(function TaskCard({ task, index, onClick, onShare, copied }: TaskCardProps) {\n return (\n <Draggable draggableId={task.id} index={index}>\n {(provided, snapshot) => (\n <div\n ref={provided.innerRef}\n {...provided.draggableProps}\n {...provided.dragHandleProps}\n onClick={onClick}\n className={`relative bg-white rounded-lg border p-3.5 cursor-pointer transition-all hover:shadow-md group/card ${\n snapshot.isDragging ? \"shadow-lg ring-2 ring-[#FF5E00]/20\" : \"\"\n } border-neutral-200`}\n >\n {/* Title + priority */}\n <div className=\"flex items-start justify-between gap-2.5\">\n <div className=\"flex items-start gap-1.5 flex-1 min-w-0\">\n {task.has_unread && (\n <span className=\"relative group/unread mt-[5px] w-1.5 h-1.5 rounded-full bg-[#FF5E00] shrink-0 cursor-default\">\n <span className=\"absolute left-1/2 -translate-x-1/2 bottom-full mb-1.5 px-2 py-1 text-[10px] font-medium text-white bg-neutral-800 rounded whitespace-nowrap opacity-0 pointer-events-none group-hover/unread:opacity-100 transition-opacity duration-75\">\n New activity\n </span>\n </span>\n )}\n <h4 className=\"text-[13px] font-medium text-neutral-900 leading-snug line-clamp-2\">\n {task.title}\n </h4>\n </div>\n <PriorityBadge priority={task.priority} />\n </div>\n\n {/* Tags */}\n {task.tags && task.tags.length > 0 && (\n <div className=\"mt-1.5 flex flex-wrap gap-1\">\n {task.tags.slice(0, 3).map((tag) => (\n <TagBadge key={tag} tag={tag} />\n ))}\n {task.tags.length > 3 && (\n <span className=\"text-[8px] text-neutral-400 px-1 py-px\">+{task.tags.length - 3}</span>\n )}\n </div>\n )}\n\n {/* Description preview */}\n {hasDescription(task.description) && (\n <p className=\"mt-2 text-[11px] text-neutral-400 leading-relaxed line-clamp-2\">\n {getDescriptionPreview(task.description)}\n </p>\n )}\n\n {/* Footer */}\n <div className=\"mt-3 flex items-center justify-between pt-2.5 border-t border-neutral-100\">\n <span className=\"text-[10px] text-neutral-400\">{formatDate(task.created_at)}</span>\n <div className=\"flex items-center gap-1.5\">\n <button\n onClick={onShare}\n className=\"opacity-0 group-hover/card:opacity-100 transition-opacity p-0.5 rounded text-neutral-300 hover:text-neutral-500 cursor-pointer\"\n title={copied ? \"Link copied!\" : \"Copy link\"}\n >\n {copied ? <CheckIcon size={12} /> : <LinkIcon size={12} />}\n </button>\n {task.comment_count > 0 && (\n <span className=\"flex items-center gap-0.5 text-[10px] text-neutral-400\">\n <MessageSquareIcon size={12} />\n {task.comment_count}\n </span>\n )}\n {task.created_by_name && (\n <UserAvatar name={task.created_by_name} size=\"xs\" showTooltip />\n )}\n </div>\n </div>\n </div>\n )}\n </Draggable>\n );\n});\n","import type { StructuredDescription, PriorityConfig, TagConfig } from '../types';\nimport { DEFAULT_PRIORITIES, PREDEFINED_TAGS, DESCRIPTION_SECTIONS } from './constants';\n\nexport function getPriorityStyle(priority: string): PriorityConfig {\n return DEFAULT_PRIORITIES.find((p) => p.value === priority) ?? DEFAULT_PRIORITIES[2];\n}\n\nexport function getTagStyle(tag: string): TagConfig {\n const predefined = PREDEFINED_TAGS.find((t) => t.value === tag);\n if (predefined) return predefined;\n const label = tag.charAt(0).toUpperCase() + tag.slice(1).replace(/-/g, \" \");\n return { value: tag, label, className: \"bg-neutral-100 text-neutral-500 border-neutral-200\" };\n}\n\nexport function getInitials(name: string): string {\n return name\n .split(\" \")\n .map((w) => w[0])\n .join(\"\")\n .toUpperCase()\n .slice(0, 2);\n}\n\nexport function parseDate(dateStr: string): Date {\n if (!dateStr) return new Date();\n const d = new Date(dateStr);\n if (isNaN(d.getTime()) && !dateStr.endsWith(\"Z\") && !dateStr.includes(\"+\")) {\n return new Date(dateStr + \"Z\");\n }\n return d;\n}\n\nexport function formatDate(dateStr: string): string {\n if (!dateStr) return \"\";\n const d = parseDate(dateStr);\n return d.toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\" });\n}\n\nexport function formatDateTime(dateStr: string): string {\n if (!dateStr) return \"\";\n const d = parseDate(dateStr);\n return d.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n}\n\nexport function getDescriptionPreview(desc: StructuredDescription | string | undefined): string {\n if (!desc) return \"\";\n if (typeof desc === \"string\") return desc;\n for (const section of DESCRIPTION_SECTIONS) {\n if (desc[section.key]?.trim()) return desc[section.key].trim();\n }\n return \"\";\n}\n\nexport function hasDescription(desc: StructuredDescription | string | undefined): boolean {\n if (!desc) return false;\n if (typeof desc === \"string\") return desc.trim().length > 0;\n return DESCRIPTION_SECTIONS.some((s) => desc[s.key]?.trim());\n}\n\nexport function getUserProjects(\n apps: string[],\n allProjects: { slug: string; name: string }[]\n): { slug: string; name: string }[] {\n if (apps.includes(\"all\")) return allProjects;\n return allProjects.filter((p) => apps.includes(p.slug));\n}\n","import React from 'react';\nimport { getPriorityStyle } from '../utils/helpers';\n\nexport interface PriorityBadgeProps {\n priority: string;\n size?: 'sm' | 'md';\n}\n\nexport function PriorityBadge({ priority, size = 'sm' }: PriorityBadgeProps) {\n const style = getPriorityStyle(priority);\n const sizeClass = size === 'sm'\n ? 'px-1.5 py-0.5 text-[9px]'\n : 'px-2.5 py-1 text-[10px]';\n\n return (\n <span className={`inline-flex items-center font-semibold uppercase tracking-wide rounded border ${style.className} ${sizeClass}`}>\n {style.label}\n </span>\n );\n}\n","import React from 'react';\n\ninterface IconProps {\n className?: string;\n size?: number;\n strokeWidth?: number;\n}\n\nexport const PlusIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" /><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n);\n\nexport const XIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" /><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\nexport const ChevronDownIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n);\n\nexport const MessageSquareIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n);\n\nexport const KanbanIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\" /><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\" /><path d=\"m9 14 2 2 4-4\" />\n </svg>\n);\n\nexport const LinkIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" /><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </svg>\n);\n\nexport const CheckIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\n\nexport const BellIcon: React.FC<IconProps> = ({ className = \"\", size = 24 }) => (\n <svg className={className} width={size} height={size} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.75}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0\" />\n </svg>\n);\n\nexport const FilterIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\" />\n </svg>\n);\n\nexport const PencilIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" />\n </svg>\n);\n\nexport const TrashIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M3 6h18\" /><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" /><path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n </svg>\n);\n\nexport const LockIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" /><path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n);\n\nexport const FeedbackIcon: React.FC<IconProps> = ({ className = \"\", size = 24, strokeWidth = 2 }) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" /><path d=\"M8 12h.01\" /><path d=\"M12 12h.01\" /><path d=\"M16 12h.01\" />\n </svg>\n);\n","import React from 'react';\nimport { getTagStyle } from '../utils/helpers';\nimport { XIcon } from '../icons';\n\nexport interface TagBadgeProps {\n tag: string;\n onRemove?: () => void;\n size?: 'sm' | 'md';\n}\n\nexport function TagBadge({ tag, onRemove, size = 'sm' }: TagBadgeProps) {\n const style = getTagStyle(tag);\n const sizeClass = size === 'sm'\n ? 'px-1.5 py-px text-[8px]'\n : 'px-2 py-0.5 text-[10px]';\n\n return (\n <span className={`inline-flex items-center gap-1 font-medium rounded border ${style.className} ${sizeClass}`}>\n {style.label}\n {onRemove && (\n <button onClick={onRemove} className=\"opacity-50 hover:opacity-100 transition-opacity\">\n <XIcon size={size === 'sm' ? 10 : 12} />\n </button>\n )}\n </span>\n );\n}\n","import React from 'react';\nimport { getInitials } from '../utils/helpers';\n\nexport interface UserAvatarProps {\n name: string;\n size?: 'xs' | 'sm' | 'md';\n showTooltip?: boolean;\n className?: string;\n}\n\nconst SIZES = {\n xs: { container: 'w-5 h-5', text: 'text-[8px]' },\n sm: { container: 'w-6 h-6', text: 'text-[9px]' },\n md: { container: 'w-7 h-7', text: 'text-[10px]' },\n};\n\nexport function UserAvatar({ name, size = 'xs', showTooltip = false, className = '' }: UserAvatarProps) {\n const s = SIZES[size];\n const initials = getInitials(name || '?');\n\n return (\n <div className={`relative ${showTooltip ? 'group/avatar' : ''} ${className}`}>\n <div className={`${s.container} rounded-full bg-[#FF5E00] flex items-center justify-center`}>\n <span className={`${s.text} font-medium text-white leading-none`}>{initials}</span>\n </div>\n {showTooltip && (\n <div className=\"absolute bottom-full right-0 mb-1.5 px-2 py-1 text-[10px] font-medium text-white bg-neutral-800 rounded whitespace-nowrap opacity-0 pointer-events-none group-hover/avatar:opacity-100 transition-opacity duration-75\">\n {name}\n </div>\n )}\n </div>\n );\n}\n","import React, { useState, useRef, useEffect } from 'react';\nimport type { Project, TagConfig } from '../types';\nimport { FilterIcon, XIcon, CheckIcon, ChevronDownIcon } from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\nexport interface FilterBarProps {\n projects: Project[];\n selectedProject: string;\n onSelectProject: (slug: string) => void;\n filterTags: string[];\n onSetFilterTags: (tags: string[]) => void;\n}\n\nexport function FilterBar({\n projects,\n selectedProject,\n onSelectProject,\n filterTags,\n onSetFilterTags,\n}: FilterBarProps) {\n const { tags: predefinedTags, features } = useTaskBoardContext();\n const [filterExpanded, setFilterExpanded] = useState(false);\n const filterDropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!filterExpanded) return;\n function handleClick(e: MouseEvent) {\n if (filterDropdownRef.current && !filterDropdownRef.current.contains(e.target as Node)) {\n setFilterExpanded(false);\n }\n }\n document.addEventListener(\"mousedown\", handleClick);\n return () => document.removeEventListener(\"mousedown\", handleClick);\n }, [filterExpanded]);\n\n const toggleTag = (value: string) => {\n onSetFilterTags(\n filterTags.includes(value)\n ? filterTags.filter((t) => t !== value)\n : [...filterTags, value]\n );\n };\n\n return (\n <div className=\"mb-4 shrink-0 flex items-start justify-between gap-3\">\n {/* Project pills */}\n {projects.length > 1 && (\n <div className=\"flex gap-2 flex-nowrap overflow-x-auto eb-tb-no-scrollbar sm:flex-wrap sm:overflow-visible\">\n {projects.map((project) => (\n <button\n key={project.slug}\n onClick={() => onSelectProject(project.slug)}\n className={`shrink-0 px-4 py-2 text-xs font-medium rounded-lg border transition-colors whitespace-nowrap ${\n selectedProject === project.slug\n ? \"bg-[#FF5E00] text-white border-[#FF5E00]\"\n : \"bg-white text-neutral-600 border-neutral-200 hover:border-neutral-300 hover:text-neutral-900\"\n }`}\n >\n {project.name}\n </button>\n ))}\n </div>\n )}\n {projects.length === 1 && (\n <span className=\"text-sm font-medium text-neutral-600\">{projects[0].name}</span>\n )}\n\n {/* Divider */}\n {features.filters && <div className=\"self-stretch w-px bg-neutral-200 shrink-0\" />}\n\n {/* Filter button + dropdown */}\n {features.filters && (\n <div className=\"relative shrink-0\" ref={filterDropdownRef}>\n <button\n onClick={() => setFilterExpanded(!filterExpanded)}\n className={`flex items-center gap-1.5 px-3 py-2 text-xs font-medium rounded-lg border transition-colors ${\n filterTags.length > 0\n ? \"bg-[#FF5E00]/5 border-[#FF5E00]/30 text-[#FF5E00]\"\n : \"bg-white text-neutral-500 border-neutral-200 hover:border-neutral-300 hover:text-neutral-700\"\n }`}\n >\n <FilterIcon size={14} />\n Filter\n {filterTags.length > 0 && (\n <span className=\"min-w-[16px] h-4 flex items-center justify-center rounded-full bg-[#FF5E00] text-white text-[9px] font-bold px-1\">\n {filterTags.length}\n </span>\n )}\n </button>\n\n {filterExpanded && (\n <div className=\"absolute right-0 top-full mt-1.5 w-64 bg-white border border-neutral-200 rounded-lg shadow-lg z-20 animate-in fade-in zoom-in-95 duration-75\">\n <div className=\"px-3 py-2.5 border-b border-neutral-100 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-neutral-700\">Filter by Tags</span>\n {filterTags.length > 0 && (\n <button\n onClick={() => onSetFilterTags([])}\n className=\"text-[10px] font-medium text-[#FF5E00] hover:text-[#E05200] transition-colors\"\n >\n Clear all\n </button>\n )}\n </div>\n <div className=\"py-1\">\n {predefinedTags.map((tag) => {\n const isActive = filterTags.includes(tag.value);\n return (\n <button\n key={tag.value}\n onClick={() => toggleTag(tag.value)}\n className={`w-full flex items-center justify-between px-3 py-2 text-xs hover:bg-neutral-50 transition-colors ${\n isActive ? \"bg-neutral-50\" : \"\"\n }`}\n >\n <span className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${tag.className}`}>\n {tag.label}\n </span>\n {isActive && <CheckIcon size={13} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n );\n })}\n {/* Other — matches custom tags */}\n <button\n onClick={() => toggleTag(\"__other__\")}\n className={`w-full flex items-center justify-between px-3 py-2 text-xs hover:bg-neutral-50 transition-colors border-t border-neutral-100 ${\n filterTags.includes(\"__other__\") ? \"bg-neutral-50\" : \"\"\n }`}\n >\n <span className=\"inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border bg-neutral-100 text-neutral-500 border-neutral-200\">\n Other\n </span>\n {filterTags.includes(\"__other__\") && <CheckIcon size={13} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport type { Notification } from '../types';\nimport { BellIcon } from '../icons';\nimport { UserAvatar } from './UserAvatar';\nimport { SkeletonPulse } from './SkeletonPulse';\nimport { formatDateTime, getInitials } from '../utils/helpers';\nimport { NOTIFICATION_POLL_INTERVAL } from '../utils/constants';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\nexport interface NotificationBellProps {\n onOpenTask: (taskId: string, projectSlug: string) => void;\n}\n\nexport function NotificationBell({ onOpenTask }: NotificationBellProps) {\n const { service, config } = useTaskBoardContext();\n const [open, setOpen] = useState(false);\n const [notifications, setNotifications] = useState<Notification[]>([]);\n const [unreadCount, setUnreadCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const pollRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const fetchCount = useCallback(async () => {\n try {\n const count = await service.getNotificationCount();\n setUnreadCount(count);\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n }, [service, config]);\n\n useEffect(() => {\n fetchCount();\n pollRef.current = setInterval(fetchCount, NOTIFICATION_POLL_INTERVAL);\n return () => { if (pollRef.current) clearInterval(pollRef.current); };\n }, [fetchCount]);\n\n const fetchNotifications = async () => {\n setLoading(true);\n try {\n const data = await service.listNotifications();\n setNotifications(data);\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n } finally { setLoading(false); }\n };\n\n const toggleOpen = () => {\n if (!open) fetchNotifications();\n setOpen(!open);\n };\n\n useEffect(() => {\n if (!open) return;\n function handleClick(e: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) setOpen(false);\n }\n document.addEventListener(\"mousedown\", handleClick);\n return () => document.removeEventListener(\"mousedown\", handleClick);\n }, [open]);\n\n const markAsRead = async (id: string) => {\n try {\n await service.markNotificationRead(id);\n setNotifications((prev) => prev.map((n) => (n.id === id ? { ...n, read: true } : n)));\n setUnreadCount((c) => Math.max(0, c - 1));\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n const markAllRead = async () => {\n try {\n await service.markAllNotificationsRead();\n setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));\n setUnreadCount(0);\n } catch (err) {\n config.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n const handleClick = (n: Notification) => {\n if (!n.read) markAsRead(n.id);\n setOpen(false);\n onOpenTask(n.task_id, n.project_slug);\n };\n\n return (\n <div ref={dropdownRef} className=\"relative\">\n <button\n onClick={toggleOpen}\n className=\"relative flex items-center justify-center w-9 h-9 rounded-lg border border-neutral-200 hover:border-neutral-300 hover:bg-neutral-50 transition-colors\"\n title=\"Notifications\"\n >\n <BellIcon size={16} className=\"text-neutral-600\" />\n {unreadCount > 0 && (\n <span className=\"absolute -top-1 -right-1 min-w-[16px] h-4 px-1 flex items-center justify-center rounded-full bg-[#FF5E00] text-white text-[9px] font-bold\">\n {unreadCount > 99 ? \"99+\" : unreadCount}\n </span>\n )}\n </button>\n\n {open && (\n <div className=\"absolute right-0 mt-2 w-[360px] bg-white rounded-xl shadow-xl border border-neutral-200 z-50 overflow-hidden\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-neutral-100\">\n <h3 className=\"text-sm font-medium text-neutral-900\">Notifications</h3>\n {unreadCount > 0 && (\n <button onClick={markAllRead} className=\"text-[11px] font-medium text-[#FF5E00] hover:text-[#E05200] transition-colors\">\n Mark all as read\n </button>\n )}\n </div>\n <div className=\"max-h-[400px] overflow-y-auto\">\n {loading ? (\n <div className=\"px-4 py-6 space-y-3\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex gap-3 animate-pulse\">\n <div className=\"w-8 h-8 rounded-full bg-neutral-200 shrink-0\" />\n <div className=\"flex-1 space-y-1.5\">\n <SkeletonPulse className=\"h-3 w-3/4\" />\n <SkeletonPulse className=\"h-2.5 w-full\" />\n <SkeletonPulse className=\"h-2 w-16\" />\n </div>\n </div>\n ))}\n </div>\n ) : notifications.length === 0 ? (\n <div className=\"px-4 py-10 text-center\">\n <BellIcon size={32} className=\"text-neutral-300 mx-auto mb-2\" />\n <p className=\"text-xs text-neutral-400\">No notifications yet</p>\n </div>\n ) : (\n notifications.map((n) => (\n <button\n key={n.id}\n onClick={() => handleClick(n)}\n className={`w-full flex items-start gap-3 px-4 py-3 text-left hover:bg-neutral-50 transition-colors border-b border-neutral-50 last:border-b-0 ${\n !n.read ? \"bg-[#FF5E00]/[0.03]\" : \"\"\n }`}\n >\n <div className=\"w-8 h-8 rounded-full bg-[#FF5E00] text-white text-[10px] font-semibold flex items-center justify-center shrink-0 mt-0.5\">\n {getInitials(n.actor_name)}\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-xs text-neutral-700 leading-relaxed\">\n <span className=\"font-semibold text-neutral-900\">{n.actor_name}</span>\n {\" mentioned you in \"}\n {n.context === \"description\" ? \"the description of \" : \"a comment on \"}\n <span className=\"font-medium text-neutral-800\">{n.task_title}</span>\n </p>\n {n.snippet && <p className=\"text-[11px] text-neutral-400 mt-0.5 truncate\">{n.snippet}</p>}\n <p className=\"text-[10px] text-neutral-400 mt-1\">{formatDateTime(n.created_at)}</p>\n </div>\n {!n.read && <span className=\"w-2 h-2 rounded-full bg-[#FF5E00] shrink-0 mt-2\" />}\n </button>\n ))\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport type { StructuredDescription, TasksByStatus } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { EMPTY_DESCRIPTION, DESCRIPTION_SECTIONS } from '../utils/constants';\nimport { getPriorityStyle } from '../utils/helpers';\nimport { XIcon, ChevronDownIcon, CheckIcon } from '../icons';\n\nexport interface CreateTaskModalProps {\n projectSlug: string;\n defaultStatus?: string;\n onClose: () => void;\n onCreate: () => void;\n}\n\nexport function CreateTaskModal({\n projectSlug,\n defaultStatus = 'backlog',\n onClose,\n onCreate,\n}: CreateTaskModalProps) {\n const { columns, priorities, tags: predefinedTags, service, config } = useTaskBoardContext();\n\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState<StructuredDescription>({ ...EMPTY_DESCRIPTION });\n const [priority, setPriority] = useState('medium');\n const [taskStatus, setTaskStatus] = useState(defaultStatus);\n const [selectedTags, setSelectedTags] = useState<string[]>([]);\n const [customTag, setCustomTag] = useState('');\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [showColumnDropdown, setShowColumnDropdown] = useState(false);\n const [showPriorityDropdown, setShowPriorityDropdown] = useState(false);\n\n const toggleTag = (tag: string) => {\n setSelectedTags((prev) =>\n prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]\n );\n };\n\n const addCustomTag = () => {\n const tag = customTag.trim().toLowerCase().replace(/\\s+/g, '-');\n if (tag && !selectedTags.includes(tag)) {\n setSelectedTags((prev) => [...prev, tag]);\n }\n setCustomTag('');\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!title.trim()) return;\n\n setLoading(true);\n setError('');\n try {\n const task = await service.createTask({\n project_slug: projectSlug,\n title: title.trim(),\n description,\n priority,\n status: taskStatus,\n tags: selectedTags,\n });\n config.onTaskCreate?.(task);\n onCreate();\n onClose();\n } catch (err: unknown) {\n const apiErr = err as { response?: { data?: { detail?: string } }; message?: string };\n setError(apiErr?.response?.data?.detail || apiErr?.message || 'Failed to create task');\n } finally {\n setLoading(false);\n }\n };\n\n const priorityStyle = getPriorityStyle(priority);\n const statusCol = columns.find((c) => c.key === taskStatus);\n\n return (\n <div\n className=\"fixed inset-0 z-[100] flex items-center justify-center bg-black/30 backdrop-blur-sm eb-tb-animate-fade-in\"\n onClick={(e) => e.target === e.currentTarget && onClose()}\n >\n <div className=\"bg-white rounded-2xl shadow-2xl border border-neutral-200 w-[80vw] max-w-[1100px] h-[85vh] flex flex-col eb-tb-animate-zoom-in\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-neutral-100 shrink-0\">\n <h2 className=\"text-lg font-semibold text-neutral-900\">New Task</h2>\n <button\n onClick={onClose}\n className=\"p-1 rounded-md text-neutral-400 hover:text-neutral-600 hover:bg-neutral-100 transition-colors\"\n >\n <XIcon size={20} />\n </button>\n </div>\n\n {/* Body */}\n <form onSubmit={handleSubmit} className=\"flex-1 flex flex-col min-h-0\">\n {error && (\n <div className=\"mx-6 mt-4 p-3 bg-red-50 border border-red-200 rounded-lg text-red-600 text-sm\">\n {error}\n </div>\n )}\n\n <div className=\"flex-1 flex min-h-0 overflow-hidden\">\n {/* Left: Content */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5 border-r border-neutral-100\">\n <div className=\"max-w-2xl\">\n {/* Title */}\n <div className=\"pb-4\">\n <label className=\"text-xs font-medium text-neutral-700 mb-1.5 block\">Title</label>\n <input\n type=\"text\"\n required\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n className=\"w-full px-3 py-2.5 border border-neutral-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50\"\n placeholder=\"What needs to be done?\"\n autoFocus\n />\n </div>\n\n <div className=\"border-t border-neutral-100 pt-4 pb-1\">\n <span className=\"text-[10px] font-semibold text-neutral-400 uppercase tracking-wider\">Description</span>\n </div>\n\n {/* Description Sections */}\n {DESCRIPTION_SECTIONS.map((section, idx) => (\n <div key={section.key} className={`py-3 ${idx < DESCRIPTION_SECTIONS.length - 1 ? 'border-b border-dashed border-neutral-100' : ''}`}>\n <label className=\"text-xs font-medium text-neutral-700 mb-1.5 block\">\n {section.label} <span className=\"text-neutral-400 font-normal\">(optional)</span>\n </label>\n <textarea\n value={description[section.key]}\n onChange={(e) =>\n setDescription((prev) => ({ ...prev, [section.key]: e.target.value }))\n }\n rows={3}\n className=\"w-full px-3 py-2.5 border border-neutral-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 resize-y\"\n placeholder={`Add ${section.label.toLowerCase()}...`}\n />\n </div>\n ))}\n </div>\n </div>\n\n {/* Right: Settings */}\n <div className=\"w-[340px] shrink-0 overflow-y-auto px-5 py-5 bg-neutral-50/30\">\n {/* Column + Priority side by side */}\n <div className=\"grid grid-cols-2 gap-4 mb-5\">\n {/* Column */}\n <div>\n <label className=\"text-[11px] font-semibold text-neutral-500 uppercase tracking-wide mb-2 block\">Column</label>\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowColumnDropdown(!showColumnDropdown)}\n className=\"w-full flex items-center justify-between gap-2 px-3 py-2 text-xs font-medium rounded-lg border border-neutral-200 bg-white hover:border-neutral-300 transition-colors\"\n >\n <div className=\"flex items-center gap-2\">\n <span className={`w-2 h-2 rounded-full ${statusCol?.color ?? 'bg-neutral-400'}`} />\n {statusCol?.label ?? taskStatus}\n </div>\n <ChevronDownIcon size={12} className=\"text-neutral-400\" />\n </button>\n {showColumnDropdown && (\n <div className=\"absolute top-full mt-1 left-0 right-0 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 py-1 eb-tb-animate-zoom-in\">\n {columns.map((col) => (\n <button\n key={col.key}\n type=\"button\"\n onClick={() => { setTaskStatus(col.key); setShowColumnDropdown(false); }}\n className={`w-full flex items-center gap-2 px-3 py-1.5 text-xs hover:bg-neutral-50 text-left ${\n taskStatus === col.key ? 'font-medium bg-neutral-50' : ''\n }`}\n >\n <span className={`w-2 h-2 rounded-full ${col.color}`} />\n {col.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Priority */}\n <div>\n <label className=\"text-[11px] font-semibold text-neutral-500 uppercase tracking-wide mb-2 block\">Priority</label>\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowPriorityDropdown(!showPriorityDropdown)}\n className={`w-full flex items-center justify-between gap-2 px-3 py-2 text-xs font-medium rounded-lg border transition-colors ${priorityStyle.className}`}\n >\n {priorityStyle.label}\n <ChevronDownIcon size={12} className=\"opacity-50\" />\n </button>\n {showPriorityDropdown && (\n <div className=\"absolute top-full mt-1 left-0 right-0 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 py-1 eb-tb-animate-zoom-in\">\n {priorities.map((p) => (\n <button\n key={p.value}\n type=\"button\"\n onClick={() => { setPriority(p.value); setShowPriorityDropdown(false); }}\n className={`w-full flex items-center gap-2 px-3 py-1.5 text-xs hover:bg-neutral-50 text-left ${\n priority === p.value ? 'bg-neutral-50' : ''\n }`}\n >\n <span className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${p.className}`}>\n {p.label}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Tags */}\n <div>\n <label className=\"text-[11px] font-semibold text-neutral-500 uppercase tracking-wide mb-2 block\">Tags</label>\n <div className=\"space-y-1\">\n {predefinedTags.map((tag) => {\n const isSelected = selectedTags.includes(tag.value);\n return (\n <button\n key={tag.value}\n type=\"button\"\n onClick={() => toggleTag(tag.value)}\n className={`w-full flex items-center justify-between px-3 py-2 text-xs rounded-lg border transition-colors text-left ${\n isSelected\n ? 'bg-[#FF5E00]/5 border-[#FF5E00]/30 text-neutral-800'\n : 'bg-white text-neutral-600 border-neutral-200 hover:border-neutral-300'\n }`}\n >\n <span className={`inline-flex items-center px-1.5 py-px text-[10px] font-medium rounded border ${tag.className}`}>\n {tag.label}\n </span>\n {isSelected && <CheckIcon size={13} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n );\n })}\n </div>\n {/* Custom tag input */}\n <div className=\"mt-2.5 flex gap-1.5\">\n <input\n type=\"text\"\n value={customTag}\n onChange={(e) => setCustomTag(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addCustomTag(); } }}\n className=\"flex-1 px-2.5 py-1.5 border border-neutral-200 rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 bg-white\"\n placeholder=\"Custom tag...\"\n />\n <button\n type=\"button\"\n onClick={addCustomTag}\n disabled={!customTag.trim()}\n className=\"px-2.5 py-1.5 text-xs font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors disabled:opacity-40\"\n >\n Add\n </button>\n </div>\n {selectedTags.filter((t) => !predefinedTags.some((p) => p.value === t)).length > 0 && (\n <div className=\"flex gap-1.5 flex-wrap mt-2\">\n {selectedTags\n .filter((t) => !predefinedTags.some((p) => p.value === t))\n .map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-[10px] font-medium bg-neutral-100 text-neutral-500 border border-neutral-200 rounded\"\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => setSelectedTags((prev) => prev.filter((t) => t !== tag))}\n className=\"text-neutral-400 hover:text-neutral-600\"\n >\n <XIcon size={12} />\n </button>\n </span>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-end gap-3 px-6 py-4 border-t border-neutral-100 shrink-0 bg-white\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm text-neutral-600 hover:text-neutral-900 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={loading}\n className=\"px-6 py-2 text-sm font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors disabled:opacity-60\"\n >\n {loading ? 'Creating...' : 'Create Task'}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport type { Task, Comment, ActivityEntry, StructuredDescription } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { useTaskDetail } from '../hooks/useTaskDetail';\nimport { EMPTY_DESCRIPTION, DESCRIPTION_SECTIONS } from '../utils/constants';\nimport { getPriorityStyle, formatDateTime, getInitials, getTagStyle, hasDescription } from '../utils/helpers';\nimport { useShareLink } from '../hooks/useShareLink';\nimport { MentionText } from './MentionText';\nimport { MentionTextarea } from './MentionTextarea';\nimport { SkeletonPulse } from './SkeletonPulse';\nimport { TagBadge } from './TagBadge';\nimport {\n XIcon, ChevronDownIcon, CheckIcon, PlusIcon,\n PencilIcon, TrashIcon, LinkIcon, LockIcon, MessageSquareIcon,\n} from '../icons';\n\nexport interface TaskDetailPanelProps {\n task: Task;\n projectSlug: string;\n onClose: () => void;\n onUpdate: () => void;\n}\n\nexport function TaskDetailPanel({ task, projectSlug, onClose, onUpdate }: TaskDetailPanelProps) {\n const { columns, priorities, tags: predefinedTags, service, config, user, features } = useTaskBoardContext();\n const detail = useTaskDetail(task.id);\n const { copiedTaskId, copyShareLink } = useShareLink();\n\n const [title, setTitle] = useState(task.title);\n const [description, setDescription] = useState<StructuredDescription>(task.description || EMPTY_DESCRIPTION);\n const [priority, setPriority] = useState(task.priority);\n const [taskStatus, setTaskStatus] = useState(task.status);\n const [localTags, setLocalTags] = useState<string[]>(task.tags || []);\n const [pendingTags, setPendingTags] = useState<string[]>([]);\n\n const [saving, setSaving] = useState(false);\n const [editing, setEditing] = useState(false);\n const [newComment, setNewComment] = useState('');\n const [isInternalComment, setIsInternalComment] = useState(false);\n\n const [showPriorityDropdown, setShowPriorityDropdown] = useState(false);\n const [showStatusDropdown, setShowStatusDropdown] = useState(false);\n const [showTagDropdown, setShowTagDropdown] = useState(false);\n const [showOtherTagInput, setShowOtherTagInput] = useState(false);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [showDiscardConfirm, setShowDiscardConfirm] = useState(false);\n const [commentToDelete, setCommentToDelete] = useState<string | null>(null);\n const [editingCommentId, setEditingCommentId] = useState<string | null>(null);\n const [editingCommentContent, setEditingCommentContent] = useState('');\n\n const commentsEndRef = useRef<HTMLDivElement>(null);\n const hasUnsavedChanges = editing && (title !== task.title || JSON.stringify(description) !== JSON.stringify(task.description));\n\n useEffect(() => {\n if (commentsEndRef.current) {\n commentsEndRef.current.scrollIntoView({ behavior: 'smooth' });\n }\n }, [detail.comments]);\n\n const saveField = async (field: string, value: unknown) => {\n setSaving(true);\n try {\n await detail.saveField(field, value);\n onUpdate();\n } finally {\n setSaving(false);\n }\n };\n\n const handleSaveEdit = async () => {\n setSaving(true);\n try {\n const updates: Record<string, unknown> = {};\n if (title.trim() && title !== task.title) updates.title = title.trim();\n if (JSON.stringify(description) !== JSON.stringify(task.description)) updates.description = description;\n if (Object.keys(updates).length > 0) {\n await service.updateTask(task.id, updates as Parameters<typeof service.updateTask>[1]);\n onUpdate();\n }\n } finally {\n setSaving(false);\n setEditing(false);\n }\n };\n\n const handleCancelEdit = () => {\n if (hasUnsavedChanges) {\n setShowDiscardConfirm(true);\n } else {\n setEditing(false);\n }\n };\n\n const handleDiscardChanges = () => {\n setTitle(task.title);\n setDescription(task.description || EMPTY_DESCRIPTION);\n setEditing(false);\n setShowDiscardConfirm(false);\n };\n\n const handleClosePanel = () => {\n if (hasUnsavedChanges) {\n setShowDiscardConfirm(true);\n } else {\n onClose();\n }\n };\n\n const handleDelete = async () => {\n setSaving(true);\n try {\n await service.deleteTask(task.id);\n config.onTaskDelete?.(task.id);\n onUpdate();\n onClose();\n } finally {\n setSaving(false);\n }\n };\n\n const handlePriorityChange = (p: string) => {\n setPriority(p);\n setShowPriorityDropdown(false);\n saveField('priority', p);\n };\n\n const handleStatusChange = (s: string) => {\n setTaskStatus(s);\n setShowStatusDropdown(false);\n saveField('status', s);\n };\n\n const handleAddComment = async () => {\n if (!newComment.trim()) return;\n await detail.addComment(newComment.trim(), isInternalComment);\n setNewComment('');\n setIsInternalComment(false);\n onUpdate();\n };\n\n const handleCommentKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleAddComment();\n }\n };\n\n const handleDeleteComment = async () => {\n if (!commentToDelete) return;\n try {\n await detail.deleteComment(commentToDelete);\n setCommentToDelete(null);\n onUpdate();\n } catch (err: unknown) {\n setCommentToDelete(null);\n }\n };\n\n const startEditingComment = (c: Comment) => {\n setEditingCommentId(c.id);\n setEditingCommentContent(c.content);\n };\n\n const cancelEditingComment = () => {\n setEditingCommentId(null);\n setEditingCommentContent('');\n };\n\n const saveEditedComment = async () => {\n if (!editingCommentId || !editingCommentContent.trim()) return;\n try {\n await detail.editComment(editingCommentId, editingCommentContent.trim());\n setEditingCommentId(null);\n setEditingCommentContent('');\n } catch {\n // error surfaced by hook\n }\n };\n\n const statusCol = columns.find((c) => c.key === taskStatus);\n const priorityStyle = getPriorityStyle(priority);\n const initials = getInitials(task.created_by_name || '?');\n const linkCopied = copiedTaskId === task.id;\n\n const handleShareFromDetail = () => {\n copyShareLink(task.id, projectSlug);\n };\n\n // Merge comments and activity into timeline\n const timeline = [\n ...detail.comments.map((c) => ({ kind: 'comment' as const, date: c.created_at, data: c })),\n ...detail.activity.map((a) => ({ kind: 'activity' as const, date: a.created_at, data: a })),\n ].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());\n\n return (\n <div\n className=\"fixed inset-0 z-[100] flex items-end justify-end bg-black/30 backdrop-blur-md eb-tb-animate-fade-in\"\n onClick={(e) => e.target === e.currentTarget && handleClosePanel()}\n >\n <div\n className=\"bg-white shadow-2xl border-l border-neutral-200 w-full lg:w-[75vw] h-full flex flex-col\"\n style={{ animation: 'eb-tb-slide-in-right 0.15s ease-out' }}\n >\n {/* Top bar */}\n <div className=\"flex items-center gap-2 sm:gap-4 px-4 sm:px-8 py-3 sm:py-4 border-b border-neutral-100 shrink-0\">\n <h2 className=\"flex-1 text-base sm:text-lg font-semibold text-neutral-900 truncate min-w-0\">\n {title}\n </h2>\n <div className=\"flex items-center gap-2 shrink-0\">\n {saving && <span className=\"text-[11px] text-neutral-400 mr-1\">Saving...</span>}\n {editing ? (\n <>\n <button onClick={handleCancelEdit} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 rounded-lg hover:bg-neutral-100 transition-colors\">\n <XIcon size={13} /> Cancel\n </button>\n <button onClick={handleSaveEdit} disabled={saving} className=\"flex items-center gap-1.5 px-4 py-1.5 text-xs font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors disabled:opacity-60\">\n <CheckIcon size={13} /> {saving ? 'Saving...' : 'Save'}\n </button>\n </>\n ) : (\n <>\n {features.sharing && (\n <button onClick={handleShareFromDetail} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 rounded-lg border border-neutral-200 hover:border-neutral-300 transition-colors\">\n {linkCopied ? <><CheckIcon size={13} /> Copied!</> : <><LinkIcon size={13} /> Share</>}\n </button>\n )}\n <button onClick={() => setEditing(true)} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 rounded-lg border border-neutral-200 hover:border-neutral-300 transition-colors\">\n <PencilIcon size={13} /> Edit\n </button>\n <button onClick={() => setShowDeleteConfirm(true)} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-neutral-600 hover:text-neutral-900 rounded-lg border border-neutral-200 hover:border-neutral-300 transition-colors\">\n <TrashIcon size={13} /> Delete\n </button>\n </>\n )}\n <button onClick={handleClosePanel} className=\"p-1.5 rounded-md text-neutral-400 hover:text-neutral-600 hover:bg-neutral-100 transition-colors ml-1\">\n <XIcon size={16} />\n </button>\n </div>\n </div>\n\n {/* Two-column body */}\n <div className=\"flex-1 flex flex-col md:flex-row min-h-0\">\n {/* Left: Task content */}\n <div className=\"flex-1 overflow-y-auto min-w-0\">\n <div className=\"max-w-2xl px-4 sm:px-8 lg:px-10 py-6 sm:py-8\">\n {/* Title edit */}\n {editing && (\n <div className=\"mb-6\">\n <label className=\"text-[11px] font-medium text-neutral-400 uppercase tracking-wide mb-2 block\">Title</label>\n <input\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n className=\"w-full text-lg font-semibold text-neutral-900 bg-white border border-neutral-200 rounded-lg px-3 py-2 outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 leading-tight\"\n placeholder=\"Task title\"\n autoFocus\n />\n </div>\n )}\n\n {/* Properties grid */}\n <div className={`${editing ? 'mt-0' : 'mt-2'} rounded-lg border border-neutral-100 grid grid-cols-1 sm:grid-cols-2`}>\n {/* Task ID | Creator */}\n <div className=\"flex items-center h-10 px-4 border-b sm:border-r border-neutral-100\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Task ID</span>\n <span className=\"text-[11px] font-mono text-neutral-400 bg-neutral-100 px-1.5 py-0.5 rounded\">\n T-{task.id.slice(-6).toUpperCase()}\n </span>\n </div>\n <div className=\"flex items-center h-10 px-4 border-b border-neutral-100\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Creator</span>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-5 h-5 rounded-full bg-[#FF5E00] flex items-center justify-center\">\n <span className=\"text-[8px] font-medium text-white leading-none\">{initials}</span>\n </div>\n <span className=\"text-xs text-neutral-700\">{task.created_by_name || task.created_by}</span>\n </div>\n </div>\n\n {/* Created | Updated */}\n <div className=\"flex items-center h-10 px-4 border-b sm:border-r border-neutral-100\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Created</span>\n <span className=\"text-xs text-neutral-600\">{formatDateTime(task.created_at)}</span>\n </div>\n <div className=\"flex items-center h-10 px-4 border-b border-neutral-100\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Updated</span>\n <span className=\"text-xs text-neutral-600\">{task.updated_at ? formatDateTime(task.updated_at) : '—'}</span>\n </div>\n\n {/* Status | Priority */}\n <div className=\"flex items-center h-10 px-4 border-b sm:border-r border-neutral-100 hover:bg-neutral-50/50 transition-colors\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Status</span>\n <div className=\"relative\">\n <button\n onClick={() => { setShowStatusDropdown(!showStatusDropdown); setShowPriorityDropdown(false); setShowTagDropdown(false); }}\n className=\"flex items-center gap-1.5 px-2 py-0.5 text-xs font-medium rounded-md hover:bg-neutral-100 transition-colors\"\n >\n <span className={`w-2 h-2 rounded-full ${statusCol?.color ?? 'bg-neutral-400'}`} />\n {statusCol?.label ?? taskStatus}\n <ChevronDownIcon size={12} className=\"text-neutral-400\" />\n </button>\n {showStatusDropdown && (\n <div className=\"absolute top-full mt-1 left-0 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 py-1 w-52 eb-tb-animate-zoom-in\">\n {columns.map((col) => (\n <button key={col.key} onClick={() => handleStatusChange(col.key)} className={`w-full text-left px-3 py-1.5 text-xs hover:bg-neutral-50 flex items-center gap-2 ${taskStatus === col.key ? 'font-medium bg-neutral-50' : ''}`}>\n <span className={`w-2 h-2 rounded-full ${col.color}`} /> {col.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n <div className=\"flex items-center h-10 px-4 border-b border-neutral-100 hover:bg-neutral-50/50 transition-colors\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Priority</span>\n <div className=\"relative\">\n <button\n onClick={() => { setShowPriorityDropdown(!showPriorityDropdown); setShowStatusDropdown(false); setShowTagDropdown(false); }}\n className={`flex items-center gap-1.5 px-2 py-0.5 text-xs font-medium rounded-md transition-colors border ${priorityStyle.className}`}\n >\n {priorityStyle.label}\n <ChevronDownIcon size={12} className=\"opacity-50\" />\n </button>\n {showPriorityDropdown && (\n <div className=\"absolute top-full mt-1 left-0 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 py-1 w-40 eb-tb-animate-zoom-in\">\n {priorities.map((p) => (\n <button key={p.value} onClick={() => handlePriorityChange(p.value)} className={`w-full text-left px-3 py-2 text-xs hover:bg-neutral-50 flex items-center gap-2 ${priority === p.value ? 'bg-neutral-50' : ''}`}>\n <span className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${p.className}`}>{p.label}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Tags — full width */}\n {features.tags && (\n <div className=\"flex items-center min-h-[40px] px-4 border-b border-neutral-100 sm:col-span-2 hover:bg-neutral-50/50 transition-colors\">\n <span className=\"w-14 text-[11px] text-neutral-400 font-medium shrink-0\">Tags</span>\n <div className=\"relative flex-1 flex items-center gap-1.5 flex-wrap py-1.5\">\n {localTags.map((tag) => (\n <TagBadge key={tag} tag={tag} size=\"sm\" onRemove={() => {\n const newTags = localTags.filter((t) => t !== tag);\n setLocalTags(newTags);\n saveField('tags', newTags);\n }} />\n ))}\n <button\n onClick={() => {\n if (!showTagDropdown) setPendingTags([...localTags]);\n setShowTagDropdown(!showTagDropdown);\n setShowStatusDropdown(false);\n setShowPriorityDropdown(false);\n }}\n className=\"inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] text-neutral-400 hover:text-neutral-600 rounded border border-dashed border-neutral-300 hover:border-neutral-400 transition-colors\"\n >\n <PlusIcon size={12} /> {showTagDropdown ? 'Close' : 'Edit'}\n </button>\n {showTagDropdown && (\n <div className=\"absolute top-full left-0 mt-1 bg-white border border-neutral-200 rounded-lg shadow-lg z-10 w-56 eb-tb-animate-zoom-in\">\n <div className=\"py-1\">\n {predefinedTags.map((tag) => {\n const isSelected = pendingTags.includes(tag.value);\n return (\n <button key={tag.value} onClick={() => setPendingTags((prev) => isSelected ? prev.filter((t) => t !== tag.value) : [...prev, tag.value])}\n className={`w-full text-left px-3 py-1.5 text-xs hover:bg-neutral-50 flex items-center justify-between ${isSelected ? 'bg-neutral-50' : ''}`}>\n <span className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${tag.className}`}>{tag.label}</span>\n {isSelected && <CheckIcon size={12} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n );\n })}\n {!showOtherTagInput ? (\n <button onClick={() => setShowOtherTagInput(true)} className=\"w-full text-left px-3 py-1.5 text-xs hover:bg-neutral-50 flex items-center justify-between\">\n <span className=\"inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border bg-neutral-100 text-neutral-500 border-neutral-200\">Other</span>\n </button>\n ) : (\n <div className=\"px-3 py-2 bg-neutral-50/50\">\n <div className=\"flex gap-1.5\">\n <input type=\"text\" autoFocus onKeyDown={(e) => {\n if (e.key === 'Enter') { e.preventDefault(); const val = e.currentTarget.value.trim().toLowerCase().replace(/\\s+/g, '-'); if (val && !pendingTags.includes(val)) setPendingTags((prev) => [...prev, val]); e.currentTarget.value = ''; setShowOtherTagInput(false); }\n if (e.key === 'Escape') setShowOtherTagInput(false);\n }} className=\"flex-1 px-2 py-1.5 text-xs border border-neutral-200 rounded-md focus:outline-none focus:ring-1 focus:ring-[#FF5E00]/20 focus:border-[#FF5E00]/50\" placeholder=\"Type a custom tag...\" onClick={(e) => e.stopPropagation()} />\n <button type=\"button\" onClick={() => setShowOtherTagInput(false)} className=\"px-2.5 py-1.5 text-[10px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-md transition-colors\">Add</button>\n </div>\n </div>\n )}\n </div>\n <div className=\"border-t border-neutral-100 px-2 py-2 flex items-center justify-end gap-2\">\n <button onClick={() => { setPendingTags([...localTags]); setShowTagDropdown(false); setShowOtherTagInput(false); }} className=\"px-2.5 py-1 text-[11px] font-medium text-neutral-500 hover:text-neutral-700 transition-colors\">Cancel</button>\n <button onClick={() => { setLocalTags([...pendingTags]); saveField('tags', pendingTags); setShowTagDropdown(false); setShowOtherTagInput(false); }} className=\"px-3 py-1 text-[11px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded transition-colors\">Save</button>\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Description Sections */}\n <div className=\"mt-5 space-y-4\">\n {DESCRIPTION_SECTIONS.map((section) => {\n const val = description[section.key] || '';\n const hasContent = val.trim().length > 0;\n if (!editing && !hasContent) return null;\n return (\n <div key={section.key}>\n <label className=\"text-[11px] font-medium text-neutral-400 uppercase tracking-wide mb-1.5 block\">{section.label}</label>\n {editing ? (\n <MentionTextarea\n value={val}\n onChange={(v) => setDescription((prev) => ({ ...prev, [section.key]: v }))}\n rows={3}\n className=\"w-full px-4 py-2.5 bg-white border border-neutral-200 rounded-lg text-sm leading-relaxed focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 resize-y transition-all placeholder:text-neutral-400\"\n placeholder={`Add ${section.label.toLowerCase()}...`}\n />\n ) : (\n <div className=\"w-full px-3.5 py-2.5 bg-neutral-50/60 border border-neutral-100 rounded-lg text-sm leading-relaxed text-neutral-700 whitespace-pre-wrap\">\n <MentionText text={val} />\n </div>\n )}\n </div>\n );\n })}\n {!editing && !hasDescription(description) && (\n <div className=\"px-3.5 py-4 bg-neutral-50/60 border border-neutral-100 rounded-lg text-sm text-neutral-400 text-center\">\n No description provided.\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Right: Activity panel */}\n {features.comments && (\n <div className=\"w-full md:w-[380px] shrink-0 border-t md:border-t-0 md:border-l border-neutral-100 flex flex-col bg-[#FAFAFA]\">\n <div className=\"px-5 h-12 flex items-center border-b border-neutral-100\">\n <h3 className=\"text-[11px] font-semibold text-neutral-500 uppercase tracking-wide\">\n Activity{detail.commentsLoaded ? ` · ${detail.comments.length + detail.activity.length}` : ''}\n </h3>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4\">\n {!detail.commentsLoaded && (\n <div className=\"space-y-4\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex gap-2.5\">\n <SkeletonPulse className=\"w-7 h-7 rounded-full shrink-0\" />\n <div className=\"flex-1 space-y-1.5\">\n <SkeletonPulse className=\"h-3 w-20\" />\n <SkeletonPulse className=\"h-3 w-full\" />\n </div>\n </div>\n ))}\n </div>\n )}\n\n {detail.commentsLoaded && detail.comments.length === 0 && detail.activity.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"w-10 h-10 rounded-full bg-neutral-100 flex items-center justify-center mb-3\">\n <MessageSquareIcon size={20} className=\"text-neutral-400\" />\n </div>\n <p className=\"text-xs text-neutral-400\">No activity yet</p>\n <p className=\"text-[10px] text-neutral-400 mt-0.5\">Comments and status changes will appear here</p>\n </div>\n )}\n\n <div className=\"space-y-4\">\n {timeline.map((item, i) => {\n if (item.kind === 'comment') {\n const c = item.data as Comment;\n const isOwner = user.username === c.author_id;\n const isEditing = editingCommentId === c.id;\n return (\n <div key={`c-${c.id}`} className={`group/comment flex gap-2.5 ${c.is_internal ? 'pl-2 border-l-2 border-amber-300' : ''}`}>\n <div className={`w-7 h-7 rounded-full flex items-center justify-center shrink-0 mt-0.5 ${c.is_internal ? 'bg-amber-100' : 'bg-neutral-200'}`}>\n <span className={`text-[10px] font-medium ${c.is_internal ? 'text-amber-600' : 'text-neutral-600'}`}>\n {getInitials(c.author_name || '?')}\n </span>\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-0.5\">\n <span className=\"text-[11px] font-semibold text-neutral-700\">{c.author_name}</span>\n {c.is_internal && (\n <span className=\"inline-flex items-center gap-0.5 px-1.5 py-px text-[9px] font-medium text-amber-600 bg-amber-50 border border-amber-200 rounded\">\n <LockIcon size={8} strokeWidth={2.5} /> Internal\n </span>\n )}\n <span className=\"text-[10px] text-neutral-400\">{formatDateTime(c.created_at)}</span>\n {c.edited && (\n <span className=\"text-[9px] text-neutral-400 italic\" title={c.edited_at ? `Edited ${formatDateTime(c.edited_at)}` : 'Edited'}>(edited)</span>\n )}\n {isOwner && (\n <div className={`ml-auto flex items-center gap-0.5 transition-opacity ${isEditing ? 'opacity-100' : 'opacity-0 group-hover/comment:opacity-100'}`}>\n {isEditing ? (\n <>\n <button onClick={saveEditedComment} disabled={!editingCommentContent.trim() || editingCommentContent.trim() === c.content} className=\"p-1 rounded hover:bg-green-50 text-neutral-400 hover:text-green-600 disabled:opacity-30\" title=\"Save edit\"><CheckIcon size={12} strokeWidth={2.5} /></button>\n <button onClick={cancelEditingComment} className=\"p-1 rounded hover:bg-red-50 text-neutral-400 hover:text-red-500\" title=\"Cancel edit\"><XIcon size={12} strokeWidth={2.5} /></button>\n </>\n ) : (\n <>\n <button onClick={() => startEditingComment(c)} className=\"p-1 rounded hover:bg-neutral-100 text-neutral-400 hover:text-neutral-600\" title=\"Edit comment\"><PencilIcon size={11} /></button>\n <button onClick={() => setCommentToDelete(c.id)} className=\"p-1 rounded hover:bg-red-50 text-neutral-400 hover:text-red-500\" title=\"Delete comment\"><TrashIcon size={11} /></button>\n </>\n )}\n </div>\n )}\n </div>\n {isEditing ? (\n <MentionTextarea\n value={editingCommentContent}\n onChange={setEditingCommentContent}\n onKeyDown={(e) => { if (e.key === 'Escape') cancelEditingComment(); if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); saveEditedComment(); } }}\n rows={2}\n className=\"w-full px-2.5 py-1.5 bg-white border border-neutral-300 rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/20 focus:border-[#FF5E00]/50 resize-none\"\n />\n ) : (\n <div className=\"text-xs text-neutral-600 whitespace-pre-wrap leading-relaxed\"><MentionText text={c.content} /></div>\n )}\n </div>\n </div>\n );\n } else {\n const a = item.data as ActivityEntry;\n const fromCol = columns.find((col) => col.key === a.from_status);\n const toCol = columns.find((col) => col.key === a.to_status);\n const isCreated = a.type === 'created';\n return (\n <div key={`a-${a.id}`} className=\"flex gap-2.5\">\n <div className=\"w-7 h-7 rounded-full bg-neutral-100 flex items-center justify-center shrink-0\">\n {isCreated ? <PlusIcon size={12} className=\"text-neutral-400\" /> : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className=\"text-neutral-400\"><path d=\"M5 12h14\"/><path d=\"m12 5 7 7-7 7\"/></svg>\n )}\n </div>\n <div className=\"flex-1 min-w-0\">\n {isCreated ? (\n <p className=\"text-[11px] text-neutral-500\"><span className=\"font-medium text-neutral-700\">{a.user_name}</span>{' created this task'}</p>\n ) : (\n <p className=\"text-[11px] text-neutral-500\">\n <span className=\"font-medium text-neutral-700\">{a.user_name}</span>{' moved from '}\n <span className=\"font-medium text-neutral-700\">{fromCol?.label ?? a.from_status}</span>{' to '}\n <span className=\"font-medium text-neutral-700\">{toCol?.label ?? a.to_status}</span>\n </p>\n )}\n <span className=\"text-[10px] text-neutral-400\">{formatDateTime(a.created_at)}</span>\n </div>\n </div>\n );\n }\n })}\n <div ref={commentsEndRef} />\n </div>\n </div>\n\n {/* Comment input */}\n <div className={`px-5 py-4 pb-5 border-t bg-white transition-colors ${isInternalComment ? 'border-amber-300 bg-amber-50/30' : 'border-neutral-200'}`}>\n <MentionTextarea\n value={newComment}\n onChange={setNewComment}\n onKeyDown={handleCommentKeyDown}\n rows={2}\n className={`w-full px-3 py-2 border rounded-lg text-xs focus:outline-none focus:ring-2 resize-none transition-colors placeholder:text-neutral-400 ${\n isInternalComment\n ? 'bg-amber-50/50 border-amber-200 focus:ring-amber-200/30 focus:border-amber-300'\n : 'bg-neutral-50 border-neutral-200 focus:bg-white focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50'\n }`}\n placeholder={isInternalComment ? 'Write an internal note... (only visible to team)' : 'Write a comment... (type @ to mention someone)'}\n />\n <div className=\"flex items-center justify-between mt-2.5\">\n {features.internalComments && user.is_internal ? (\n <button\n type=\"button\"\n onClick={() => setIsInternalComment(!isInternalComment)}\n className={`flex items-center gap-1.5 text-[11px] font-medium rounded-md px-2 py-1 transition-colors ${\n isInternalComment ? 'bg-amber-100 text-amber-700 border border-amber-200' : 'text-neutral-400 hover:text-neutral-600 hover:bg-neutral-100'\n }`}\n >\n <LockIcon size={12} /> Internal\n </button>\n ) : <div />}\n <button\n onClick={handleAddComment}\n disabled={detail.commentLoading || !newComment.trim()}\n className={`px-4 py-1.5 text-xs font-medium text-white rounded-lg transition-colors disabled:opacity-40 ${\n isInternalComment ? 'bg-amber-500 hover:bg-amber-600' : 'bg-[#FF5E00] hover:bg-[#E05200]'\n }`}\n >\n {detail.commentLoading ? 'Sending...' : isInternalComment ? 'Add Note' : 'Comment'}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Confirmation modals */}\n {showDeleteConfirm && (\n <div className=\"fixed inset-0 z-[110] flex items-center justify-center bg-black/40 eb-tb-animate-fade-in\">\n <div className=\"bg-white rounded-2xl shadow-2xl border border-neutral-200 w-full max-w-sm mx-4 eb-tb-animate-zoom-in\">\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-lg font-medium text-neutral-900\">Delete Task</h2>\n <p className=\"text-sm text-neutral-500\">Are you sure you want to delete <span className=\"font-medium text-neutral-900\">{task.title}</span>? This cannot be undone.</p>\n <div className=\"flex items-center justify-end gap-3\">\n <button onClick={() => setShowDeleteConfirm(false)} className=\"px-4 py-2 text-sm text-neutral-600 hover:text-neutral-900 transition-colors\">Cancel</button>\n <button onClick={handleDelete} disabled={saving} className=\"px-5 py-2 text-sm font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors disabled:opacity-60\">{saving ? 'Deleting...' : 'Delete'}</button>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {commentToDelete && (\n <div className=\"fixed inset-0 z-[110] flex items-center justify-center bg-black/40 eb-tb-animate-fade-in\">\n <div className=\"bg-white rounded-2xl shadow-2xl border border-neutral-200 w-full max-w-sm mx-4 eb-tb-animate-zoom-in\">\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-lg font-medium text-neutral-900\">Delete Comment</h2>\n <p className=\"text-sm text-neutral-500\">Are you sure you want to delete this comment? This cannot be undone.</p>\n <div className=\"flex items-center justify-end gap-3\">\n <button onClick={() => setCommentToDelete(null)} className=\"px-4 py-2 text-sm text-neutral-600 hover:text-neutral-900 transition-colors\">Cancel</button>\n <button onClick={handleDeleteComment} className=\"px-5 py-2 text-sm font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors\">Delete</button>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {showDiscardConfirm && (\n <div className=\"fixed inset-0 z-[110] flex items-center justify-center bg-black/40 eb-tb-animate-fade-in\">\n <div className=\"bg-white rounded-2xl shadow-2xl border border-neutral-200 w-full max-w-sm mx-4 eb-tb-animate-zoom-in\">\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-lg font-medium text-neutral-900\">Unsaved Changes</h2>\n <p className=\"text-sm text-neutral-500\">You have unsaved changes that will be lost. Are you sure you want to discard them?</p>\n <div className=\"flex items-center justify-end gap-3\">\n <button onClick={() => setShowDiscardConfirm(false)} className=\"px-4 py-2 text-sm text-neutral-600 hover:text-neutral-900 transition-colors\">Keep Editing</button>\n <button onClick={() => { handleDiscardChanges(); onClose(); }} className=\"px-5 py-2 text-sm font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-lg transition-colors\">Discard</button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport type { Comment, ActivityEntry, TaskDetailResponse, UpdateTaskPayload } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\ninterface ApiError {\n response?: {\n data?: {\n detail?: string;\n };\n };\n message?: string;\n}\n\nfunction getErrorMessage(err: unknown): string {\n const apiErr = err as ApiError;\n return apiErr?.response?.data?.detail || apiErr?.message || 'An error occurred';\n}\n\nexport function useTaskDetail(taskId: string) {\n const { service, config } = useTaskBoardContext();\n\n const [comments, setComments] = useState<Comment[]>([]);\n const [activity, setActivity] = useState<ActivityEntry[]>([]);\n const [commentsLoaded, setCommentsLoaded] = useState(false);\n const [commentLoading, setCommentLoading] = useState(false);\n\n const fetchDetail = useCallback(async () => {\n try {\n const data = await service.getTask(taskId);\n setComments(data.comments || []);\n setActivity(data.activity || []);\n } catch {\n try {\n const comments = await service.listComments(taskId);\n setComments(comments);\n } catch { /* silent */ }\n } finally {\n setCommentsLoaded(true);\n }\n }, [taskId, service]);\n\n useEffect(() => { fetchDetail(); }, [fetchDetail]);\n\n const addComment = async (content: string, isInternal: boolean = false) => {\n setCommentLoading(true);\n try {\n await service.addComment(taskId, { content, is_internal: isInternal });\n await fetchDetail();\n } catch (err) {\n const message = getErrorMessage(err);\n config.onError?.(err instanceof Error ? err : new Error(message));\n } finally { setCommentLoading(false); }\n };\n\n const editComment = async (commentId: string, content: string) => {\n try {\n await service.editComment(taskId, commentId, { content });\n await fetchDetail();\n } catch (err: unknown) {\n const msg = getErrorMessage(err);\n throw new Error(msg);\n }\n };\n\n const deleteComment = async (commentId: string) => {\n try {\n await service.deleteComment(taskId, commentId);\n await fetchDetail();\n } catch (err: unknown) {\n const msg = getErrorMessage(err);\n throw new Error(msg);\n }\n };\n\n const saveField = async (field: string, value: unknown) => {\n await service.updateTask(taskId, { [field]: value } as UpdateTaskPayload);\n };\n\n return {\n comments,\n activity,\n commentsLoaded,\n commentLoading,\n addComment,\n editComment,\n deleteComment,\n saveField,\n refreshDetail: fetchDetail,\n };\n}\n","import React from 'react';\n\nconst MENTION_RE = /(@\\[.*?\\]\\(.*?\\))/g;\nconst MENTION_PARSE = /^@\\[(.*?)\\]\\((.*?)\\)$/;\n\n/** Renders text with @mentions highlighted as styled badges. */\nexport function MentionText({ text, className = \"\" }: { text: string; className?: string }) {\n if (!text) return null;\n\n const parts = text.split(MENTION_RE);\n\n return (\n <span className={className}>\n {parts.map((part, i) => {\n const match = part.match(MENTION_PARSE);\n if (match) {\n return (\n <span\n key={i}\n className=\"inline-flex items-center px-1.5 py-0.5 mx-0.5 bg-[#FF5E00]/10 text-[#FF5E00] rounded text-[11px] font-semibold cursor-default\"\n title={`@${match[2]}`}\n >\n @{match[1]}\n </span>\n );\n }\n return <span key={i}>{part}</span>;\n })}\n </span>\n );\n}\n\n/** Convert stored @[Name](username) to display @Name for textarea */\nexport function toDisplayText(stored: string): string {\n return stored.replace(/@\\[(.*?)\\]\\(.*?\\)/g, '@$1');\n}\n\n/** Convert display @Name back to stored @[Name](username) using a mention map */\nexport function toStoredText(display: string, mentionMap: Map<string, string>): string {\n let result = display;\n mentionMap.forEach((username, name) => {\n result = result.replace(new RegExp(`@${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`, 'g'), `@[${name}](${username})`);\n });\n return result;\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport type { MentionUser } from '../types';\nimport { getInitials } from '../utils/helpers';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { toDisplayText, toStoredText } from './MentionText';\n\nexport interface MentionTextareaProps {\n value: string;\n onChange: (val: string) => void;\n onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n placeholder?: string;\n rows?: number;\n className?: string;\n disabled?: boolean;\n}\n\nexport function MentionTextarea({\n value,\n onChange,\n onKeyDown,\n placeholder = \"\",\n rows = 2,\n className = \"\",\n disabled = false,\n}: MentionTextareaProps) {\n const { service, features } = useTaskBoardContext();\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [mentionQuery, setMentionQuery] = useState<string | null>(null);\n const [mentionStart, setMentionStart] = useState(0);\n const [mentionUsers, setMentionUsers] = useState<MentionUser[]>([]);\n const [selectedIndex, setSelectedIndex] = useState(0);\n const fetchTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const mentionMapRef = useRef<Map<string, string>>(new Map());\n\n // Initialize mention map from existing value\n useEffect(() => {\n const re = /@\\[(.*?)\\]\\((.*?)\\)/g;\n let match;\n while ((match = re.exec(value)) !== null) {\n mentionMapRef.current.set(match[1], match[2]);\n }\n }, []);\n\n // Fetch users when mention query changes\n useEffect(() => {\n if (!features.mentions || mentionQuery === null) {\n setMentionUsers([]);\n return;\n }\n if (fetchTimeoutRef.current) clearTimeout(fetchTimeoutRef.current);\n fetchTimeoutRef.current = setTimeout(async () => {\n try {\n const users = await service.searchMentionUsers(mentionQuery);\n setMentionUsers(users);\n setSelectedIndex(0);\n } catch {\n setMentionUsers([]);\n }\n }, 150);\n return () => { if (fetchTimeoutRef.current) clearTimeout(fetchTimeoutRef.current); };\n }, [mentionQuery, service, features.mentions]);\n\n const displayValue = toDisplayText(value);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newDisplay = e.target.value;\n const stored = toStoredText(newDisplay, mentionMapRef.current);\n onChange(stored);\n\n const cursorPos = e.target.selectionStart;\n const textBefore = newDisplay.slice(0, cursorPos);\n const atIndex = textBefore.lastIndexOf(\"@\");\n\n if (atIndex >= 0) {\n const charBefore = atIndex > 0 ? textBefore[atIndex - 1] : \" \";\n if (charBefore === \" \" || charBefore === \"\\n\" || atIndex === 0) {\n const query = textBefore.slice(atIndex + 1);\n if (!query.includes(\" \") || query.length <= 20) {\n setMentionQuery(query);\n setMentionStart(atIndex);\n return;\n }\n }\n }\n setMentionQuery(null);\n };\n\n const insertMention = (user: MentionUser) => {\n const display = toDisplayText(value);\n const before = display.slice(0, mentionStart);\n const after = display.slice(mentionStart + 1 + (mentionQuery?.length || 0));\n mentionMapRef.current.set(user.name, user.username);\n const newDisplay = before + `@${user.name} ` + after;\n const stored = toStoredText(newDisplay, mentionMapRef.current);\n onChange(stored);\n setMentionQuery(null);\n setTimeout(() => {\n if (textareaRef.current) {\n textareaRef.current.focus();\n const pos = before.length + user.name.length + 2;\n textareaRef.current.setSelectionRange(pos, pos);\n }\n }, 0);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (mentionQuery !== null && mentionUsers.length > 0) {\n if (e.key === \"ArrowDown\") { e.preventDefault(); setSelectedIndex((i) => Math.min(i + 1, mentionUsers.length - 1)); return; }\n if (e.key === \"ArrowUp\") { e.preventDefault(); setSelectedIndex((i) => Math.max(i - 1, 0)); return; }\n if (e.key === \"Enter\" || e.key === \"Tab\") { e.preventDefault(); insertMention(mentionUsers[selectedIndex]); return; }\n if (e.key === \"Escape\") { e.preventDefault(); setMentionQuery(null); return; }\n }\n onKeyDown?.(e);\n };\n\n return (\n <div className=\"relative\">\n <textarea\n ref={textareaRef}\n value={displayValue}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n rows={rows}\n className={className}\n placeholder={placeholder}\n disabled={disabled}\n />\n {mentionQuery !== null && mentionUsers.length > 0 && (\n <div className=\"absolute bottom-full left-0 mb-1 w-64 bg-white border border-neutral-200 rounded-lg shadow-lg z-50 py-1 max-h-48 overflow-y-auto\">\n <div className=\"px-2.5 py-1.5 text-[10px] font-medium text-neutral-400 uppercase tracking-wide\">People</div>\n {mentionUsers.map((user, i) => (\n <button\n key={user.username}\n onClick={() => insertMention(user)}\n className={`w-full flex items-center gap-2.5 px-3 py-2 text-xs text-left hover:bg-neutral-50 ${\n i === selectedIndex ? \"bg-neutral-50\" : \"\"\n }`}\n >\n <div className=\"w-6 h-6 rounded-full bg-[#FF5E00] flex items-center justify-center shrink-0\">\n <span className=\"text-[9px] font-medium text-white\">{getInitials(user.name)}</span>\n </div>\n <div className=\"min-w-0\">\n <div className=\"text-xs font-medium text-neutral-800 truncate\">{user.name}</div>\n <div className=\"text-[10px] text-neutral-400 truncate\">{user.email}</div>\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["useState","useEffect","useCallback","useCallback","useRef","useRef","useCallback","useState","useCallback","jsx","useEffect","useRef","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","TaskCard","jsx","jsxs","useRef","useEffect","useState","useRef","useEffect","jsx","jsxs","useState","useRef","useEffect","useState","useEffect","useCallback","useRef","jsx","jsxs","useState","useRef","useCallback","useEffect","handleClick","useState","jsx","jsxs","useState","useState","useEffect","useRef","useState","useEffect","useCallback","useState","useCallback","comments","useEffect","jsx","jsxs","useState","useEffect","useRef","jsx","jsxs","useRef","useState","useEffect","jsx","jsxs","useState","useRef","useEffect","Fragment","jsx","jsxs","useState","useEffect","useCallback"]}
|