@emberai-engg/task-board 0.3.6 → 0.4.0
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/README.md +121 -71
- package/dist/index.d.mts +561 -2
- package/dist/index.d.ts +561 -2
- package/dist/index.js +3458 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3400 -35
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +64 -0
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../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":["// ─── Components ───\nexport { TaskBoard } from './components/TaskBoard';\nexport type { TaskBoardProps } from './components/TaskBoard';\nexport { TaskCard } from './components/TaskCard';\nexport type { TaskCardProps } from './components/TaskCard';\nexport { KanbanColumn } from './components/KanbanColumn';\nexport type { KanbanColumnProps } from './components/KanbanColumn';\nexport { FilterBar } from './components/FilterBar';\nexport type { FilterBarProps } from './components/FilterBar';\nexport { NotificationBell } from './components/NotificationBell';\nexport type { NotificationBellProps } from './components/NotificationBell';\nexport { PriorityBadge } from './components/PriorityBadge';\nexport type { PriorityBadgeProps } from './components/PriorityBadge';\nexport { UserAvatar } from './components/UserAvatar';\nexport type { UserAvatarProps } from './components/UserAvatar';\nexport { TagBadge } from './components/TagBadge';\nexport type { TagBadgeProps } from './components/TagBadge';\nexport { MentionText, toDisplayText, toStoredText } from './components/MentionText';\nexport { MentionTextarea } from './components/MentionTextarea';\nexport type { MentionTextareaProps } from './components/MentionTextarea';\nexport { SkeletonPulse, SkeletonCard, BoardSkeleton } from './components/SkeletonPulse';\nexport { CreateTaskModal } from './components/CreateTaskModal';\nexport type { CreateTaskModalProps } from './components/CreateTaskModal';\nexport { TaskDetailPanel } from './components/TaskDetailPanel';\nexport type { TaskDetailPanelProps } from './components/TaskDetailPanel';\n\n// ─── Provider ───\nexport { TaskBoardProvider, useTaskBoardContext } from './context/TaskBoardProvider';\nexport type { TaskBoardConfig, TaskBoardContextValue } from './context/TaskBoardProvider';\n\n// ─── Hooks ───\nexport { useTaskBoard } from './hooks/useTaskBoard';\nexport { useTaskActions } from './hooks/useTaskActions';\nexport { useTaskDetail } from './hooks/useTaskDetail';\nexport { useShareLink } from './hooks/useShareLink';\n\n// ─── Types ───\nexport type {\n Project,\n StructuredDescription,\n Task,\n ActivityEntry,\n Comment,\n Notification,\n MentionUser,\n TasksByStatus,\n ColumnTotals,\n ColumnUnreads,\n ColumnConfig,\n PriorityConfig,\n TagConfig,\n DescriptionSectionConfig,\n TaskBoardUser,\n ApiClient,\n ColumnResponse,\n TaskDetailResponse,\n NotificationCountResponse,\n CreateTaskPayload,\n UpdateTaskPayload,\n CreateCommentPayload,\n EditCommentPayload,\n ApiClientConfig,\n} from './types';\n\n// ─── Service ───\nexport { createTaskBoardService } from './services/taskBoardService';\nexport type { TaskBoardService } from './services/taskBoardService';\n\n// ─── Utils ───\nexport {\n getPriorityStyle,\n getTagStyle,\n getInitials,\n formatDate,\n formatDateTime,\n getDescriptionPreview,\n hasDescription,\n getUserProjects,\n} from './utils/helpers';\n\n// ─── Constants ───\nexport {\n DEFAULT_COLUMNS,\n DEFAULT_PRIORITIES,\n PREDEFINED_TAGS,\n DESCRIPTION_SECTIONS,\n EMPTY_DESCRIPTION,\n POSITION_GAP,\n DEFAULT_PAGE_SIZE,\n} from './utils/constants';\n\n// ─── Icons ───\nexport {\n PlusIcon,\n XIcon,\n ChevronDownIcon,\n MessageSquareIcon,\n KanbanIcon,\n LinkIcon,\n CheckIcon,\n BellIcon,\n FilterIcon,\n PencilIcon,\n TrashIcon,\n LockIcon,\n FeedbackIcon,\n} from './icons';\n","import React, { useState, useEffect, useCallback, useRef } 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 isDraggingRef = useRef(false);\n const board = useTaskBoard(isDraggingRef);\n const actions = useTaskActions(board.tasks, board.setTasks, board.fetchTasks, isDraggingRef, board.setColumnTotals);\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(isDragging?: React.RefObject<boolean>) {\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(() => {\n if (isDragging?.current) return;\n fetchTasks();\n }, [fetchTasks, isDragging]);\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 setColumnTotals,\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, ColumnTotals, 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 isDragging?: React.RefObject<boolean>,\n setColumnTotals?: React.Dispatch<React.SetStateAction<ColumnTotals>>,\n) {\n const { service, config } = useTaskBoardContext();\n\n const internalDragging = useRef(false);\n const draggingRef = isDragging ?? internalDragging;\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 draggingRef.current = true;\n\n // Calculate position and apply optimistic update via functional updater\n let newPosition = POSITION_GAP;\n\n setTasks((prev) => {\n const sourceCol = [...(prev[sourceStatus] || [])];\n const destCol = sourceStatus === destStatus ? sourceCol : [...(prev[destStatus] || [])];\n\n const [movedTask] = sourceCol.splice(sourceIndex, 1);\n if (!movedTask) return prev;\n\n const updatedTask = { ...movedTask, status: destStatus };\n destCol.splice(destIndex, 0, updatedTask);\n\n // Calculate position\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 const newTasks = { ...prev };\n newTasks[sourceStatus] = sourceCol;\n if (sourceStatus !== destStatus) {\n newTasks[destStatus] = destCol;\n }\n return newTasks;\n });\n\n // Keep column totals in sync so infinite-scroll sentinel stops firing\n if (sourceStatus !== destStatus && setColumnTotals) {\n setColumnTotals((prev) => ({\n ...prev,\n [sourceStatus]: Math.max(0, (prev[sourceStatus] || 0) - 1),\n [destStatus]: (prev[destStatus] || 0) + 1,\n }));\n }\n\n // Persist to backend\n try {\n await service.updateTask(taskId, { status: destStatus, position: newPosition });\n } catch {\n fetchTasks();\n } finally {\n draggingRef.current = false;\n }\n }, [setTasks, setColumnTotals, 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 const onLoadMoreRef = useRef(onLoadMore);\n onLoadMoreRef.current = onLoadMore;\n\n useEffect(() => {\n const el = sentinelRef.current;\n if (!el) return;\n const observer = new IntersectionObserver(\n ([entry]) => { if (entry.isIntersecting && !loading) onLoadMoreRef.current(); },\n { threshold: 0.1 }\n );\n observer.observe(el);\n return () => observer.disconnect();\n }, [loading]);\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\n/** Strip @[Name](username) mention markup to plain @Name for previews. */\nfunction stripMentionMarkup(text: string): string {\n return text.replace(/@\\[(.*?)\\]\\(.*?\\)/g, \"@$1\");\n}\n\nexport function getDescriptionPreview(desc: StructuredDescription | string | undefined): string {\n if (!desc) return \"\";\n if (typeof desc === \"string\") return stripMentionMarkup(desc);\n for (const section of DESCRIPTION_SECTIONS) {\n const val = desc[section.key]?.trim();\n if (val) return stripMentionMarkup(val);\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":["import_react","import_dnd","import_react","import_react","import_react","import_jsx_runtime","import_react","import_dnd","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","TaskCard","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","handleClick","import_react","import_jsx_runtime","import_react","import_react","comments","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../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","../src/components/TaskDetailView.tsx","../src/utils/threads.ts","../src/components/DescriptionSection.tsx","../src/components/MarkdownView.tsx","../src/components/MarkdownEditor.tsx","../src/utils/markdown.ts","../src/components/OutstandingQuestionsSection.tsx","../src/components/AttachmentsSection.tsx","../src/components/ThreadsPanel.tsx","../src/components/ActivityList.tsx","../src/components/ContextPill.tsx","../src/components/ThreadCard.tsx","../src/components/ThreadComposer.tsx","../src/components/ThreadDetailView.tsx","../src/components/HighlightBubble.tsx","../src/hooks/useTaskQuestions.ts","../src/hooks/useTaskAttachments.ts","../src/hooks/useHighlightAnchor.ts"],"sourcesContent":["// ─── Components ───\nexport { TaskBoard } from './components/TaskBoard';\nexport type { TaskBoardProps } from './components/TaskBoard';\nexport { TaskCard } from './components/TaskCard';\nexport type { TaskCardProps } from './components/TaskCard';\nexport { KanbanColumn } from './components/KanbanColumn';\nexport type { KanbanColumnProps } from './components/KanbanColumn';\nexport { FilterBar } from './components/FilterBar';\nexport type { FilterBarProps } from './components/FilterBar';\nexport { NotificationBell } from './components/NotificationBell';\nexport type { NotificationBellProps } from './components/NotificationBell';\nexport { PriorityBadge } from './components/PriorityBadge';\nexport type { PriorityBadgeProps } from './components/PriorityBadge';\nexport { UserAvatar } from './components/UserAvatar';\nexport type { UserAvatarProps } from './components/UserAvatar';\nexport { TagBadge } from './components/TagBadge';\nexport type { TagBadgeProps } from './components/TagBadge';\nexport { MentionText, toDisplayText, toStoredText } from './components/MentionText';\nexport { MentionTextarea } from './components/MentionTextarea';\nexport type { MentionTextareaProps } from './components/MentionTextarea';\nexport { SkeletonPulse, SkeletonCard, BoardSkeleton } from './components/SkeletonPulse';\nexport { CreateTaskModal } from './components/CreateTaskModal';\nexport type { CreateTaskModalProps } from './components/CreateTaskModal';\nexport { TaskDetailPanel } from './components/TaskDetailPanel';\nexport type { TaskDetailPanelProps } from './components/TaskDetailPanel';\n\n// ─── v0.4 detail page ───\nexport { TaskDetailView } from './components/TaskDetailView';\nexport type { TaskDetailViewProps } from './components/TaskDetailView';\nexport { DescriptionSection } from './components/DescriptionSection';\nexport type { DescriptionSectionProps } from './components/DescriptionSection';\nexport { MarkdownView } from './components/MarkdownView';\nexport { MarkdownEditor } from './components/MarkdownEditor';\nexport type { MarkdownEditorProps } from './components/MarkdownEditor';\nexport { OutstandingQuestionsSection } from './components/OutstandingQuestionsSection';\nexport type { OutstandingQuestionsSectionProps } from './components/OutstandingQuestionsSection';\nexport { AttachmentsSection } from './components/AttachmentsSection';\nexport type { AttachmentsSectionProps } from './components/AttachmentsSection';\nexport { ThreadsPanel } from './components/ThreadsPanel';\nexport type { ThreadsPanelProps } from './components/ThreadsPanel';\nexport { ThreadCard } from './components/ThreadCard';\nexport type { ThreadCardProps } from './components/ThreadCard';\nexport { ThreadDetailView } from './components/ThreadDetailView';\nexport type { ThreadDetailViewProps } from './components/ThreadDetailView';\nexport { ThreadComposer } from './components/ThreadComposer';\nexport type { ThreadComposerProps } from './components/ThreadComposer';\nexport { ActivityList } from './components/ActivityList';\nexport type { ActivityListProps } from './components/ActivityList';\nexport { ContextPill } from './components/ContextPill';\nexport type { ContextPillProps, ContextPillVariant } from './components/ContextPill';\nexport { HighlightBubble } from './components/HighlightBubble';\nexport type { HighlightBubbleProps } from './components/HighlightBubble';\n\n// ─── Provider ───\nexport { TaskBoardProvider, useTaskBoardContext } from './context/TaskBoardProvider';\nexport type { TaskBoardConfig, TaskBoardContextValue } from './context/TaskBoardProvider';\n\n// ─── Hooks ───\nexport { useTaskBoard } from './hooks/useTaskBoard';\nexport { useTaskActions } from './hooks/useTaskActions';\nexport { useTaskDetail } from './hooks/useTaskDetail';\nexport { useShareLink } from './hooks/useShareLink';\nexport { useTaskQuestions } from './hooks/useTaskQuestions';\nexport type { UseTaskQuestionsResult } from './hooks/useTaskQuestions';\nexport { useTaskAttachments } from './hooks/useTaskAttachments';\nexport type { UseTaskAttachmentsResult } from './hooks/useTaskAttachments';\nexport { useHighlightAnchor } from './hooks/useHighlightAnchor';\nexport type { UseHighlightAnchorResult, BubbleState } from './hooks/useHighlightAnchor';\n\n// ─── Types ───\nexport type {\n Project,\n StructuredDescription,\n Task,\n ActivityEntry,\n Comment,\n Notification,\n MentionUser,\n TasksByStatus,\n ColumnTotals,\n ColumnUnreads,\n ColumnConfig,\n PriorityConfig,\n TagConfig,\n DescriptionSectionConfig,\n TaskBoardUser,\n ApiClient,\n ColumnResponse,\n TaskDetailResponse,\n NotificationCountResponse,\n CreateTaskPayload,\n UpdateTaskPayload,\n CreateCommentPayload,\n EditCommentPayload,\n ApiClientConfig,\n // v0.4 additions\n SectionKey,\n SectionStatus,\n ThreadStatus,\n ThreadAnchor,\n Question,\n QuestionReply,\n QuestionStatus,\n Attachment,\n AttachmentKind,\n UpdateThreadPayload,\n CreateQuestionPayload,\n UpdateQuestionPayload,\n CreateQuestionReplyPayload,\n CreateLinkAttachmentPayload,\n} from './types';\n\n// ─── Service ───\nexport { createTaskBoardService } from './services/taskBoardService';\nexport type { TaskBoardService } from './services/taskBoardService';\n\n// ─── Utils ───\nexport {\n getPriorityStyle,\n getTagStyle,\n getInitials,\n formatDate,\n formatDateTime,\n parseDate,\n formatTaskId,\n getDescriptionPreview,\n hasDescription,\n getUserProjects,\n} from './utils/helpers';\nexport { mdToHtml, htmlToMd } from './utils/markdown';\nexport { deriveThreads, sectionLabel, timeAgo } from './utils/threads';\nexport type { Thread, ThreadReply } from './utils/threads';\n\n// ─── Constants ───\nexport {\n DEFAULT_COLUMNS,\n DEFAULT_PRIORITIES,\n PREDEFINED_TAGS,\n DESCRIPTION_SECTIONS,\n EMPTY_DESCRIPTION,\n POSITION_GAP,\n DEFAULT_PAGE_SIZE,\n DEFAULT_INTERNAL_LABEL,\n} from './utils/constants';\n\n// ─── Icons ───\nexport {\n PlusIcon,\n XIcon,\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ArrowLeftIcon,\n MoreVerticalIcon,\n Share2Icon,\n MessageSquareIcon,\n KanbanIcon,\n LinkIcon,\n Link2Icon,\n ExternalLinkIcon,\n ImageIcon,\n FileTextIcon,\n CheckIcon,\n CheckCircle2Icon,\n BellIcon,\n FilterIcon,\n PencilIcon,\n TrashIcon,\n LockIcon,\n FeedbackIcon,\n HelpCircleIcon,\n CornerUpLeftIcon,\n RotateCcwIcon,\n ChatDotsIcon,\n HistoryIcon,\n SidebarToggleIcon,\n // Markdown editor toolbar\n Bold,\n Italic,\n List,\n ListOrdered,\n Heading2,\n Quote,\n Code,\n} from './icons';\n","import React, { useState, useEffect, useCallback, useRef } 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 isDraggingRef = useRef(false);\n const board = useTaskBoard(isDraggingRef);\n const actions = useTaskActions(board.tasks, board.setTasks, board.fetchTasks, isDraggingRef, board.setColumnTotals);\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) — legacy support.\n // When `onTaskOpen` is provided we hand off to the consumer (route-based nav);\n // otherwise we open the built-in slide-over. Either way, the ?task= param\n // gets stripped from the URL.\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 if (onTaskOpen) {\n onTaskOpen(task);\n } else {\n setSelectedTask(task);\n service.markTaskRead(taskId).catch(() => {});\n }\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, onTaskOpen]);\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 // When the consumer routes to a separate detail page (onTaskOpen\n // provided), don't open the built-in slide-over — they own navigation.\n if (!onTaskOpen) {\n setSelectedTask(task);\n }\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 if (onTaskOpen) {\n onTaskOpen(task);\n } else {\n setSelectedTask(task);\n service.markTaskRead(taskId).catch(() => {});\n }\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 /** Label shown on internal-only comment chips. Defaults to \"Internal\". */\n internalLabel?: 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 internalLabel: string;\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 internalLabel: config.internalLabel ?? 'Internal',\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 Question,\n Attachment,\n CreateTaskPayload,\n UpdateTaskPayload,\n CreateCommentPayload,\n EditCommentPayload,\n UpdateThreadPayload,\n CreateQuestionPayload,\n UpdateQuestionPayload,\n CreateQuestionReplyPayload,\n CreateLinkAttachmentPayload,\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 / Threads ───\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 /** Update a top-level comment's title and/or thread_status. */\n updateThread(taskId: string, threadId: string, data: UpdateThreadPayload): Promise<Comment>;\n\n // ─── Outstanding Questions ───\n listQuestions(taskId: string): Promise<Question[]>;\n createQuestion(taskId: string, data: CreateQuestionPayload): Promise<Question>;\n updateQuestion(taskId: string, questionId: string, data: UpdateQuestionPayload): Promise<Question>;\n deleteQuestion(taskId: string, questionId: string): Promise<void>;\n addQuestionReply(taskId: string, questionId: string, data: CreateQuestionReplyPayload): Promise<{ id: string }>;\n deleteQuestionReply(taskId: string, questionId: string, replyId: string): Promise<void>;\n\n // ─── Attachments ───\n listAttachments(taskId: string): Promise<Attachment[]>;\n uploadAttachment(taskId: string, file: File): Promise<Attachment>;\n addLinkAttachment(taskId: string, data: CreateLinkAttachmentPayload): Promise<Attachment>;\n deleteAttachment(taskId: string, attachmentId: 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 / Threads ───\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 async updateThread(taskId, threadId, payload) {\n const { data } = await apiClient.patch<Comment>(\n `${basePath}/tasks/${taskId}/threads/${threadId}`,\n payload\n );\n return data;\n },\n\n // ─── Outstanding Questions ───\n\n async listQuestions(taskId) {\n const { data } = await apiClient.get<Question[]>(`${basePath}/tasks/${taskId}/questions`);\n return data;\n },\n\n async createQuestion(taskId, payload) {\n const { data } = await apiClient.post<Question>(`${basePath}/tasks/${taskId}/questions`, payload);\n return data;\n },\n\n async updateQuestion(taskId, questionId, payload) {\n const { data } = await apiClient.patch<Question>(\n `${basePath}/tasks/${taskId}/questions/${questionId}`,\n payload\n );\n return data;\n },\n\n async deleteQuestion(taskId, questionId) {\n await apiClient.delete(`${basePath}/tasks/${taskId}/questions/${questionId}`);\n },\n\n async addQuestionReply(taskId, questionId, payload) {\n const { data } = await apiClient.post<{ id: string }>(\n `${basePath}/tasks/${taskId}/questions/${questionId}/replies`,\n payload\n );\n return data;\n },\n\n async deleteQuestionReply(taskId, questionId, replyId) {\n await apiClient.delete(\n `${basePath}/tasks/${taskId}/questions/${questionId}/replies/${replyId}`\n );\n },\n\n // ─── Attachments ───\n\n async listAttachments(taskId) {\n const { data } = await apiClient.get<Attachment[]>(\n `${basePath}/tasks/${taskId}/attachments`\n );\n return data;\n },\n\n async uploadAttachment(taskId, file) {\n const form = new FormData();\n form.append('file', file);\n const { data } = await apiClient.post<Attachment>(\n `${basePath}/tasks/${taskId}/attachments/upload`,\n form\n );\n return data;\n },\n\n async addLinkAttachment(taskId, payload) {\n const { data } = await apiClient.post<Attachment>(\n `${basePath}/tasks/${taskId}/attachments/link`,\n payload\n );\n return data;\n },\n\n async deleteAttachment(taskId, attachmentId) {\n await apiClient.delete(`${basePath}/tasks/${taskId}/attachments/${attachmentId}`);\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 {\n ColumnConfig,\n PriorityConfig,\n TagConfig,\n DescriptionSectionConfig,\n StructuredDescription,\n} from '../types';\n\nexport const DEFAULT_COLUMNS: ColumnConfig[] = [\n { key: \"backlog\", label: \"Backlog\", color: \"bg-neutral-400\", chip: \"bg-neutral-100 text-neutral-700\", description: \"Tasks not yet scheduled\" },\n { key: \"blocked\", label: \"Blocked\", color: \"bg-red-500\", chip: \"bg-red-50 text-red-700\", description: \"Waiting on a dependency\" },\n { key: \"queued\", label: \"Queued\", color: \"bg-[#FF5E00]\", chip: \"bg-[#FF5E00]/10 text-[#FF5E00]\", description: \"Scheduled for this sprint\" },\n { key: \"in_progress\", label: \"In Progress\", color: \"bg-amber-500\", chip: \"bg-amber-50 text-amber-700\", description: \"Actively being worked on\" },\n { key: \"in_testing\", label: \"In Testing\", color: \"bg-teal-500\", chip: \"bg-teal-50 text-teal-700\", description: \"Under QA and validation\" },\n { key: \"client_review\", label: \"Client Review\", color: \"bg-purple-500\", chip: \"bg-purple-50 text-purple-700\", description: \"Live & ready for client review\" },\n { key: \"changes_requested\", label: \"Changes Requested\", color: \"bg-orange-500\", chip: \"bg-orange-50 text-orange-700\", description: \"Revisions needed from review\" },\n { key: \"approved\", label: \"Approved\", color: \"bg-green-500\", chip: \"bg-green-50 text-green-700\", 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\", dot: \"bg-red-500\" },\n { value: \"high\", label: \"High\", className: \"bg-orange-50 text-orange-600 border-orange-200\", dot: \"bg-orange-500\" },\n { value: \"medium\", label: \"Medium\", className: \"bg-amber-50 text-amber-600 border-amber-200\", dot: \"bg-amber-500\" },\n { value: \"low\", label: \"Low\", className: \"bg-neutral-100 text-neutral-500 border-neutral-200\", dot: \"bg-neutral-300\" },\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\", placeholder: \"Describe the problem...\" },\n { key: \"user_story\", label: \"User Story\", placeholder: \"As a ___, I want ___, so that ___...\" },\n { key: \"proposed_behavior\", label: \"Proposed Behavior\", placeholder: \"Describe the proposed behavior...\" },\n { key: \"acceptance_criteria\", label: \"Acceptance Criteria\", placeholder: \"What needs to be true for this to be considered done?\" },\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\n/** Default label shown on internal-only comments. Override via TaskBoardProvider's `internalLabel` prop. */\nexport const DEFAULT_INTERNAL_LABEL = \"Internal\";\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(isDragging?: React.RefObject<boolean>) {\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(() => {\n if (isDragging?.current) return;\n fetchTasks();\n }, [fetchTasks, isDragging]);\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 setColumnTotals,\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, ColumnTotals, 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 isDragging?: React.RefObject<boolean>,\n setColumnTotals?: React.Dispatch<React.SetStateAction<ColumnTotals>>,\n) {\n const { service, config } = useTaskBoardContext();\n\n const internalDragging = useRef(false);\n const draggingRef = isDragging ?? internalDragging;\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 draggingRef.current = true;\n\n // Calculate position and apply optimistic update via functional updater\n let newPosition = POSITION_GAP;\n\n setTasks((prev) => {\n const sourceCol = [...(prev[sourceStatus] || [])];\n const destCol = sourceStatus === destStatus ? sourceCol : [...(prev[destStatus] || [])];\n\n const [movedTask] = sourceCol.splice(sourceIndex, 1);\n if (!movedTask) return prev;\n\n const updatedTask = { ...movedTask, status: destStatus };\n destCol.splice(destIndex, 0, updatedTask);\n\n // Calculate position\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 const newTasks = { ...prev };\n newTasks[sourceStatus] = sourceCol;\n if (sourceStatus !== destStatus) {\n newTasks[destStatus] = destCol;\n }\n return newTasks;\n });\n\n // Keep column totals in sync so infinite-scroll sentinel stops firing\n if (sourceStatus !== destStatus && setColumnTotals) {\n setColumnTotals((prev) => ({\n ...prev,\n [sourceStatus]: Math.max(0, (prev[sourceStatus] || 0) - 1),\n [destStatus]: (prev[destStatus] || 0) + 1,\n }));\n }\n\n // Persist to backend\n try {\n await service.updateTask(taskId, { status: destStatus, position: newPosition });\n } catch {\n fetchTasks();\n } finally {\n draggingRef.current = false;\n }\n }, [setTasks, setColumnTotals, 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 const onLoadMoreRef = useRef(onLoadMore);\n onLoadMoreRef.current = onLoadMore;\n\n useEffect(() => {\n const el = sentinelRef.current;\n if (!el) return;\n const observer = new IntersectionObserver(\n ([entry]) => { if (entry.isIntersecting && !loading) onLoadMoreRef.current(); },\n { threshold: 0.1 }\n );\n observer.observe(el);\n return () => observer.disconnect();\n }, [loading]);\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\n/** Parse a date string, treating timezone-naive Mongo timestamps as UTC. */\nexport function parseDate(dateStr: string): Date {\n if (!dateStr) return new Date();\n if (\n !dateStr.endsWith(\"Z\") &&\n !dateStr.includes(\"+\") &&\n !/\\d{2}:\\d{2}$/.test(dateStr.slice(-6))\n ) {\n return new Date(dateStr + \"Z\");\n }\n return new Date(dateStr);\n}\n\nexport function formatDate(dateStr: string): string {\n if (!dateStr) return \"\";\n return parseDate(dateStr).toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\" });\n}\n\nexport function formatDateTime(dateStr: string): string {\n if (!dateStr) return \"\";\n return parseDate(dateStr).toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n}\n\n/** Build a short task ID label like \"T-AB12CD\" from a Mongo ObjectId. */\nexport function formatTaskId(id: string): string {\n return `T-${id.slice(-6).toUpperCase()}`;\n}\n\n/** Strip @[Name](username) mention markup to plain @Name for previews. */\nfunction stripMentionMarkup(text: string): string {\n return text.replace(/@\\[(.*?)\\]\\(.*?\\)/g, \"@$1\");\n}\n\n/** Convert stored format `@[Name](username)` to display format `@Name` for textareas. */\nexport function toDisplayText(stored: string): string {\n return stripMentionMarkup(stored);\n}\n\n/** Convert display format back to stored format using a name → username map. */\nexport function toStoredText(display: string, mentionMap: Map<string, string>): string {\n let result = display;\n mentionMap.forEach((username, name) => {\n result = result.replace(\n new RegExp(`@${name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}(?!\\\\])`, \"g\"),\n `@[${name}](${username})`\n );\n });\n return result;\n}\n\nexport function getDescriptionPreview(desc: StructuredDescription | string | undefined): string {\n if (!desc) return \"\";\n if (typeof desc === \"string\") return stripMentionMarkup(desc);\n for (const section of DESCRIPTION_SECTIONS) {\n const val = desc[section.key]?.trim();\n if (val) return stripMentionMarkup(val);\n }\n if (desc.open_questions?.trim()) return stripMentionMarkup(desc.open_questions.trim());\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 if (DESCRIPTION_SECTIONS.some((s) => desc[s.key]?.trim())) return true;\n return !!desc.open_questions?.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 ChevronLeftIcon: 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=\"15 18 9 12 15 6\" />\n </svg>\n);\n\nexport const ChevronRightIcon: 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=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nexport const ArrowLeftIcon: 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=\"19\" y1=\"12\" x2=\"5\" y2=\"12\" /><polyline points=\"12 19 5 12 12 5\" />\n </svg>\n);\n\nexport const MoreVerticalIcon: 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 <circle cx=\"12\" cy=\"12\" r=\"1\" /><circle cx=\"12\" cy=\"5\" r=\"1\" /><circle cx=\"12\" cy=\"19\" r=\"1\" />\n </svg>\n);\n\nexport const Share2Icon: 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 <circle cx=\"18\" cy=\"5\" r=\"3\" /><circle cx=\"6\" cy=\"12\" r=\"3\" /><circle cx=\"18\" cy=\"19\" r=\"3\" />\n <line x1=\"8.59\" y1=\"13.51\" x2=\"15.42\" y2=\"17.49\" /><line x1=\"15.41\" y1=\"6.51\" x2=\"8.59\" y2=\"10.49\" />\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 Link2Icon: 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=\"M9 17H7A5 5 0 0 1 7 7h2\" /><path d=\"M15 7h2a5 5 0 1 1 0 10h-2\" /><line x1=\"8\" y1=\"12\" x2=\"16\" y2=\"12\" />\n </svg>\n);\n\nexport const ExternalLinkIcon: 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=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" /><polyline points=\"15 3 21 3 21 9\" /><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n);\n\nexport const ImageIcon: 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=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\" /><circle cx=\"9\" cy=\"9\" r=\"2\" /><path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" />\n </svg>\n);\n\nexport const FileTextIcon: 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=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" /><polyline points=\"14 2 14 8 20 8\" /><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" /><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" /><line x1=\"10\" y1=\"9\" x2=\"8\" y2=\"9\" />\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 CheckCircle2Icon: 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 <circle cx=\"12\" cy=\"12\" r=\"10\" /><polyline points=\"9 11 12 14 15 11\" />\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\nexport const HelpCircleIcon: 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 <circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" /><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n);\n\nexport const CornerUpLeftIcon: 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=\"9 14 4 9 9 4\" /><path d=\"M20 20v-7a4 4 0 0 0-4-4H4\" />\n </svg>\n);\n\nexport const RotateCcwIcon: 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 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" /><path d=\"M3 3v5h5\" />\n </svg>\n);\n\n// ─── Markdown editor toolbar ───\n\nexport const Bold: 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=\"M14 12a4 4 0 0 0 0-8H6v8\" /><path d=\"M15 20a4 4 0 0 0 0-8H6v8Z\" />\n </svg>\n);\n\nexport const Italic: 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=\"19\" y1=\"4\" x2=\"10\" y2=\"4\" /><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\" /><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\" />\n </svg>\n);\n\nexport const List: 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=\"8\" y1=\"6\" x2=\"21\" y2=\"6\" /><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\" /><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\" /><line x1=\"3\" y1=\"6\" x2=\"3.01\" y2=\"6\" /><line x1=\"3\" y1=\"12\" x2=\"3.01\" y2=\"12\" /><line x1=\"3\" y1=\"18\" x2=\"3.01\" y2=\"18\" />\n </svg>\n);\n\nexport const ListOrdered: 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=\"10\" y1=\"6\" x2=\"21\" y2=\"6\" /><line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\" /><line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\" /><path d=\"M4 6h1v4\" /><path d=\"M4 10h2\" /><path d=\"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1\" />\n </svg>\n);\n\nexport const Heading2: 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=\"M4 12h8\" /><path d=\"M4 18V6\" /><path d=\"M12 18V6\" /><path d=\"M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1\" />\n </svg>\n);\n\nexport const Quote: 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 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z\" /><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\" />\n </svg>\n);\n\nexport const Code: 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=\"16 18 22 12 16 6\" /><polyline points=\"8 6 2 12 8 18\" />\n </svg>\n);\n\n// ─── Threads panel chrome ───\n\nexport const ChatDotsIcon: 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 <line x1=\"8\" y1=\"10\" x2=\"8.01\" y2=\"10\" /><line x1=\"12\" y1=\"10\" x2=\"12.01\" y2=\"10\" /><line x1=\"16\" y1=\"10\" x2=\"16.01\" y2=\"10\" />\n </svg>\n);\n\nexport const HistoryIcon: 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 12a9 9 0 1 0 3-6.7L3 8\" /><polyline points=\"3 3 3 8 8 8\" /><polyline points=\"12 7 12 12 15 14\" />\n </svg>\n);\n\n/** Sidebar-toggle icon used to collapse / re-open the threads panel. */\nexport const SidebarToggleIcon: 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 x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" /><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" />\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","import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n ActivityEntry,\n Attachment,\n Comment,\n Question,\n SectionKey,\n SectionStatus,\n StructuredDescription,\n Task,\n ThreadAnchor,\n ThreadStatus,\n} from '../types';\nimport {\n ArrowLeftIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n MoreVerticalIcon,\n PlusIcon,\n Share2Icon,\n TrashIcon,\n XIcon,\n} from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { DESCRIPTION_SECTIONS, EMPTY_DESCRIPTION } from '../utils/constants';\nimport { formatDate, formatTaskId, getInitials, getPriorityStyle, getTagStyle } from '../utils/helpers';\nimport { deriveThreads } from '../utils/threads';\nimport { DescriptionSection } from './DescriptionSection';\nimport { OutstandingQuestionsSection } from './OutstandingQuestionsSection';\nimport { AttachmentsSection } from './AttachmentsSection';\nimport { ThreadsPanel } from './ThreadsPanel';\nimport { HighlightBubble } from './HighlightBubble';\nimport { useTaskQuestions } from '../hooks/useTaskQuestions';\nimport { useTaskAttachments } from '../hooks/useTaskAttachments';\nimport { useHighlightAnchor } from '../hooks/useHighlightAnchor';\n\nconst PANEL_OPEN_KEY = 'taskboard:panelOpen';\n\nexport interface TaskDetailViewProps {\n taskId: string;\n /** href for the \"Back to Task Board\" link. Ignored if `onBack` is provided. */\n backHref?: string;\n /** Called when the back link is clicked. Use this for SPA routing. */\n onBack?: () => void;\n /** Optional slot above the main content (e.g. consumer's breadcrumb bar). */\n breadcrumb?: React.ReactNode;\n /** Called after a successful delete; consumer should navigate away. */\n onDeleted?: (task: Task) => void;\n /**\n * Provide this to enable the prev/next buttons. The view fetches the\n * project's task list and computes neighbors; on click, the consumer\n * is responsible for navigating to /task-board/[id]?project=<slug>.\n */\n onNavigateToTask?: (taskId: string, projectSlug: string) => void;\n /** Build a share URL for the task. Defaults to `${origin}/task-board/${id}?project=${slug}`. */\n buildShareUrl?: (task: Task) => string;\n}\n\n/**\n * Full-page task detail orchestrator. Renders the breadcrumb slot, back +\n * prev/next chrome, the task ID/project header, inline-editable title,\n * status/priority/menu action cluster, all description sections, outstanding\n * questions, attachments, and the right-side threads panel with\n * highlight-to-comment.\n *\n * Consumers are responsible for app chrome (sidebar, breadcrumb bar) — pass\n * the breadcrumb via `breadcrumb` and place this inside your existing layout.\n */\nexport function TaskDetailView({\n taskId,\n backHref,\n onBack,\n breadcrumb,\n onDeleted,\n onNavigateToTask,\n buildShareUrl,\n}: TaskDetailViewProps) {\n const { service, projects, columns, priorities, tags: predefinedTags, user, internalLabel } = useTaskBoardContext();\n\n const [task, setTask] = useState<Task | null>(null);\n const [comments, setComments] = useState<Comment[]>([]);\n const [activity, setActivity] = useState<ActivityEntry[]>([]);\n const [initialQuestions, setInitialQuestions] = useState<Question[] | undefined>(undefined);\n const [initialAttachments, setInitialAttachments] = useState<Attachment[] | undefined>(undefined);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState('');\n const [saving, setSaving] = useState(false);\n\n // Editable local state mirrors the task and persists on commit.\n const [title, setTitle] = useState('');\n const [titleEditing, setTitleEditing] = useState(false);\n const [description, setDescription] = useState<StructuredDescription>(EMPTY_DESCRIPTION);\n const [priority, setPriority] = useState('medium');\n const [taskStatus, setTaskStatus] = useState('backlog');\n const [tags, setTags] = useState<string[]>([]);\n\n // Header dropdowns\n const [statusOpen, setStatusOpen] = useState(false);\n const [priorityOpen, setPriorityOpen] = useState(false);\n const [moreOpen, setMoreOpen] = useState(false);\n const [tagsOpen, setTagsOpen] = useState(false);\n const [pendingTags, setPendingTags] = useState<string[]>([]);\n const [showOtherTagInput, setShowOtherTagInput] = useState(false);\n const [linkCopied, setLinkCopied] = useState(false);\n\n const statusRef = useRef<HTMLDivElement>(null);\n const priorityRef = useRef<HTMLDivElement>(null);\n const moreRef = useRef<HTMLDivElement>(null);\n const tagsRef = useRef<HTMLDivElement>(null);\n\n const [projectTaskIds, setProjectTaskIds] = useState<string[]>([]);\n const [openThreadId, setOpenThreadId] = useState<string | null>(null);\n const [shimmeringThreadIds, setShimmeringThreadIds] = useState<Set<string>>(new Set());\n\n // Right panel open/closed (persisted via localStorage)\n const [panelOpen, setPanelOpen] = useState<boolean>(() => {\n if (typeof window === 'undefined') return true;\n try {\n const stored = window.localStorage.getItem(PANEL_OPEN_KEY);\n return stored === null ? true : stored === 'true';\n } catch {\n return true;\n }\n });\n\n const togglePanel = () => {\n setPanelOpen((prev) => {\n const next = !prev;\n try {\n window.localStorage.setItem(PANEL_OPEN_KEY, String(next));\n } catch {\n // ignore\n }\n return next;\n });\n };\n\n // ─── Data fetching ───\n\n const fetchTask = useCallback(async () => {\n try {\n const data = await service.getTask(taskId);\n setTask(data);\n setTitle(data.title || '');\n setDescription(data.description || EMPTY_DESCRIPTION);\n setPriority(data.priority || 'medium');\n setTaskStatus(data.status || 'backlog');\n setTags(data.tags || []);\n setComments(data.comments || []);\n setActivity(data.activity || []);\n setInitialQuestions(data.questions || []);\n setInitialAttachments(data.attachments || []);\n service.markTaskRead(taskId).catch(() => {});\n } catch {\n setError('Could not load task.');\n } finally {\n setLoading(false);\n }\n }, [service, taskId]);\n\n useEffect(() => {\n fetchTask();\n }, [fetchTask]);\n\n // Fetch peers for prev/next\n useEffect(() => {\n if (!task || !onNavigateToTask) return;\n let cancelled = false;\n (async () => {\n try {\n const data = await service.listTasks(task.project_slug, 200);\n if (cancelled) return;\n const ids: string[] = [];\n for (const col of columns) {\n const colData = data[col.key];\n if (colData && Array.isArray(colData.tasks)) {\n ids.push(...colData.tasks.map((t) => t.id));\n }\n }\n setProjectTaskIds(ids);\n } catch {\n // silent\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [task, columns, service, onNavigateToTask]);\n\n // Outside-click closes header menus\n useEffect(() => {\n const onClick = (e: MouseEvent) => {\n const target = e.target as Node;\n if (statusOpen && statusRef.current && !statusRef.current.contains(target)) setStatusOpen(false);\n if (priorityOpen && priorityRef.current && !priorityRef.current.contains(target)) setPriorityOpen(false);\n if (moreOpen && moreRef.current && !moreRef.current.contains(target)) setMoreOpen(false);\n if (tagsOpen && tagsRef.current && !tagsRef.current.contains(target)) setTagsOpen(false);\n };\n document.addEventListener('mousedown', onClick);\n return () => document.removeEventListener('mousedown', onClick);\n }, [statusOpen, priorityOpen, moreOpen, tagsOpen]);\n\n // ─── Hooks for sub-features ───\n\n const questions = useTaskQuestions(taskId, initialQuestions);\n const attachments = useTaskAttachments(taskId, initialAttachments);\n const highlight = useHighlightAnchor();\n\n // Open the panel automatically when the user starts an anchored thread.\n useEffect(() => {\n if (highlight.pendingAnchor && !panelOpen) {\n setPanelOpen(true);\n try {\n window.localStorage.setItem(PANEL_OPEN_KEY, 'true');\n } catch {\n // ignore\n }\n }\n }, [highlight.pendingAnchor, panelOpen]);\n\n // ─── Mutations ───\n\n const persist = useCallback(\n async (updates: Record<string, unknown>) => {\n setSaving(true);\n try {\n const updated = await service.updateTask(taskId, updates);\n setTask((prev) => (prev ? { ...prev, ...updated } : prev));\n } finally {\n setSaving(false);\n }\n },\n [service, taskId]\n );\n\n const handleTitleCommit = () => {\n setTitleEditing(false);\n if (task && title.trim() && title.trim() !== task.title) {\n persist({ title: title.trim() });\n } else if (task) {\n setTitle(task.title);\n }\n };\n\n const handleSectionChange = (section: SectionKey, val: string) => {\n const next = { ...description, [section]: val };\n setDescription(next);\n persist({ description: next });\n };\n\n const handleSectionStatusChange = (section: SectionKey, status: SectionStatus) => {\n const sectionStatus = { ...(description.section_status || {}), [section]: status };\n const next = { ...description, section_status: sectionStatus };\n setDescription(next);\n persist({ description: next });\n };\n\n const handleStatusChange = (s: string) => {\n setTaskStatus(s);\n setStatusOpen(false);\n persist({ status: s });\n // Refetch so we pick up the activity log entry the backend just wrote.\n setTimeout(() => fetchTask(), 500);\n };\n\n const handlePriorityChange = (p: string) => {\n setPriority(p);\n setPriorityOpen(false);\n persist({ priority: p });\n };\n\n const handleTagsCommit = () => {\n setTags([...pendingTags]);\n setTagsOpen(false);\n setShowOtherTagInput(false);\n persist({ tags: pendingTags });\n };\n\n const handleDelete = async () => {\n if (!task) return;\n if (!confirm(`Delete \"${task.title}\"? This cannot be undone.`)) return;\n try {\n await service.deleteTask(taskId);\n onDeleted?.(task);\n } catch {\n setError('Failed to delete task.');\n }\n };\n\n const handleShare = () => {\n if (!task) return;\n const defaultUrl = `${window.location.origin}/task-board/${taskId}${\n task.project_slug ? `?project=${task.project_slug}` : ''\n }`;\n const url = buildShareUrl ? buildShareUrl(task) : defaultUrl;\n navigator.clipboard.writeText(url).then(() => {\n setLinkCopied(true);\n setTimeout(() => setLinkCopied(false), 2000);\n });\n };\n\n const handleCreateThread = async ({\n title: titleLine,\n content,\n isInternal,\n anchor,\n attachmentIds,\n }: {\n title: string;\n content: string;\n isInternal: boolean;\n anchor: ThreadAnchor | null;\n attachmentIds: string[];\n }) => {\n try {\n const created = await service.addComment(taskId, {\n content,\n is_internal: isInternal,\n title: titleLine || null,\n anchor,\n attachment_ids: attachmentIds,\n });\n // Brief shimmer when a thread was posted without a manual title — mimics\n // an AI-generated title appearing.\n if (created.id && !titleLine) {\n setShimmeringThreadIds((prev) => new Set(prev).add(created.id));\n setTimeout(() => {\n setShimmeringThreadIds((prev) => {\n const next = new Set(prev);\n next.delete(created.id);\n return next;\n });\n }, 800);\n }\n highlight.clearPendingAnchor();\n await fetchTask();\n } catch {\n // silent\n }\n };\n\n const handleCreateReply = async (parentId: string, content: string, isInternal: boolean) => {\n try {\n await service.addComment(taskId, {\n content,\n is_internal: isInternal,\n parent_id: parentId,\n });\n await fetchTask();\n } catch {\n // silent\n }\n };\n\n const handleUpdateThread = async (\n threadId: string,\n body: { title?: string; thread_status?: ThreadStatus }\n ) => {\n try {\n await service.updateThread(taskId, threadId, body);\n await fetchTask();\n } catch {\n // silent\n }\n };\n\n // ─── Derived state ───\n\n const project = useMemo(() => {\n if (!task) return null;\n return projects.find((p) => p.slug === task.project_slug) ?? null;\n }, [task, projects]);\n\n const threads = useMemo(\n () => deriveThreads(comments, attachments.attachments),\n [comments, attachments.attachments]\n );\n\n const statusCol = columns.find((c) => c.key === taskStatus);\n const priorityStyle = getPriorityStyle(priority);\n\n const currentIdx = task ? projectTaskIds.indexOf(task.id) : -1;\n const prevId = currentIdx > 0 ? projectTaskIds[currentIdx - 1] : null;\n const nextId =\n currentIdx >= 0 && currentIdx < projectTaskIds.length - 1\n ? projectTaskIds[currentIdx + 1]\n : null;\n\n if (loading) {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-[#FAFAFA]\">\n <div className=\"text-sm text-neutral-400\">Loading task…</div>\n </div>\n );\n }\n\n if (!task) {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-[#FAFAFA]\">\n <div className=\"text-center\">\n <h1 className=\"text-2xl font-medium text-neutral-900 mb-2\">Task not found</h1>\n <p className=\"text-neutral-500\">{error || 'This task may have been deleted.'}</p>\n </div>\n </div>\n );\n }\n\n const initials = getInitials(task.created_by_name || task.created_by || '?');\n\n return (\n <div className=\"bg-white text-neutral-900\">\n {breadcrumb}\n\n <div\n className={`flex-1 px-6 lg:px-10 pt-6 pb-24 transition-[padding] duration-200 ${\n panelOpen ? 'xl:pr-[460px]' : 'xl:pr-[88px]'\n }`}\n >\n {/* Back row + prev/next */}\n <div className=\"flex items-center justify-between mb-6\">\n {onBack ? (\n <button\n onClick={onBack}\n className=\"flex items-center gap-2 text-neutral-500 hover:text-neutral-900 w-fit\"\n >\n <ArrowLeftIcon size={16} strokeWidth={1.5} />\n <span className=\"text-[13px] font-medium\">Back to Task Board</span>\n </button>\n ) : backHref ? (\n <a\n href={backHref}\n className=\"flex items-center gap-2 text-neutral-500 hover:text-neutral-900 w-fit\"\n >\n <ArrowLeftIcon size={16} strokeWidth={1.5} />\n <span className=\"text-[13px] font-medium\">Back to Task Board</span>\n </a>\n ) : (\n <span />\n )}\n {onNavigateToTask && (\n <div className=\"flex items-center gap-1 shrink-0\">\n <button\n onClick={() => prevId && onNavigateToTask(prevId, task.project_slug)}\n disabled={!prevId}\n className=\"inline-flex items-center justify-center w-9 h-9 rounded-xl border border-neutral-200 text-neutral-500 hover:text-neutral-900 hover:bg-neutral-50 hover:border-neutral-300 disabled:opacity-40 disabled:hover:bg-white disabled:hover:text-neutral-500\"\n title=\"Previous task\"\n >\n <ChevronLeftIcon size={16} strokeWidth={1.5} />\n </button>\n <button\n onClick={() => nextId && onNavigateToTask(nextId, task.project_slug)}\n disabled={!nextId}\n className=\"inline-flex items-center justify-center w-9 h-9 rounded-xl border border-neutral-200 text-neutral-500 hover:text-neutral-900 hover:bg-neutral-50 hover:border-neutral-300 disabled:opacity-40 disabled:hover:bg-white disabled:hover:text-neutral-500\"\n title=\"Next task\"\n >\n <ChevronRightIcon size={16} strokeWidth={1.5} />\n </button>\n </div>\n )}\n </div>\n\n {/* Task ID chip + project */}\n <div className=\"mb-3 flex items-center gap-2 flex-wrap\">\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[12px] font-medium bg-neutral-50 text-neutral-700 border border-neutral-200\">\n <span className=\"font-mono\">{formatTaskId(task.id)}</span>\n </span>\n {project && (\n <>\n <span className=\"text-[12px] text-neutral-400\">in</span>\n <span className=\"text-[12px] text-[#FF5E00] hover:text-[#E05200] font-medium\">\n {project.name}\n </span>\n </>\n )}\n </div>\n\n {/* Title row + actions */}\n <div className=\"flex gap-6 items-start mb-4\">\n <div className=\"flex-1 min-w-0\">\n {titleEditing ? (\n <input\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n onBlur={handleTitleCommit}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleTitleCommit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setTitle(task.title);\n setTitleEditing(false);\n }\n }}\n autoFocus\n className=\"w-full text-[20px] font-semibold text-neutral-900 tracking-tight leading-snug bg-transparent border-b-2 border-[#FF5E00] focus:outline-none px-1 -mx-1\"\n />\n ) : (\n <h1\n onClick={() => setTitleEditing(true)}\n className=\"text-[20px] font-semibold text-neutral-900 tracking-tight leading-snug cursor-text rounded px-1 -mx-1 hover:bg-neutral-50/60\"\n title=\"Click to edit\"\n >\n {title || 'Untitled task'}\n </h1>\n )}\n\n {/* Metadata strip */}\n <div className=\"mt-3 flex items-center gap-3 flex-wrap text-[12px] text-neutral-500\">\n <span>\n Created <span className=\"font-medium text-neutral-700\">{formatDate(task.created_at)}</span>\n </span>\n <span className=\"text-neutral-300\">·</span>\n <span>\n Updated{' '}\n <span className=\"font-medium text-neutral-700\">\n {task.updated_at ? formatDate(task.updated_at) : '—'}\n </span>\n </span>\n <span className=\"text-neutral-300\">·</span>\n <span className=\"inline-flex items-center gap-1.5\">\n Creator\n <span className=\"w-4 h-4 rounded-full bg-[#FF5E00] text-white inline-flex items-center justify-center text-[9px] font-semibold\">\n {initials}\n </span>\n <span className=\"font-medium text-neutral-700\">\n {task.created_by_name || task.created_by}\n </span>\n </span>\n <span className=\"text-neutral-300\">·</span>\n <div className=\"inline-flex items-center gap-1.5 relative\" ref={tagsRef}>\n <span>Tags</span>\n {tags.map((tag) => {\n const style = getTagStyle(tag);\n return (\n <span\n key={tag}\n className={`inline-flex items-center px-1.5 py-px text-[10px] font-medium rounded border ${style.className}`}\n >\n {style.label}\n </span>\n );\n })}\n <button\n onClick={() => {\n if (!tagsOpen) setPendingTags([...tags]);\n setTagsOpen(!tagsOpen);\n }}\n className=\"inline-flex items-center gap-1 px-1.5 py-0.5 rounded border border-dashed border-neutral-300 text-neutral-400 hover:text-neutral-700 hover:border-neutral-400 text-[10px]\"\n >\n <PlusIcon size={10} strokeWidth={2} />\n Edit\n </button>\n {tagsOpen && (\n <div className=\"absolute top-full left-0 mt-1 bg-white border border-neutral-200 rounded-lg shadow-lg z-30 w-56\">\n <div className=\"py-1\">\n {predefinedTags.map((tag) => {\n const isSelected = pendingTags.includes(tag.value);\n return (\n <button\n key={tag.value}\n onClick={() => {\n setPendingTags((prev) =>\n isSelected ? prev.filter((t) => t !== tag.value) : [...prev, tag.value]\n );\n }}\n className={`w-full text-left px-3 py-1.5 text-[12px] hover:bg-neutral-50 flex items-center justify-between ${\n isSelected ? 'bg-neutral-50' : ''\n }`}\n >\n <span\n className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${tag.className}`}\n >\n {tag.label}\n </span>\n {isSelected && (\n <CheckIcon size={12} strokeWidth={2.5} className=\"text-[#FF5E00]\" />\n )}\n </button>\n );\n })}\n {pendingTags\n .filter((t) => !predefinedTags.some((p) => p.value === t))\n .map((tag) => (\n <div\n key={tag}\n className=\"w-full text-left px-3 py-1.5 text-[12px] bg-neutral-50 flex items-center justify-between\"\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 {tag}\n </span>\n <button\n onClick={() => setPendingTags((prev) => prev.filter((t) => t !== tag))}\n className=\"text-neutral-400 hover:text-neutral-600\"\n >\n <XIcon size={12} strokeWidth={2} />\n </button>\n </div>\n ))}\n {!showOtherTagInput ? (\n <button\n onClick={() => setShowOtherTagInput(true)}\n className=\"w-full text-left px-3 py-1.5 text-[12px] hover:bg-neutral-50 flex items-center justify-between\"\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 </button>\n ) : (\n <div className=\"px-3 py-2 bg-neutral-50/50\">\n <input\n type=\"text\"\n autoFocus\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n const val = e.currentTarget.value\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-');\n if (val && !pendingTags.includes(val)) {\n setPendingTags((prev) => [...prev, val]);\n }\n e.currentTarget.value = '';\n setShowOtherTagInput(false);\n }\n if (e.key === 'Escape') {\n setShowOtherTagInput(false);\n }\n }}\n className=\"w-full px-2 py-1.5 text-[12px] border border-neutral-200 rounded-md focus:outline-none focus:ring-1 focus:ring-[#FF5E00]/20 focus:border-[#FF5E00]/50\"\n placeholder=\"Type a custom tag...\"\n />\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\n onClick={() => {\n setPendingTags([...tags]);\n setTagsOpen(false);\n setShowOtherTagInput(false);\n }}\n className=\"px-2.5 py-1 text-[11px] font-medium text-neutral-500 hover:text-neutral-700\"\n >\n Cancel\n </button>\n <button\n onClick={handleTagsCommit}\n className=\"px-3 py-1 text-[11px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded\"\n >\n Save\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Right action cluster */}\n <div className=\"flex items-center gap-2 shrink-0\">\n {saving && <span className=\"text-[11px] text-neutral-400 mr-1\">Saving...</span>}\n\n {/* Status */}\n <div className=\"relative\" ref={statusRef}>\n <button\n onClick={() => {\n setStatusOpen(!statusOpen);\n setPriorityOpen(false);\n setMoreOpen(false);\n }}\n className=\"inline-flex items-center gap-2 h-10 px-3 rounded-xl border border-neutral-200 bg-white text-[12px] font-medium text-neutral-700 hover:text-neutral-900 hover:border-neutral-300\"\n >\n <span className={`w-2 h-2 rounded-full ${statusCol?.color ?? 'bg-neutral-400'}`} />\n <span>{statusCol?.label ?? taskStatus}</span>\n <ChevronDownIcon size={12} strokeWidth={1.5} className=\"text-neutral-400\" />\n </button>\n {statusOpen && (\n <div className=\"absolute right-0 top-full mt-1 w-52 bg-white border border-neutral-200 rounded-xl shadow-lg py-1 z-40\">\n {columns.map((col) => (\n <button\n key={col.key}\n onClick={() => handleStatusChange(col.key)}\n className={`w-full text-left px-3 py-2 text-[12px] text-neutral-700 hover:bg-neutral-50 flex items-center gap-2 ${\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\n {/* Priority */}\n <div className=\"relative\" ref={priorityRef}>\n <button\n onClick={() => {\n setPriorityOpen(!priorityOpen);\n setStatusOpen(false);\n setMoreOpen(false);\n }}\n className={`inline-flex items-center gap-2 h-10 px-3 rounded-xl border text-[12px] font-medium transition-colors ${priorityStyle.className}`}\n >\n <span>{priorityStyle.label}</span>\n <ChevronDownIcon size={12} strokeWidth={1.5} className=\"opacity-50\" />\n </button>\n {priorityOpen && (\n <div className=\"absolute right-0 top-full mt-1 w-44 bg-white border border-neutral-200 rounded-xl shadow-lg py-1 z-40\">\n {priorities.map((p) => (\n <button\n key={p.value}\n onClick={() => handlePriorityChange(p.value)}\n className={`w-full text-left px-3 py-2 text-[12px] hover:bg-neutral-50 flex items-center gap-2 ${\n priority === p.value ? 'bg-neutral-50' : ''\n }`}\n >\n <span\n className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded border ${p.className}`}\n >\n {p.label}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* More */}\n <div className=\"relative\" ref={moreRef}>\n <button\n onClick={() => {\n setMoreOpen(!moreOpen);\n setStatusOpen(false);\n setPriorityOpen(false);\n }}\n className=\"w-10 h-10 flex items-center justify-center rounded-xl border border-neutral-200 bg-white text-neutral-500 hover:text-neutral-900 hover:border-neutral-300\"\n aria-label=\"More actions\"\n >\n <MoreVerticalIcon size={16} strokeWidth={1.5} />\n </button>\n {moreOpen && (\n <div className=\"absolute right-0 top-full mt-1 w-40 bg-white border border-neutral-200 rounded-xl shadow-lg py-1 z-40\">\n <button\n onClick={() => {\n setMoreOpen(false);\n handleShare();\n }}\n className=\"w-full text-left px-3 py-2 text-[12px] text-neutral-700 hover:bg-neutral-50 flex items-center gap-2.5\"\n >\n <Share2Icon size={14} strokeWidth={1.5} className=\"text-neutral-400\" />\n {linkCopied ? 'Copied!' : 'Share'}\n </button>\n <button\n onClick={() => {\n setMoreOpen(false);\n handleDelete();\n }}\n className=\"w-full text-left px-3 py-2 text-[12px] text-red-600 hover:bg-red-50 flex items-center gap-2.5\"\n >\n <TrashIcon size={14} strokeWidth={1.5} />\n Delete\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Description sections + questions + attachments */}\n <div className=\"flex flex-col gap-10 mt-10\">\n {DESCRIPTION_SECTIONS.map((section) => {\n const status: SectionStatus =\n description.section_status?.[section.key] === 'approved' ? 'approved' : 'draft';\n return (\n <DescriptionSection\n key={section.key}\n sectionKey={section.key}\n label={section.label}\n placeholder={section.placeholder ?? ''}\n value={description[section.key] || ''}\n onChange={(v) => handleSectionChange(section.key, v)}\n status={status}\n onStatusChange={(s) => handleSectionStatusChange(section.key, s)}\n saving={saving}\n />\n );\n })}\n\n <OutstandingQuestionsSection\n questions={questions.questions}\n currentUsername={user.username}\n onCreate={questions.createQuestion}\n onSetStatus={questions.setStatus}\n onDelete={questions.deleteQuestion}\n onAddReply={questions.addReply}\n />\n\n <AttachmentsSection\n attachments={attachments.attachments}\n onUpload={attachments.uploadFile}\n onAddLink={(url, name) => attachments.addLink({ url, name })}\n onDelete={attachments.remove}\n />\n </div>\n </div>\n\n <ThreadsPanel\n threads={threads}\n activity={activity}\n attachments={attachments.attachments}\n open={panelOpen}\n onToggle={togglePanel}\n openThreadId={openThreadId}\n onOpenThread={setOpenThreadId}\n pendingAnchor={highlight.pendingAnchor}\n onClearAnchor={highlight.clearPendingAnchor}\n onAnchorClick={highlight.focusAnchor}\n shimmeringThreadIds={shimmeringThreadIds}\n isInternalUser={!!user.is_internal}\n onCreateThread={handleCreateThread}\n onCreateReply={handleCreateReply}\n onUpdateThread={handleUpdateThread}\n onUploadAttachment={attachments.uploadFile}\n onAddLinkAttachment={(url, name) => attachments.addLink({ url, name })}\n />\n\n <HighlightBubble bubble={highlight.bubble} onComment={highlight.beginAnchoredThread} />\n </div>\n );\n}\n","import type { Attachment, Comment, SectionKey, ThreadAnchor, ThreadStatus } from '../types';\nimport { DESCRIPTION_SECTIONS } from './constants';\nimport { formatDate, parseDate } from './helpers';\n\n/**\n * UI shape derived from Comment + Attachment data. A `Thread` is a top-level\n * comment (no `parent_id`) augmented with metadata, replies, and resolved\n * attachment objects (looked up by id).\n */\nexport interface Thread {\n id: string;\n title: string;\n /** True when title was derived from content rather than persisted on the row. */\n titleDerived: boolean;\n preview: string;\n author_id: string;\n author_name: string;\n created_at: string;\n is_internal: boolean;\n status: ThreadStatus;\n /** Original mention-tagged text, used when rendering the message. */\n rawContent: string;\n anchor?: ThreadAnchor | null;\n attachments: Attachment[];\n replies: ThreadReply[];\n}\n\nexport interface ThreadReply {\n id: string;\n author_id: string;\n author_name: string;\n content: string;\n created_at: string;\n is_internal: boolean;\n}\n\n/** Group a flat comments list into threads (top-level + replies + resolved attachments). */\nexport function deriveThreads(comments: Comment[], attachments: Attachment[]): Thread[] {\n const attachById = new Map(attachments.map((a) => [a.id, a]));\n const topLevel = comments.filter((c) => !c.parent_id);\n const repliesByParent = new Map<string, Comment[]>();\n for (const c of comments) {\n if (c.parent_id) {\n const arr = repliesByParent.get(c.parent_id) || [];\n arr.push(c);\n repliesByParent.set(c.parent_id, arr);\n }\n }\n return topLevel.map((c) => {\n const stripped = c.content.replace(/@\\[(.*?)\\]\\(.*?\\)/g, '@$1');\n const lines = stripped.split(/\\r?\\n/).filter((l) => l.trim());\n let title = (c.title || '').trim();\n let titleDerived = false;\n if (!title) {\n const firstLine = lines[0] || '';\n title = firstLine.length > 80 ? firstLine.slice(0, 80) + '…' : firstLine;\n if (!title) title = 'Comment';\n titleDerived = true;\n }\n const preview = lines.join(' ').slice(0, 200);\n const replies: ThreadReply[] = (repliesByParent.get(c.id) || [])\n .sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime())\n .map((r) => ({\n id: r.id,\n author_id: r.author_id,\n author_name: r.author_name,\n content: r.content,\n created_at: r.created_at,\n is_internal: !!r.is_internal,\n }));\n const threadAttachments: Attachment[] = (c.attachment_ids || [])\n .map((aid) => attachById.get(aid))\n .filter((a): a is Attachment => Boolean(a));\n return {\n id: c.id,\n title,\n titleDerived,\n preview,\n author_id: c.author_id,\n author_name: c.author_name,\n created_at: c.created_at,\n is_internal: !!c.is_internal,\n status: c.thread_status === 'complete' ? 'complete' : 'active',\n rawContent: c.content,\n anchor: c.anchor || null,\n attachments: threadAttachments,\n replies,\n };\n });\n}\n\n/** Display label for a description section key, falling back to the key itself. */\nexport function sectionLabel(key: SectionKey): string {\n return DESCRIPTION_SECTIONS.find((s) => s.key === key)?.label || key;\n}\n\n/** Compact relative time like \"5m ago\", \"3h ago\", \"2d ago\", or a short date. */\nexport function timeAgo(dateStr: string): string {\n const d = parseDate(dateStr);\n const diff = Date.now() - d.getTime();\n const minutes = Math.floor(diff / 60000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n if (days < 30) return `${days}d ago`;\n return formatDate(dateStr);\n}\n","import React, { useState } from 'react';\nimport type { SectionKey, SectionStatus } from '../types';\nimport { HelpCircleIcon } from '../icons';\nimport { MarkdownView } from './MarkdownView';\nimport { MarkdownEditor } from './MarkdownEditor';\n\nexport interface DescriptionSectionProps {\n sectionKey: SectionKey;\n label: string;\n placeholder: string;\n /** Markdown content. */\n value: string;\n /** Called with the new markdown when the user commits an edit. */\n onChange: (next: string) => void;\n /** Current Draft/Approved status; defaults to \"draft\" when omitted. */\n status: SectionStatus;\n /** Toggle Draft ↔ Approved. */\n onStatusChange: (next: SectionStatus) => void;\n /** Optional saving indicator passed through to the editor. */\n saving?: boolean;\n}\n\n/**\n * One free-text description section (Problem / User Story / etc.) with:\n * - segmented Draft/Approved toggle and hover-card explanations\n * - read-mode `MarkdownView`\n * - click-to-focus WYSIWYG `MarkdownEditor`\n * - `data-section={sectionKey}` so highlight-to-comment can anchor here\n */\nexport function DescriptionSection({\n sectionKey,\n label,\n placeholder,\n value,\n onChange,\n status,\n onStatusChange,\n saving,\n}: DescriptionSectionProps) {\n const [editing, setEditing] = useState(false);\n const [openHelp, setOpenHelp] = useState<null | SectionStatus>(null);\n\n const startEdit = () => setEditing(true);\n const cancel = () => setEditing(false);\n const handleCommit = (md: string) => {\n if (md !== value) onChange(md);\n setEditing(false);\n };\n\n const hasContent = value.trim().length > 0;\n\n return (\n <section className=\"group\" data-section={sectionKey}>\n <div className=\"flex items-center justify-between gap-3 mb-3\">\n <h2 className=\"text-[15px] font-semibold text-neutral-900 tracking-tight\">{label}</h2>\n\n {/* Draft / Approved segmented toggle */}\n <div\n className=\"flex rounded-2xl border border-neutral-200/60 bg-neutral-100/80 p-0.5 items-center h-7 shrink-0\"\n role=\"group\"\n aria-label={`${label} status`}\n >\n {(['draft', 'approved'] as SectionStatus[]).map((s) => {\n const active = status === s;\n const labelText = s === 'draft' ? 'Draft' : 'Approved';\n const help =\n s === 'draft'\n ? 'Draft — content is being written and is not yet ready for review.'\n : 'Approved — content has been reviewed and signed off (e.g. by the client).';\n return (\n <button\n key={s}\n type=\"button\"\n onClick={() => onStatusChange(s)}\n aria-pressed={active}\n className={`inline-flex items-center justify-center gap-1.5 rounded-xl px-3 h-6 text-[12px] font-medium transition-all ${\n active\n ? 'bg-[#FF5E00] text-white shadow-sm'\n : 'text-neutral-500 hover:text-neutral-900'\n }`}\n >\n {labelText}\n <span\n className=\"relative inline-flex items-center\"\n onMouseEnter={() => setOpenHelp(s)}\n onMouseLeave={() => setOpenHelp(null)}\n onClick={(e) => e.stopPropagation()}\n >\n <HelpCircleIcon className=\"w-3 h-3 opacity-70\" strokeWidth={1.5} />\n {openHelp === s && (\n <span className=\"absolute right-0 top-full mt-2 z-50 pointer-events-none\">\n <span className=\"block bg-white border border-neutral-200 shadow-lg rounded-xl px-3.5 py-2.5 text-[12px] font-medium text-neutral-700 whitespace-normal w-60 text-left\">\n {help}\n </span>\n </span>\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n\n {editing ? (\n <MarkdownEditor\n value={value}\n onCommit={handleCommit}\n onCancel={cancel}\n placeholder={placeholder}\n saving={saving}\n />\n ) : (\n <button\n type=\"button\"\n onClick={startEdit}\n className=\"w-full text-left rounded-lg border border-transparent hover:border-neutral-200 hover:bg-neutral-50/60 transition-colors px-3.5 py-2.5 -mx-3.5 -my-2.5 cursor-text\"\n >\n {hasContent ? (\n <MarkdownView content={value} className=\"text-[13px]\" />\n ) : (\n <p className=\"text-[13px] text-neutral-400 italic\">{placeholder}</p>\n )}\n </button>\n )}\n </section>\n );\n}\n","import React from 'react';\n\n/**\n * Lightweight read-mode markdown renderer for description sections, thread\n * messages, and other static markdown content. Supports H1/H2/H3, bullet lists,\n * numbered lists, blockquotes, task lists (`- [ ] foo`), inline bold (`**`),\n * inline code, and `@[Name](username)` mentions rendered as styled pills.\n *\n * For editing, use `MarkdownEditor` (WYSIWYG, contenteditable).\n */\nexport function MarkdownView({ content, className = \"\" }: { content: string; className?: string }) {\n if (!content?.trim()) return null;\n\n const renderInline = (text: string, keyBase: string): React.ReactNode[] => {\n const out: React.ReactNode[] = [];\n const parts = text.split(/(@\\[.*?\\]\\(.*?\\))/g);\n let k = 0;\n for (const part of parts) {\n const m = part.match(/^@\\[(.*?)\\]\\((.*?)\\)$/);\n if (m) {\n out.push(\n <span\n key={`${keyBase}-m${k++}`}\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={`@${m[2]}`}\n >\n @{m[1]}\n </span>\n );\n continue;\n }\n const segs = part.split(/(\\*\\*.*?\\*\\*|`[^`]+`)/g);\n for (const seg of segs) {\n if (!seg) continue;\n const bold = seg.match(/^\\*\\*(.+?)\\*\\*$/);\n const code = seg.match(/^`(.+?)`$/);\n if (bold) {\n out.push(\n <strong key={`${keyBase}-b${k++}`} className=\"font-semibold text-neutral-900\">\n {bold[1]}\n </strong>\n );\n } else if (code) {\n out.push(\n <code\n key={`${keyBase}-c${k++}`}\n className=\"px-1 py-px rounded bg-neutral-100 text-neutral-800 text-[12px] font-mono\"\n >\n {code[1]}\n </code>\n );\n } else {\n out.push(<React.Fragment key={`${keyBase}-t${k++}`}>{seg}</React.Fragment>);\n }\n }\n }\n return out;\n };\n\n const lines = content.split(/\\r?\\n/);\n const blocks: React.ReactNode[] = [];\n let i = 0;\n let blockKey = 0;\n\n while (i < lines.length) {\n const raw = lines[i];\n const line = raw.trimEnd();\n const trimmed = line.trim();\n\n if (!trimmed) {\n i++;\n continue;\n }\n\n // Headings\n if (/^### /.test(trimmed)) {\n blocks.push(\n <h3 key={blockKey++} className=\"text-[15px] font-semibold text-neutral-900 mt-3 mb-1.5\">\n {renderInline(trimmed.replace(/^### /, \"\"), `b${blockKey}`)}\n </h3>\n );\n i++;\n continue;\n }\n if (/^## /.test(trimmed)) {\n blocks.push(\n <h3 key={blockKey++} className=\"text-base font-semibold text-neutral-900 mt-4 mb-1.5\">\n {renderInline(trimmed.replace(/^## /, \"\"), `b${blockKey}`)}\n </h3>\n );\n i++;\n continue;\n }\n if (/^# /.test(trimmed)) {\n blocks.push(\n <h2 key={blockKey++} className=\"text-lg font-semibold text-neutral-900 mt-4 mb-2\">\n {renderInline(trimmed.replace(/^# /, \"\"), `b${blockKey}`)}\n </h2>\n );\n i++;\n continue;\n }\n\n // Blockquote\n if (/^> /.test(trimmed)) {\n const quoteLines: string[] = [];\n while (i < lines.length && /^> /.test(lines[i].trim())) {\n quoteLines.push(lines[i].trim().replace(/^> /, \"\"));\n i++;\n }\n blocks.push(\n <blockquote\n key={blockKey++}\n className=\"border-l-2 border-neutral-200 pl-3 my-2 text-neutral-600 italic\"\n >\n {quoteLines.map((q, j) => (\n <p key={j}>{renderInline(q, `bq${blockKey}-${j}`)}</p>\n ))}\n </blockquote>\n );\n continue;\n }\n\n // Task list\n if (/^[-*] \\[[ xX]\\] /.test(trimmed)) {\n const taskItems: { checked: boolean; text: string }[] = [];\n while (i < lines.length && /^[-*] \\[[ xX]\\] /.test(lines[i].trim())) {\n const m = lines[i].trim().match(/^[-*] \\[([ xX])\\] (.*)$/);\n if (!m) break;\n taskItems.push({ checked: m[1].toLowerCase() === \"x\", text: m[2] });\n i++;\n }\n blocks.push(\n <ul key={blockKey++} className=\"my-1.5 space-y-1\">\n {taskItems.map((t, j) => (\n <li key={j} className=\"flex items-start gap-2\">\n <input\n type=\"checkbox\"\n checked={t.checked}\n readOnly\n className=\"mt-1 accent-[#FF5E00]\"\n />\n <span className={t.checked ? \"line-through text-neutral-400\" : \"text-neutral-700\"}>\n {renderInline(t.text, `t${blockKey}-${j}`)}\n </span>\n </li>\n ))}\n </ul>\n );\n continue;\n }\n\n // Bullet list\n if (/^[-*] /.test(trimmed)) {\n const items: string[] = [];\n while (i < lines.length && /^[-*] /.test(lines[i].trim())) {\n items.push(lines[i].trim().replace(/^[-*] /, \"\"));\n i++;\n }\n blocks.push(\n <ul key={blockKey++} className=\"list-disc pl-5 my-1.5 space-y-0.5\">\n {items.map((it, j) => (\n <li key={j} className=\"text-neutral-700 leading-relaxed\">\n {renderInline(it, `u${blockKey}-${j}`)}\n </li>\n ))}\n </ul>\n );\n continue;\n }\n\n // Numbered list\n if (/^\\d+\\. /.test(trimmed)) {\n const items: string[] = [];\n while (i < lines.length && /^\\d+\\. /.test(lines[i].trim())) {\n items.push(lines[i].trim().replace(/^\\d+\\. /, \"\"));\n i++;\n }\n blocks.push(\n <ol key={blockKey++} className=\"list-decimal pl-5 my-1.5 space-y-0.5\">\n {items.map((it, j) => (\n <li key={j} className=\"text-neutral-700 leading-relaxed\">\n {renderInline(it, `o${blockKey}-${j}`)}\n </li>\n ))}\n </ol>\n );\n continue;\n }\n\n // Paragraph (collect consecutive non-blank lines)\n const paraLines: string[] = [trimmed];\n i++;\n while (\n i < lines.length &&\n lines[i].trim() &&\n !/^(#{1,3} |> |[-*] (\\[[ xX]\\] )?|\\d+\\. )/.test(lines[i].trim())\n ) {\n paraLines.push(lines[i].trim());\n i++;\n }\n blocks.push(\n <p key={blockKey++} className=\"text-neutral-700 leading-relaxed my-1.5\">\n {renderInline(paraLines.join(\" \"), `p${blockKey}`)}\n </p>\n );\n }\n\n return <div className={className}>{blocks}</div>;\n}\n","import React, { useEffect, useRef } from 'react';\nimport { Bold, Italic, List, ListOrdered, Heading2, Quote, Code } from '../icons';\nimport { mdToHtml, htmlToMd } from '../utils/markdown';\n\ninterface ToolbarBtnProps {\n icon: React.ComponentType<{ className?: string; strokeWidth?: number }>;\n title: string;\n onClick: () => void;\n}\n\n/**\n * A toolbar button that does NOT blur the editor on click.\n *\n * Bug #1 fix: the editor commits on blur. Without `onMouseDown.preventDefault`,\n * clicking any toolbar button would blur the editor first and the click handler\n * would never run against a live selection. preventDefault on mousedown keeps\n * focus inside the contenteditable.\n */\nfunction ToolbarBtn({ icon: IconC, title, onClick }: ToolbarBtnProps) {\n return (\n <button\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n title={title}\n className=\"w-7 h-7 inline-flex items-center justify-center rounded hover:bg-neutral-100 text-neutral-500 hover:text-neutral-900 transition-colors\"\n >\n <IconC className=\"w-4 h-4\" strokeWidth={1.5} />\n </button>\n );\n}\n\nexport interface MarkdownEditorProps {\n /** Markdown content. Used once on mount; the contenteditable owns state from then on. */\n value: string;\n /** Called with the canonical markdown when the user blurs the editor. */\n onCommit: (md: string) => void;\n /** Called when the user presses Escape. */\n onCancel: () => void;\n /** Placeholder shown when the editor is empty. */\n placeholder: string;\n /** Optional saving indicator. */\n saving?: boolean;\n}\n\n/**\n * WYSIWYG markdown editor. Uses a contenteditable div with execCommand\n * formatting so users never see raw `**` / `- ` / `# ` syntax. Storage\n * format remains markdown via `mdToHtml`/`htmlToMd` round-trip helpers,\n * so existing readers (`MarkdownView`, server-side previews) keep working.\n *\n * Pair with the CSS in `task-board.css` (`.eb-tb-markdown-editor`).\n */\nexport function MarkdownEditor({ value, onCommit, onCancel, placeholder, saving }: MarkdownEditorProps) {\n const editorRef = useRef<HTMLDivElement>(null);\n\n // Set HTML once on mount; afterwards the contenteditable owns state.\n useEffect(() => {\n if (editorRef.current) {\n editorRef.current.innerHTML = mdToHtml(value);\n editorRef.current.focus();\n const range = document.createRange();\n range.selectNodeContents(editorRef.current);\n range.collapse(false);\n const sel = window.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const focusEditor = () => editorRef.current?.focus();\n\n const exec = (command: string, arg?: string) => {\n focusEditor();\n document.execCommand(command, false, arg);\n };\n\n /**\n * Wrap the current selection in a `<code>` element. execCommand has no\n * built-in for this, so we do it manually.\n */\n const wrapSelectionInCode = () => {\n focusEditor();\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n if (range.collapsed) return;\n const codeEl = document.createElement('code');\n try {\n codeEl.textContent = range.toString();\n range.deleteContents();\n range.insertNode(codeEl);\n range.setStartAfter(codeEl);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n } catch {\n // ignore\n }\n };\n\n const commit = () => {\n if (!editorRef.current) return;\n onCommit(htmlToMd(editorRef.current.innerHTML));\n };\n\n return (\n <div>\n <div className=\"flex items-center gap-0.5 bg-neutral-50/60 border border-neutral-200 rounded-md p-0.5 mb-2 w-fit\">\n <ToolbarBtn icon={Heading2} title=\"Heading\" onClick={() => exec('formatBlock', 'h2')} />\n <ToolbarBtn icon={Bold} title=\"Bold\" onClick={() => exec('bold')} />\n <ToolbarBtn icon={Italic} title=\"Italic\" onClick={() => exec('italic')} />\n <span className=\"w-px h-5 bg-neutral-200 mx-0.5\" />\n <ToolbarBtn icon={List} title=\"Bullet list\" onClick={() => exec('insertUnorderedList')} />\n <ToolbarBtn icon={ListOrdered} title=\"Numbered list\" onClick={() => exec('insertOrderedList')} />\n <span className=\"w-px h-5 bg-neutral-200 mx-0.5\" />\n <ToolbarBtn icon={Quote} title=\"Quote\" onClick={() => exec('formatBlock', 'blockquote')} />\n <ToolbarBtn icon={Code} title=\"Inline code\" onClick={wrapSelectionInCode} />\n </div>\n <div\n ref={editorRef}\n contentEditable\n suppressContentEditableWarning\n data-placeholder={placeholder}\n onBlur={commit}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onCancel();\n }\n }}\n className=\"eb-tb-markdown-editor w-full px-3.5 py-2.5 bg-white border border-neutral-200 rounded-lg text-[13px] leading-relaxed text-neutral-800 focus:outline-none focus:ring-2 focus:ring-[#FF5E00]/10 focus:border-[#FF5E00]/50 transition-all min-h-[80px]\"\n />\n <p className=\"mt-1.5 text-[11px] text-neutral-400\">\n <kbd className=\"px-1 py-0.5 rounded bg-neutral-100 border border-neutral-200 text-[10px]\">Esc</kbd>{' '}\n to cancel · click outside to save\n {saving && <span className=\"ml-2\">· Saving...</span>}\n </p>\n </div>\n );\n}\n","/**\n * Markdown ⇄ HTML round-trip helpers used by the WYSIWYG `MarkdownEditor`.\n *\n * Storage format: markdown (so existing readers, the backend, and previews\n * keep working). Editing format: HTML in a contenteditable div, so users\n * never see raw `**` / `- ` / `# ` syntax.\n *\n * Mentions stored as `@[Name](username)` round-trip through the\n * `<span class=\"mention-pill\" data-mention-username=\"...\">@Name</span>`\n * representation.\n */\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction inlineMdToHtml(text: string): string {\n // Split on mention markup so we can HTML-escape user text without escaping\n // our own injected mention spans.\n const tokens = text.split(/(@\\[.*?\\]\\([^)]*?\\))/g);\n return tokens\n .map((tok) => {\n const m = tok.match(/^@\\[(.*?)\\]\\(([^)]*?)\\)$/);\n if (m) {\n return `<span class=\"mention-pill\" data-mention-username=\"${escapeHtml(m[2])}\">@${escapeHtml(m[1])}</span>`;\n }\n let s = escapeHtml(tok);\n s = s.replace(/`([^`]+)`/g, \"<code>$1</code>\");\n s = s.replace(/\\*\\*(.+?)\\*\\*/g, \"<strong>$1</strong>\");\n // `*x*` italic but not part of `**bold**`. Applied line-by-line.\n s = s.replace(/(^|[^*])\\*([^*\\n]+?)\\*(?!\\*)/g, \"$1<em>$2</em>\");\n return s;\n })\n .join(\"\");\n}\n\nexport function mdToHtml(md: string): string {\n if (!md.trim()) return \"\";\n const lines = md.split(/\\r?\\n/);\n const out: string[] = [];\n let i = 0;\n while (i < lines.length) {\n const trimmed = lines[i].trim();\n if (!trimmed) {\n i++;\n continue;\n }\n if (/^### /.test(trimmed)) {\n out.push(`<h3>${inlineMdToHtml(trimmed.slice(4))}</h3>`);\n i++;\n continue;\n }\n if (/^## /.test(trimmed)) {\n out.push(`<h2>${inlineMdToHtml(trimmed.slice(3))}</h2>`);\n i++;\n continue;\n }\n if (/^# /.test(trimmed)) {\n out.push(`<h1>${inlineMdToHtml(trimmed.slice(2))}</h1>`);\n i++;\n continue;\n }\n if (/^[-*] /.test(trimmed)) {\n out.push(\"<ul>\");\n while (i < lines.length && /^[-*] /.test(lines[i].trim())) {\n const text = lines[i].trim().replace(/^[-*] /, \"\");\n out.push(`<li>${inlineMdToHtml(text)}</li>`);\n i++;\n }\n out.push(\"</ul>\");\n continue;\n }\n if (/^\\d+\\. /.test(trimmed)) {\n out.push(\"<ol>\");\n while (i < lines.length && /^\\d+\\. /.test(lines[i].trim())) {\n const text = lines[i].trim().replace(/^\\d+\\. /, \"\");\n out.push(`<li>${inlineMdToHtml(text)}</li>`);\n i++;\n }\n out.push(\"</ol>\");\n continue;\n }\n if (/^> /.test(trimmed)) {\n out.push(\"<blockquote>\");\n while (i < lines.length && /^> /.test(lines[i].trim())) {\n out.push(`<p>${inlineMdToHtml(lines[i].trim().slice(2))}</p>`);\n i++;\n }\n out.push(\"</blockquote>\");\n continue;\n }\n // Paragraph\n const paraLines: string[] = [trimmed];\n i++;\n while (\n i < lines.length &&\n lines[i].trim() &&\n !/^(#{1,3} |> |[-*] |\\d+\\. )/.test(lines[i].trim())\n ) {\n paraLines.push(lines[i].trim());\n i++;\n }\n out.push(`<p>${inlineMdToHtml(paraLines.join(\" \"))}</p>`);\n }\n return out.join(\"\");\n}\n\nfunction inlineHtmlToMd(node: Node): string {\n let out = \"\";\n for (const child of Array.from(node.childNodes)) {\n if (child.nodeType === Node.TEXT_NODE) {\n out += child.textContent || \"\";\n continue;\n }\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\n const el = child as HTMLElement;\n const tag = el.tagName.toLowerCase();\n if (tag === \"br\") {\n out += \"\\n\";\n } else if (tag === \"strong\" || tag === \"b\") {\n out += \"**\" + inlineHtmlToMd(el) + \"**\";\n } else if (tag === \"em\" || tag === \"i\") {\n out += \"*\" + inlineHtmlToMd(el) + \"*\";\n } else if (tag === \"code\") {\n out += \"`\" + (el.textContent || \"\") + \"`\";\n } else if (tag === \"span\" && el.classList.contains(\"mention-pill\")) {\n const username = el.dataset.mentionUsername || \"\";\n const name = (el.textContent || \"\").replace(/^@/, \"\");\n out += `@[${name}](${username})`;\n } else {\n out += inlineHtmlToMd(el);\n }\n }\n return out;\n}\n\nexport function htmlToMd(html: string): string {\n if (!html || !html.trim()) return \"\";\n const div = document.createElement(\"div\");\n div.innerHTML = html;\n const blocks: string[] = [];\n\n const handle = (el: HTMLElement): string => {\n const tag = el.tagName.toLowerCase();\n if (tag === \"h1\") return \"# \" + inlineHtmlToMd(el);\n if (tag === \"h2\") return \"## \" + inlineHtmlToMd(el);\n if (tag === \"h3\" || tag === \"h4\" || tag === \"h5\" || tag === \"h6\")\n return \"### \" + inlineHtmlToMd(el);\n if (tag === \"p\" || tag === \"div\") return inlineHtmlToMd(el);\n if (tag === \"ul\") {\n const items = Array.from(el.children)\n .filter((c) => c.tagName.toLowerCase() === \"li\")\n .map((li) => \"- \" + inlineHtmlToMd(li as HTMLElement));\n return items.join(\"\\n\");\n }\n if (tag === \"ol\") {\n const items = Array.from(el.children)\n .filter((c) => c.tagName.toLowerCase() === \"li\")\n .map((li, idx) => `${idx + 1}. ` + inlineHtmlToMd(li as HTMLElement));\n return items.join(\"\\n\");\n }\n if (tag === \"blockquote\") {\n const inner: string = Array.from(el.children)\n .map((c) => handle(c as HTMLElement) || inlineHtmlToMd(c as HTMLElement))\n .filter(Boolean)\n .join(\"\\n\");\n return inner\n .split(\"\\n\")\n .map((line: string) => \"> \" + line)\n .join(\"\\n\");\n }\n if (tag === \"br\") return \"\";\n return inlineHtmlToMd(el);\n };\n\n for (const child of Array.from(div.childNodes)) {\n if (child.nodeType === Node.TEXT_NODE) {\n const t = (child.textContent || \"\").trim();\n if (t) blocks.push(t);\n continue;\n }\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\n const text = handle(child as HTMLElement);\n if (text && text.trim()) blocks.push(text);\n }\n return blocks.join(\"\\n\\n\").trim();\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { Question } from '../types';\nimport {\n ChevronDownIcon,\n CheckIcon,\n CheckCircle2Icon,\n PlusIcon,\n RotateCcwIcon,\n TrashIcon,\n} from '../icons';\nimport { getInitials, parseDate, formatDate } from '../utils/helpers';\nimport { MentionText } from './MentionText';\nimport { MentionTextarea } from './MentionTextarea';\n\nfunction timeAgo(dateStr: string): string {\n const d = parseDate(dateStr);\n const diff = Date.now() - d.getTime();\n const minutes = Math.floor(diff / 60000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n if (days < 30) return `${days}d ago`;\n return formatDate(dateStr);\n}\n\nexport interface OutstandingQuestionsSectionProps {\n /** All questions for the task. */\n questions: Question[];\n /** Username of the logged-in user, for permission checks (delete-own). */\n currentUsername: string;\n /** Create a new question. */\n onCreate: (text: string) => Promise<void> | void;\n /** Toggle question status (awaiting ↔ answered). */\n onSetStatus: (questionId: string, status: 'awaiting' | 'answered') => Promise<void> | void;\n /** Delete a question (and its replies). */\n onDelete: (questionId: string) => Promise<void> | void;\n /** Add a reply to a question. */\n onAddReply: (questionId: string, content: string) => Promise<void> | void;\n}\n\n/**\n * Structured list of outstanding questions with awaiting/answered filter,\n * inline composer, and per-question collapsible threads. Replaces the legacy\n * free-text `open_questions` description field.\n */\nexport function OutstandingQuestionsSection({\n questions,\n currentUsername,\n onCreate,\n onSetStatus,\n onDelete,\n onAddReply,\n}: OutstandingQuestionsSectionProps) {\n const [filter, setFilter] = useState<'awaiting' | 'answered'>('awaiting');\n const [filterMenuOpen, setFilterMenuOpen] = useState(false);\n const [adding, setAdding] = useState(false);\n const [newText, setNewText] = useState('');\n const [posting, setPosting] = useState(false);\n const filterRef = useRef<HTMLDivElement>(null);\n const newRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n if (!filterMenuOpen) return;\n const onClick = (e: MouseEvent) => {\n if (filterRef.current && !filterRef.current.contains(e.target as Node)) {\n setFilterMenuOpen(false);\n }\n };\n document.addEventListener('mousedown', onClick);\n return () => document.removeEventListener('mousedown', onClick);\n }, [filterMenuOpen]);\n\n const counts = {\n awaiting: questions.filter((q) => q.status === 'awaiting').length,\n answered: questions.filter((q) => q.status === 'answered').length,\n };\n const filtered = questions.filter((q) => q.status === filter);\n\n const submitNew = async () => {\n if (!newText.trim()) return;\n setPosting(true);\n try {\n await onCreate(newText.trim());\n setNewText('');\n setAdding(false);\n } catch {\n // surface via parent's onError\n } finally {\n setPosting(false);\n }\n };\n\n return (\n <section>\n <div className=\"flex items-center gap-3 mb-3\">\n <h2 className=\"text-[15px] font-semibold text-neutral-900 tracking-tight\">\n Outstanding Questions\n </h2>\n <span\n className={`inline-flex items-center justify-center min-w-[18px] h-4 px-1 rounded text-[10px] font-semibold ${\n filter === 'awaiting'\n ? 'bg-amber-50 text-amber-700'\n : 'bg-emerald-50 text-emerald-700'\n }`}\n >\n {filtered.length}\n </span>\n <div className=\"relative ml-2\" ref={filterRef}>\n <button\n type=\"button\"\n onClick={() => setFilterMenuOpen(!filterMenuOpen)}\n className=\"inline-flex items-center gap-1.5 text-[12px] font-medium text-neutral-700 hover:text-neutral-900\"\n >\n <span>{filter === 'awaiting' ? 'Awaiting answer' : 'Answered'}</span>\n <ChevronDownIcon className=\"w-3 h-3 text-neutral-400\" strokeWidth={1.5} />\n </button>\n {filterMenuOpen && (\n <div className=\"absolute left-0 top-full mt-1 bg-white border border-neutral-200 rounded-xl shadow-lg py-1 z-30 min-w-[200px]\">\n {(['awaiting', 'answered'] as const).map((f) => (\n <button\n key={f}\n onClick={() => {\n setFilter(f);\n setFilterMenuOpen(false);\n }}\n className=\"w-full text-left px-3 py-2 text-[12px] text-neutral-700 hover:bg-neutral-50 flex items-center justify-between gap-3\"\n >\n <span className=\"flex items-center gap-2\">\n <CheckIcon\n size={12}\n strokeWidth={2.5}\n className={`text-[#FF5E00] ${filter === f ? '' : 'invisible'}`}\n />\n <span>{f === 'awaiting' ? 'Awaiting answer' : 'Answered'}</span>\n </span>\n <span className=\"text-[10px] text-neutral-400\">{counts[f]}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => {\n setAdding(true);\n setTimeout(() => newRef.current?.focus(), 0);\n }}\n className=\"ml-auto inline-flex items-center gap-1 text-[12px] font-medium text-[#FF5E00] hover:text-[#E05200]\"\n >\n <PlusIcon size={12} strokeWidth={2} />\n Add question\n </button>\n </div>\n\n {adding && (\n <div className=\"mb-4 rounded-lg border border-neutral-200 bg-white p-3\">\n <textarea\n ref={newRef}\n value={newText}\n onChange={(e) => setNewText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submitNew();\n }\n if (e.key === 'Escape') {\n setAdding(false);\n setNewText('');\n }\n }}\n placeholder=\"What's the question?\"\n rows={2}\n className=\"w-full px-2 py-1.5 text-[13px] text-neutral-800 placeholder:text-neutral-400 focus:outline-none resize-y\"\n />\n <div className=\"flex items-center justify-end gap-2 mt-2\">\n <button\n onClick={() => {\n setAdding(false);\n setNewText('');\n }}\n className=\"text-[12px] font-medium text-neutral-500 hover:text-neutral-900 px-2 h-7 rounded hover:bg-neutral-50\"\n >\n Cancel\n </button>\n <button\n onClick={submitNew}\n disabled={!newText.trim() || posting}\n className=\"inline-flex items-center justify-center px-3 h-7 rounded-lg text-[12px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] disabled:opacity-50\"\n >\n {posting ? 'Adding...' : 'Add'}\n </button>\n </div>\n </div>\n )}\n\n {filtered.length === 0 ? (\n <div className=\"rounded-lg border border-dashed border-neutral-200 px-4 py-6 text-center\">\n <p className=\"text-[12px] text-neutral-400\">\n {filter === 'awaiting'\n ? 'No outstanding questions.'\n : 'No answered questions yet.'}\n </p>\n </div>\n ) : (\n <ul className=\"flex flex-col gap-1\">\n {filtered.map((q) => (\n <QuestionItem\n key={q.id}\n question={q}\n currentUsername={currentUsername}\n onSetStatus={onSetStatus}\n onDelete={onDelete}\n onAddReply={onAddReply}\n />\n ))}\n </ul>\n )}\n </section>\n );\n}\n\nfunction QuestionItem({\n question,\n currentUsername,\n onSetStatus,\n onDelete,\n onAddReply,\n}: {\n question: Question;\n currentUsername: string;\n onSetStatus: OutstandingQuestionsSectionProps['onSetStatus'];\n onDelete: OutstandingQuestionsSectionProps['onDelete'];\n onAddReply: OutstandingQuestionsSectionProps['onAddReply'];\n}) {\n const [expanded, setExpanded] = useState(false);\n const [reply, setReply] = useState('');\n const [posting, setPosting] = useState(false);\n const isAnswered = question.status === 'answered';\n const dotColor = isAnswered ? 'bg-emerald-500' : 'bg-amber-500';\n const pillTextColor = isAnswered ? 'text-emerald-700' : 'text-amber-700';\n const borderColor = isAnswered ? 'border-emerald-200' : 'border-neutral-200';\n\n const submitReply = async () => {\n if (!reply.trim()) return;\n setPosting(true);\n try {\n await onAddReply(question.id, reply.trim());\n setReply('');\n } finally {\n setPosting(false);\n }\n };\n\n const toggleStatus = async () => {\n await onSetStatus(question.id, isAnswered ? 'awaiting' : 'answered');\n };\n\n const handleDelete = async () => {\n if (!confirm('Delete this question and its replies?')) return;\n await onDelete(question.id);\n };\n\n const canDelete = question.asked_by === currentUsername;\n\n return (\n <li className=\"group rounded-lg hover:bg-neutral-50/60 transition-colors\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-start gap-3 p-3 text-left\"\n >\n <span className={`mt-1.5 w-1.5 h-1.5 rounded-full shrink-0 ${dotColor}`} />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-[13px] text-neutral-800 leading-snug\">{question.text}</p>\n <div className=\"mt-1 flex items-center gap-2 text-[12px] text-neutral-500 flex-wrap\">\n <span>\n Asked by{' '}\n <span className=\"font-medium text-neutral-700\">\n {question.asked_by_name || question.asked_by}\n </span>\n </span>\n <span className=\"text-neutral-300\">·</span>\n <span>\n {question.replies.length} repl{question.replies.length === 1 ? 'y' : 'ies'}\n </span>\n <span className=\"text-neutral-300\">·</span>\n <span className={`inline-flex items-center gap-1 ${pillTextColor}`}>\n <span className={`w-1.5 h-1.5 rounded-full ${dotColor}`} />\n {isAnswered ? 'Answered' : 'Awaiting answer'}\n </span>\n </div>\n </div>\n <ChevronDownIcon\n className={`w-4 h-4 text-neutral-400 mt-1 shrink-0 transition-transform ${\n expanded ? 'rotate-180' : ''\n }`}\n strokeWidth={1.5}\n />\n </button>\n\n {expanded && (\n <div className=\"pl-7 pr-3 pb-3\">\n <div className={`border-l-2 ${borderColor} pl-4 flex flex-col gap-3`}>\n {question.replies.map((r) => (\n <div key={r.id} className=\"flex gap-2.5\">\n <div className=\"w-6 h-6 rounded-full bg-[#FF5E00] text-white flex items-center justify-center text-[10px] font-semibold shrink-0\">\n {getInitials(r.author_name || '?')}\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-[12px] font-medium text-neutral-900\">\n {r.author_name}\n </span>\n <span className=\"text-[10px] text-neutral-400\">\n {timeAgo(r.created_at)}\n </span>\n </div>\n <p className=\"text-[12px] text-neutral-700 leading-relaxed whitespace-pre-wrap\">\n <MentionText text={r.content} />\n </p>\n </div>\n </div>\n ))}\n <div className=\"flex gap-2.5 pt-1\">\n <div className=\"w-6 h-6 rounded-full bg-neutral-100 text-neutral-700 flex items-center justify-center text-[10px] font-semibold shrink-0\">\n {getInitials(currentUsername || '?')}\n </div>\n <div className=\"flex-1 min-w-0 flex flex-col gap-2\">\n <MentionTextarea\n value={reply}\n onChange={setReply}\n rows={2}\n placeholder=\"Reply… (type @ to mention)\"\n className=\"w-full rounded-md border border-neutral-200 px-3 py-1.5 text-[12px] min-h-[60px] focus:outline-none focus:ring-1 focus:ring-neutral-300 resize-none\"\n />\n <div className=\"flex items-center justify-end gap-2\">\n {canDelete && (\n <button\n type=\"button\"\n onClick={handleDelete}\n className=\"inline-flex items-center gap-1.5 text-[12px] font-medium text-neutral-500 hover:text-red-600 px-2 h-7 rounded hover:bg-red-50\"\n >\n <TrashIcon size={12} strokeWidth={1.5} />\n Delete question\n </button>\n )}\n <button\n type=\"button\"\n onClick={toggleStatus}\n className=\"inline-flex items-center gap-1.5 text-[12px] font-medium text-neutral-600 hover:text-neutral-900 px-2 h-7 rounded hover:bg-neutral-100\"\n >\n {isAnswered ? (\n <>\n <RotateCcwIcon size={12} strokeWidth={1.5} />\n Reopen\n </>\n ) : (\n <>\n <CheckCircle2Icon size={12} strokeWidth={1.5} />\n Mark answered\n </>\n )}\n </button>\n <button\n type=\"button\"\n onClick={submitReply}\n disabled={!reply.trim() || posting}\n className=\"inline-flex items-center justify-center px-3 h-7 rounded-lg text-[12px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] disabled:opacity-50\"\n >\n {posting ? 'Posting...' : 'Reply'}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n )}\n </li>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { Attachment } from '../types';\nimport {\n PlusIcon,\n XIcon,\n ImageIcon,\n FileTextIcon,\n Link2Icon,\n ExternalLinkIcon,\n} from '../icons';\n\nfunction formatBytes(bytes: number | null | undefined): string {\n if (!bytes && bytes !== 0) return '';\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction attachmentMeta(a: Attachment): string {\n if (a.kind === 'link') {\n try {\n return new URL(a.url.startsWith('http') ? a.url : `https://${a.url}`).hostname;\n } catch {\n return '';\n }\n }\n return formatBytes(a.size);\n}\n\nexport interface AttachmentsSectionProps {\n attachments: Attachment[];\n /** Upload a file (image or document). */\n onUpload: (file: File) => Promise<unknown> | void;\n /** Add an external link/recording. */\n onAddLink: (url: string, name?: string) => Promise<unknown> | void;\n /** Delete an attachment by id. */\n onDelete: (attachmentId: string) => Promise<unknown> | void;\n}\n\n/**\n * Three-subgroup attachments display (Images / Files / Links & recordings)\n * with an \"Add attachment\" popover and an \"Add link or recording\" modal.\n *\n * Bug #3 fix: Cancel/Save buttons in the link modal use `inline-flex\n * items-center justify-center` (without these, the button text wasn't\n * vertically centered) and `text-[13px]` (was `text-[12px]`).\n */\nexport function AttachmentsSection({\n attachments,\n onUpload,\n onAddLink,\n onDelete,\n}: AttachmentsSectionProps) {\n const [menuOpen, setMenuOpen] = useState(false);\n const [linkModalOpen, setLinkModalOpen] = useState(false);\n const [linkUrl, setLinkUrl] = useState('');\n const [linkTitle, setLinkTitle] = useState('');\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState('');\n const fileInputRef = useRef<HTMLInputElement>(null);\n const imageInputRef = useRef<HTMLInputElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!menuOpen) return;\n const onClick = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setMenuOpen(false);\n }\n };\n document.addEventListener('mousedown', onClick);\n return () => document.removeEventListener('mousedown', onClick);\n }, [menuOpen]);\n\n const showError = (msg: string) => {\n setError(msg);\n setTimeout(() => setError(''), 4000);\n };\n\n const upload = async (file: File) => {\n setBusy(true);\n setError('');\n try {\n await onUpload(file);\n } catch (err: unknown) {\n const e = err as { response?: { data?: { detail?: string } } };\n showError(e.response?.data?.detail || 'Upload failed');\n } finally {\n setBusy(false);\n }\n };\n\n const submitLink = async () => {\n if (!linkUrl.trim()) return;\n setBusy(true);\n setError('');\n try {\n await onAddLink(linkUrl.trim(), linkTitle.trim() || undefined);\n setLinkUrl('');\n setLinkTitle('');\n setLinkModalOpen(false);\n } catch (err: unknown) {\n const e = err as { response?: { data?: { detail?: string } } };\n showError(e.response?.data?.detail || 'Failed to add link');\n } finally {\n setBusy(false);\n }\n };\n\n const remove = async (id: string) => {\n try {\n await onDelete(id);\n } catch (err: unknown) {\n const e = err as { response?: { data?: { detail?: string } } };\n showError(e.response?.data?.detail || 'Failed to delete');\n }\n };\n\n const images = attachments.filter((a) => a.kind === 'image');\n const files = attachments.filter((a) => a.kind === 'file');\n const links = attachments.filter((a) => a.kind === 'link');\n\n return (\n <section>\n <div className=\"flex items-center gap-3 mb-3\">\n <h2 className=\"text-[15px] font-semibold text-neutral-900 tracking-tight\">Attachments</h2>\n {busy && <span className=\"text-[11px] text-neutral-400\">Uploading...</span>}\n <div className=\"ml-auto relative\" ref={menuRef}>\n <button\n type=\"button\"\n onClick={() => setMenuOpen(!menuOpen)}\n disabled={busy}\n className=\"inline-flex items-center gap-1 text-[12px] font-medium text-[#FF5E00] hover:text-[#E05200] disabled:opacity-50\"\n >\n <PlusIcon size={12} strokeWidth={2} />\n Add attachment\n </button>\n {menuOpen && (\n <div className=\"absolute right-0 top-full mt-1 w-44 bg-white border border-neutral-200 rounded-xl shadow-lg py-1 z-30\">\n <button\n onClick={() => {\n setMenuOpen(false);\n imageInputRef.current?.click();\n }}\n className=\"w-full text-left px-3 py-2 text-[12px] text-neutral-700 hover:bg-neutral-50 flex items-center gap-2.5\"\n >\n <ImageIcon size={14} strokeWidth={1.5} className=\"text-neutral-400\" />\n Image\n </button>\n <button\n onClick={() => {\n setMenuOpen(false);\n fileInputRef.current?.click();\n }}\n className=\"w-full text-left px-3 py-2 text-[12px] text-neutral-700 hover:bg-neutral-50 flex items-center gap-2.5\"\n >\n <FileTextIcon size={14} strokeWidth={1.5} className=\"text-neutral-400\" />\n File\n </button>\n <button\n onClick={() => {\n setMenuOpen(false);\n setLinkModalOpen(true);\n }}\n className=\"w-full text-left px-3 py-2 text-[12px] text-neutral-700 hover:bg-neutral-50 flex items-center gap-2.5\"\n >\n <Link2Icon size={14} strokeWidth={1.5} className=\"text-neutral-400\" />\n Link / Recording\n </button>\n </div>\n )}\n </div>\n\n <input\n ref={imageInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) upload(f);\n e.target.value = '';\n }}\n />\n <input\n ref={fileInputRef}\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) upload(f);\n e.target.value = '';\n }}\n />\n </div>\n\n {error && (\n <div className=\"mb-3 text-[12px] text-red-600 bg-red-50 border border-red-100 rounded-lg px-3 py-2\">\n {error}\n </div>\n )}\n\n {attachments.length === 0 ? (\n <div className=\"rounded-lg border border-dashed border-neutral-200 px-4 py-6 text-center\">\n <p className=\"text-[12px] text-neutral-400\">No attachments yet.</p>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {images.length > 0 && (\n <div>\n <p className=\"text-[10px] font-semibold tracking-wider text-neutral-400 uppercase mb-2\">\n Images\n </p>\n <div className=\"grid grid-cols-3 gap-2\">\n {images.map((img) => (\n <a\n key={img.id}\n href={img.url || '#'}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"group relative aspect-video overflow-hidden rounded-lg border border-neutral-200 hover:border-neutral-300 bg-neutral-50\"\n >\n {img.url ? (\n // eslint-disable-next-line @next/next/no-img-element\n <img src={img.url} alt={img.name} className=\"w-full h-full object-cover\" />\n ) : (\n <div className=\"w-full h-full flex items-center justify-center text-neutral-400\">\n <ImageIcon size={24} strokeWidth={1.5} />\n </div>\n )}\n <div className=\"absolute bottom-1 left-1 right-8 text-[10px] text-white px-1.5 py-0.5 rounded bg-black/60 truncate opacity-0 group-hover:opacity-100\">\n {img.name}\n </div>\n <button\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n remove(img.id);\n }}\n className=\"absolute top-1 right-1 w-6 h-6 rounded-full bg-black/60 text-white opacity-0 group-hover:opacity-100 flex items-center justify-center\"\n title=\"Remove\"\n >\n <XIcon size={12} strokeWidth={2} />\n </button>\n </a>\n ))}\n </div>\n </div>\n )}\n\n {files.length > 0 && (\n <div>\n <p className=\"text-[10px] font-semibold tracking-wider text-neutral-400 uppercase mb-2\">\n Files\n </p>\n <div className=\"flex flex-col gap-1.5\">\n {files.map((f) => {\n const meta = attachmentMeta(f);\n return (\n <div\n key={f.id}\n className=\"group flex items-center gap-3 p-2 rounded-lg border border-neutral-200 hover:bg-neutral-50\"\n >\n <div className=\"w-8 h-8 rounded bg-neutral-100 flex items-center justify-center text-neutral-500\">\n <FileTextIcon size={16} strokeWidth={1.5} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-[13px] font-medium text-neutral-900 truncate\">{f.name}</div>\n {meta && <div className=\"text-[10px] text-neutral-500\">{meta}</div>}\n </div>\n {f.url && (\n <a\n href={f.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"w-7 h-7 rounded hover:bg-neutral-100 text-neutral-500 hover:text-neutral-900 flex items-center justify-center\"\n title=\"Open\"\n >\n <ExternalLinkIcon size={14} strokeWidth={1.5} />\n </a>\n )}\n <button\n onClick={() => remove(f.id)}\n className=\"opacity-0 group-hover:opacity-100 w-7 h-7 rounded hover:bg-red-50 text-neutral-400 hover:text-red-500 flex items-center justify-center\"\n title=\"Remove\"\n >\n <XIcon size={14} strokeWidth={2} />\n </button>\n </div>\n );\n })}\n </div>\n </div>\n )}\n\n {links.length > 0 && (\n <div>\n <p className=\"text-[10px] font-semibold tracking-wider text-neutral-400 uppercase mb-2\">\n Links & recordings\n </p>\n <div className=\"flex flex-col gap-1.5\">\n {links.map((l) => {\n const meta = attachmentMeta(l);\n return (\n <a\n key={l.id}\n href={l.url.startsWith('http') ? l.url : `https://${l.url}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"group flex items-center gap-3 p-2 rounded-lg border border-neutral-200 hover:bg-neutral-50\"\n >\n <div className=\"w-8 h-8 rounded bg-neutral-100 flex items-center justify-center text-neutral-500\">\n <Link2Icon size={16} strokeWidth={1.5} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-[13px] font-medium text-neutral-900 truncate\">{l.name}</div>\n {meta && <div className=\"text-[10px] text-neutral-500\">{meta}</div>}\n </div>\n <ExternalLinkIcon size={14} strokeWidth={1.5} className=\"text-neutral-400 shrink-0\" />\n <button\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n remove(l.id);\n }}\n className=\"opacity-0 group-hover:opacity-100 w-7 h-7 rounded hover:bg-red-50 text-neutral-400 hover:text-red-500 flex items-center justify-center\"\n title=\"Remove\"\n >\n <XIcon size={14} strokeWidth={2} />\n </button>\n </a>\n );\n })}\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Add link / recording modal */}\n {linkModalOpen && (\n <div\n className=\"fixed inset-0 z-[80] flex items-center justify-center bg-black/40 backdrop-blur-sm p-4\"\n onClick={() => setLinkModalOpen(false)}\n >\n <div\n className=\"bg-white rounded-2xl shadow-2xl w-full max-w-[460px] overflow-hidden\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-neutral-100\">\n <h3 className=\"text-[15px] font-semibold text-neutral-900\">Add link or recording</h3>\n <button\n onClick={() => setLinkModalOpen(false)}\n className=\"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-neutral-100 text-neutral-500\"\n >\n <XIcon size={16} strokeWidth={1.5} />\n </button>\n </div>\n <div className=\"p-5 flex flex-col gap-3\">\n <div className=\"flex flex-col gap-1.5\">\n <label className=\"text-[12px] font-medium text-neutral-600\">URL</label>\n <input\n type=\"url\"\n value={linkUrl}\n onChange={(e) => setLinkUrl(e.target.value)}\n placeholder=\"https://loom.com/share/…\"\n autoFocus\n className=\"h-10 rounded-xl border border-neutral-200 px-3 text-[13px] text-neutral-900 placeholder:text-neutral-400 focus:outline-none focus:ring-1 focus:ring-neutral-300\"\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <label className=\"text-[12px] font-medium text-neutral-600\">\n Title <span className=\"text-neutral-400 font-normal\">(optional)</span>\n </label>\n <input\n type=\"text\"\n value={linkTitle}\n onChange={(e) => setLinkTitle(e.target.value)}\n placeholder=\"e.g. Walkthrough — parsing edge cases\"\n className=\"h-10 rounded-xl border border-neutral-200 px-3 text-[13px] text-neutral-900 placeholder:text-neutral-400 focus:outline-none focus:ring-1 focus:ring-neutral-300\"\n />\n </div>\n </div>\n <div className=\"px-5 py-4 border-t border-neutral-100 flex items-center justify-end gap-2\">\n <button\n onClick={() => setLinkModalOpen(false)}\n className=\"inline-flex items-center justify-center h-10 px-4 rounded-xl border border-neutral-200 bg-white text-neutral-700 text-[13px] font-medium hover:bg-neutral-50 transition-colors\"\n >\n Cancel\n </button>\n <button\n onClick={submitLink}\n disabled={!linkUrl.trim() || busy}\n className=\"inline-flex items-center justify-center h-10 px-4 rounded-xl bg-[#FF5E00] text-white text-[13px] font-medium shadow-sm hover:bg-[#E05200] disabled:opacity-50 transition-colors\"\n >\n {busy ? 'Saving...' : 'Save'}\n </button>\n </div>\n </div>\n </div>\n )}\n </section>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { ActivityEntry, Attachment, ThreadAnchor, ThreadStatus } from '../types';\nimport {\n ChatDotsIcon,\n CheckIcon,\n ChevronDownIcon,\n HistoryIcon,\n SidebarToggleIcon,\n} from '../icons';\nimport { type Thread } from '../utils/threads';\nimport { ActivityList } from './ActivityList';\nimport { ThreadCard } from './ThreadCard';\nimport { ThreadComposer } from './ThreadComposer';\nimport { ThreadDetailView } from './ThreadDetailView';\n\nexport interface ThreadsPanelProps {\n threads: Thread[];\n activity: ActivityEntry[];\n attachments: Attachment[];\n\n /** Open / close state. Lift this to the page so the bubble + main padding can coordinate. */\n open: boolean;\n onToggle: () => void;\n\n /** Currently-open thread (null = list view). Lifted so panel + page agree. */\n openThreadId: string | null;\n onOpenThread: (id: string | null) => void;\n\n /** Highlight-to-comment anchor pending placement on a new thread. */\n pendingAnchor: ThreadAnchor | null;\n onClearAnchor: () => void;\n /** Click handler for anchor pills — should scroll/pulse the anchored section. */\n onAnchorClick: (anchor: ThreadAnchor) => void;\n\n /** Set of thread ids currently shimmering (no user-supplied title yet). */\n shimmeringThreadIds: Set<string>;\n\n /** Whether the current user is allowed to post internal-only threads/replies. */\n isInternalUser: boolean;\n\n /** Submit a brand-new top-level thread. */\n onCreateThread: (data: {\n title: string;\n content: string;\n isInternal: boolean;\n anchor: ThreadAnchor | null;\n attachmentIds: string[];\n }) => Promise<void>;\n /** Submit a reply on an existing thread. */\n onCreateReply: (parentId: string, content: string, isInternal: boolean) => Promise<void>;\n /** Update title or status on an existing thread. */\n onUpdateThread: (\n threadId: string,\n body: { title?: string; thread_status?: ThreadStatus }\n ) => Promise<void>;\n /** Upload a file attachment for the current task. Returns the new row. */\n onUploadAttachment: (file: File) => Promise<Attachment>;\n /** Add a link/recording attachment for the current task. */\n onAddLinkAttachment: (url: string, name?: string) => Promise<Attachment>;\n}\n\n/**\n * Right-side panel with Threads / Activity tabs, collapse toggle, thread list,\n * thread detail view, and the new-thread composer. Designed to be `xl:flex\n * hidden` and `fixed` to the right edge by the consuming page.\n */\nexport function ThreadsPanel({\n threads,\n activity,\n attachments,\n open,\n onToggle,\n openThreadId,\n onOpenThread,\n pendingAnchor,\n onClearAnchor,\n onAnchorClick,\n shimmeringThreadIds,\n isInternalUser,\n onCreateThread,\n onCreateReply,\n onUpdateThread,\n onUploadAttachment,\n onAddLinkAttachment,\n}: ThreadsPanelProps) {\n const [tab, setTab] = useState<'threads' | 'activity'>('threads');\n const [composerOpen, setComposerOpen] = useState(false);\n const [filter, setFilter] = useState<ThreadStatus>('active');\n const [filterMenuOpen, setFilterMenuOpen] = useState(false);\n const filterRef = useRef<HTMLDivElement>(null);\n\n // When parent passes a pending anchor, expand the composer immediately.\n useEffect(() => {\n if (pendingAnchor) {\n setComposerOpen(true);\n setTab('threads');\n onOpenThread(null);\n }\n }, [pendingAnchor, onOpenThread]);\n\n useEffect(() => {\n if (!filterMenuOpen) return;\n const onClick = (e: MouseEvent) => {\n if (filterRef.current && !filterRef.current.contains(e.target as Node)) {\n setFilterMenuOpen(false);\n }\n };\n document.addEventListener('mousedown', onClick);\n return () => document.removeEventListener('mousedown', onClick);\n }, [filterMenuOpen]);\n\n const filteredThreads = threads.filter((t) => t.status === filter);\n const openThread = openThreadId ? threads.find((t) => t.id === openThreadId) : null;\n\n // If the open thread disappears (e.g. data refresh removed it), close detail.\n useEffect(() => {\n if (openThreadId && !threads.some((t) => t.id === openThreadId)) {\n onOpenThread(null);\n }\n }, [threads, openThreadId, onOpenThread]);\n\n // Collapsed state — show a thin strip with just the open button.\n if (!open) {\n return (\n <aside className=\"hidden xl:flex flex-col fixed top-[56px] bottom-0 right-0 w-14 border-l border-neutral-200 bg-white z-30\">\n <div className=\"shrink-0 flex bg-white h-12 border-b border-neutral-200 items-center justify-center\">\n <button\n type=\"button\"\n onClick={onToggle}\n aria-label=\"Open thread panel\"\n title=\"Open thread panel\"\n className=\"w-7 h-7 flex items-center justify-center rounded hover:bg-neutral-100 text-neutral-400 hover:text-neutral-600\"\n >\n <SidebarToggleIcon size={18} strokeWidth={1.5} />\n </button>\n </div>\n </aside>\n );\n }\n\n return (\n <aside className=\"hidden xl:flex flex-col fixed top-[56px] bottom-0 right-0 w-[420px] border-l border-neutral-200 bg-white z-30\">\n {/* Header with tabs */}\n <div className=\"shrink-0 flex bg-white h-12 border-b border-neutral-200 px-5 items-center justify-between\">\n <span className=\"text-[13px] font-medium text-neutral-500\">\n {tab === 'threads' ? 'Threads' : 'Activity'}{' '}\n <span className=\"text-neutral-400 ml-0.5\">\n {tab === 'threads' ? threads.length : activity.length}\n </span>\n </span>\n <div className=\"flex items-center gap-1\" role=\"tablist\">\n <button\n type=\"button\"\n onClick={() => {\n setTab('threads');\n onOpenThread(null);\n }}\n aria-pressed={tab === 'threads'}\n className={`w-7 h-7 flex items-center justify-center rounded ${\n tab === 'threads'\n ? 'bg-neutral-100 text-neutral-700'\n : 'text-neutral-400 hover:bg-neutral-100 hover:text-neutral-600'\n }`}\n aria-label=\"Threads\"\n >\n <ChatDotsIcon size={16} strokeWidth={1.5} />\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setTab('activity');\n onOpenThread(null);\n }}\n aria-pressed={tab === 'activity'}\n className={`w-7 h-7 flex items-center justify-center rounded ${\n tab === 'activity'\n ? 'bg-neutral-100 text-neutral-700'\n : 'text-neutral-400 hover:bg-neutral-100 hover:text-neutral-600'\n }`}\n aria-label=\"Activity\"\n >\n <HistoryIcon size={16} strokeWidth={1.5} />\n </button>\n <span className=\"w-px h-4 bg-neutral-200 mx-1\" />\n <button\n type=\"button\"\n onClick={onToggle}\n aria-label=\"Close thread panel\"\n title=\"Close thread panel\"\n className=\"w-7 h-7 flex items-center justify-center rounded text-neutral-400 hover:bg-neutral-100 hover:text-neutral-600\"\n >\n <SidebarToggleIcon size={18} strokeWidth={1.5} />\n </button>\n </div>\n </div>\n\n {/* Threads list view */}\n {tab === 'threads' && !openThread && (\n <>\n <div className=\"shrink-0 px-4 pt-3 pb-2 bg-white relative\" ref={filterRef}>\n <button\n onClick={() => setFilterMenuOpen(!filterMenuOpen)}\n className=\"inline-flex items-center gap-1.5 text-[12px] font-medium text-neutral-700 hover:text-neutral-900\"\n >\n <span>{filter === 'active' ? 'Active threads' : 'Completed threads'}</span>\n <span className=\"text-[10px] text-neutral-400\">{filteredThreads.length}</span>\n <ChevronDownIcon size={12} strokeWidth={1.5} className=\"text-neutral-400\" />\n </button>\n {filterMenuOpen && (\n <div className=\"absolute left-4 top-full mt-0.5 bg-white border border-neutral-200 rounded-xl shadow-lg py-1 z-20 min-w-[200px]\">\n {(['active', 'complete'] as const).map((f) => (\n <button\n key={f}\n onClick={() => {\n setFilter(f);\n setFilterMenuOpen(false);\n }}\n className=\"w-full text-left px-3 py-2 text-[12px] text-neutral-700 hover:bg-neutral-50 flex items-center justify-between gap-3\"\n >\n <span className=\"flex items-center gap-2\">\n <CheckIcon\n size={12}\n strokeWidth={2.5}\n className={`text-[#FF5E00] ${filter === f ? '' : 'invisible'}`}\n />\n <span>{f === 'active' ? 'Active threads' : 'Completed threads'}</span>\n </span>\n <span className=\"text-[10px] text-neutral-400\">\n {threads.filter((t) => t.status === f).length}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-2 flex flex-col divide-y divide-neutral-100\">\n {filteredThreads.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <div className=\"w-10 h-10 rounded-full bg-neutral-100 flex items-center justify-center mb-3\">\n <ChatDotsIcon size={18} strokeWidth={1.5} className=\"text-neutral-400\" />\n </div>\n <p className=\"text-[12px] text-neutral-400\">No threads yet</p>\n <p className=\"text-[10px] text-neutral-400 mt-0.5\">\n Start a thread to discuss this task.\n </p>\n </div>\n )}\n {filteredThreads.map((t) => (\n <ThreadCard\n key={t.id}\n thread={t}\n onOpen={() => onOpenThread(t.id)}\n onAnchorClick={onAnchorClick}\n shimmer={shimmeringThreadIds.has(t.id)}\n />\n ))}\n </div>\n\n <ThreadComposer\n attachments={attachments}\n pendingAnchor={pendingAnchor}\n onClearAnchor={onClearAnchor}\n onSubmit={onCreateThread}\n onUpload={onUploadAttachment}\n onAddLink={onAddLinkAttachment}\n isInternalUser={isInternalUser}\n open={composerOpen}\n onOpen={() => setComposerOpen(true)}\n onClose={() => {\n setComposerOpen(false);\n onClearAnchor();\n }}\n />\n </>\n )}\n\n {/* Threads detail view */}\n {tab === 'threads' && openThread && (\n <ThreadDetailView\n thread={openThread}\n onBack={() => onOpenThread(null)}\n onReply={(content, isInternal) => onCreateReply(openThread.id, content, isInternal)}\n onUpdateThread={(body) => onUpdateThread(openThread.id, body)}\n onAnchorClick={onAnchorClick}\n isInternalUser={isInternalUser}\n />\n )}\n\n {/* Activity tab */}\n {tab === 'activity' && <ActivityList activity={activity} />}\n </aside>\n );\n}\n","import React from 'react';\nimport type { ActivityEntry } from '../types';\nimport { ChevronRightIcon, HistoryIcon, PlusIcon } from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { formatDateTime } from '../utils/helpers';\n\nexport interface ActivityListProps {\n activity: ActivityEntry[];\n}\n\n/** Status-change activity log shown in the Activity tab of the threads panel. */\nexport function ActivityList({ activity }: ActivityListProps) {\n const { columns } = useTaskBoardContext();\n\n if (activity.length === 0) {\n return (\n <div className=\"flex-1 overflow-y-auto p-4 flex flex-col items-center justify-center text-center\">\n <div className=\"w-10 h-10 rounded-full bg-neutral-100 flex items-center justify-center mb-3\">\n <HistoryIcon size={18} strokeWidth={1.5} className=\"text-neutral-400\" />\n </div>\n <p className=\"text-[12px] text-neutral-400\">No activity yet</p>\n <p className=\"text-[10px] text-neutral-400 mt-0.5\">Status changes will appear here</p>\n </div>\n );\n }\n\n return (\n <div className=\"flex-1 overflow-y-auto p-4\">\n <ul className=\"flex flex-col gap-4\">\n {activity.map((a) => {\n const fromCol = columns.find((c) => c.key === a.from_status);\n const toCol = columns.find((c) => c.key === a.to_status);\n const isCreated = a.type === 'created';\n return (\n <li key={a.id} className=\"flex gap-3\">\n <div className=\"w-7 h-7 rounded-full bg-neutral-100 text-neutral-500 flex items-center justify-center shrink-0\">\n {isCreated ? (\n <PlusIcon size={14} strokeWidth={1.5} />\n ) : (\n <ChevronRightIcon size={14} strokeWidth={1.5} />\n )}\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-[12px] text-neutral-700\">\n <span className=\"font-medium text-neutral-900\">{a.user_name}</span>{' '}\n {isCreated ? (\n 'created this task'\n ) : (\n <>\n moved from{' '}\n <span\n className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded ${\n fromCol?.chip ?? 'bg-neutral-100 text-neutral-700'\n }`}\n >\n <span\n className={`w-1.5 h-1.5 rounded-full ${fromCol?.color ?? 'bg-neutral-300'}`}\n />\n {fromCol?.label ?? a.from_status}\n </span>{' '}\n to{' '}\n <span\n className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded ${\n toCol?.chip ?? 'bg-neutral-100 text-neutral-700'\n }`}\n >\n <span\n className={`w-1.5 h-1.5 rounded-full ${toCol?.color ?? 'bg-neutral-300'}`}\n />\n {toCol?.label ?? a.to_status}\n </span>\n </>\n )}\n </p>\n <p className=\"text-[10px] text-neutral-400 mt-0.5\">\n {formatDateTime(a.created_at)}\n </p>\n </div>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n","import React from 'react';\n\nexport type ContextPillVariant = 'amber' | 'purple' | 'blue' | 'emerald' | 'neutral';\n\nconst VARIANTS: Record<ContextPillVariant, string> = {\n amber: 'bg-amber-50 text-amber-700 border-amber-200 hover:bg-amber-100',\n purple: 'bg-purple-50 text-purple-700 border-purple-200 hover:bg-purple-100',\n blue: 'bg-blue-50 text-blue-700 border-blue-200 hover:bg-blue-100',\n emerald: 'bg-emerald-50 text-emerald-700 border-emerald-200 hover:bg-emerald-100',\n neutral: 'bg-neutral-50 text-neutral-700 border-neutral-200 hover:bg-neutral-100',\n};\n\nexport interface ContextPillProps {\n variant: ContextPillVariant;\n icon: React.ComponentType<{ className?: string; strokeWidth?: number; size?: number }>;\n label: string;\n onClick?: (e: React.MouseEvent) => void;\n}\n\n/** A small color-coded pill used on thread cards (highlights, attachments, etc.). */\nexport function ContextPill({ variant, icon: IconC, label, onClick }: ContextPillProps) {\n return (\n <span\n role={onClick ? 'button' : undefined}\n onClick={onClick}\n className={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full border text-[11px] font-medium max-w-full self-start shrink-0 transition-colors ${\n VARIANTS[variant]\n } ${onClick ? 'cursor-pointer' : ''}`}\n >\n <IconC className=\"w-3 h-3 shrink-0\" strokeWidth={1.5} />\n <span className=\"truncate\">{label}</span>\n </span>\n );\n}\n","import React from 'react';\nimport type { ThreadAnchor } from '../types';\nimport {\n CheckIcon,\n CornerUpLeftIcon,\n FileTextIcon,\n ImageIcon,\n Link2Icon,\n LockIcon,\n MessageSquareIcon,\n} from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { getInitials } from '../utils/helpers';\nimport { type Thread, sectionLabel, timeAgo } from '../utils/threads';\nimport { MentionText } from './MentionText';\nimport { ContextPill, type ContextPillVariant } from './ContextPill';\n\nexport interface ThreadCardProps {\n thread: Thread;\n /** Open the full thread detail view. */\n onOpen: () => void;\n /** Click handler for an anchor pill — should scroll/pulse the anchored section. */\n onAnchorClick: (anchor: ThreadAnchor) => void;\n /** When true, render the title as a shimmer placeholder (\"AI is generating a title\"). */\n shimmer?: boolean;\n}\n\n/**\n * One row in the threads list. Click anywhere on the card to open the\n * thread detail view. Anchor pills stop propagation so they can scroll\n * back to the highlighted description section instead.\n */\nexport function ThreadCard({ thread, onOpen, onAnchorClick, shimmer }: ThreadCardProps) {\n const { internalLabel } = useTaskBoardContext();\n const initials = getInitials(thread.author_name || '?');\n const hasContext = !!thread.anchor || thread.attachments.length > 0;\n const isComplete = thread.status === 'complete';\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onOpen}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onOpen();\n }\n }}\n className={`text-left w-full px-3 py-4 flex flex-col gap-1.5 hover:bg-neutral-50/60 transition-colors cursor-pointer focus:outline-none focus-visible:bg-neutral-50 ${\n isComplete ? 'opacity-60' : ''\n }`}\n >\n <div className=\"flex items-center gap-2\">\n {shimmer ? (\n <span className=\"eb-tb-thread-title-skeleton h-4 w-48 rounded shrink-0\" aria-hidden />\n ) : (\n <h4\n className={`text-[13px] font-semibold leading-snug flex-1 min-w-0 truncate ${\n isComplete ? 'text-neutral-400' : 'text-neutral-900'\n }`}\n >\n {thread.title}\n </h4>\n )}\n {isComplete && (\n <span className=\"shrink-0 inline-flex items-center gap-1 text-[10px] font-medium text-emerald-700 bg-emerald-50 px-1.5 py-0.5 rounded\">\n <CheckIcon size={10} strokeWidth={2.5} /> Complete\n </span>\n )}\n </div>\n\n {hasContext && (\n <div className=\"flex flex-wrap gap-1.5\">\n {thread.anchor && (\n <ContextPill\n variant=\"amber\"\n icon={MessageSquareIcon}\n label={`Highlight · ${sectionLabel(thread.anchor.section)}`}\n onClick={(e) => {\n e.stopPropagation();\n if (thread.anchor) onAnchorClick(thread.anchor);\n }}\n />\n )}\n {thread.attachments.slice(0, 3).map((a) => {\n const variant: ContextPillVariant =\n a.kind === 'image' ? 'emerald' : a.kind === 'link' ? 'blue' : 'neutral';\n const IconC =\n a.kind === 'image' ? ImageIcon : a.kind === 'link' ? Link2Icon : FileTextIcon;\n return <ContextPill key={a.id} variant={variant} icon={IconC} label={a.name} />;\n })}\n {thread.attachments.length > 3 && (\n <span className=\"text-[10px] text-neutral-400 self-center\">\n +{thread.attachments.length - 3}\n </span>\n )}\n </div>\n )}\n\n <div className=\"flex items-center gap-2 text-[10px] text-neutral-500\">\n <div\n className={`w-5 h-5 rounded-full flex items-center justify-center text-[9px] font-semibold shrink-0 ${\n thread.is_internal ? 'bg-neutral-200 text-neutral-700' : 'bg-[#FF5E00] text-white'\n }`}\n >\n {initials}\n </div>\n <span className=\"font-medium text-neutral-700\">{thread.author_name}</span>\n <span className=\"text-neutral-300\">·</span>\n <span>{timeAgo(thread.created_at)}</span>\n {thread.is_internal && (\n <>\n <span className=\"text-neutral-300\">·</span>\n <span className=\"text-[10px] text-neutral-500 bg-neutral-100 px-1.5 py-0.5 rounded inline-flex items-center gap-1\">\n <LockIcon size={10} strokeWidth={1.5} />\n {internalLabel}\n </span>\n </>\n )}\n </div>\n\n <div\n className={`text-[12px] leading-relaxed line-clamp-2 ${\n isComplete ? 'text-neutral-400' : 'text-neutral-700'\n }`}\n >\n <MentionText text={thread.preview} />\n </div>\n\n {thread.replies.length > 0 ? (\n <div className=\"flex items-center gap-2 mt-0.5\">\n <span className=\"text-[12px] font-medium text-[#FF5E00]\">\n {thread.replies.length} repl{thread.replies.length === 1 ? 'y' : 'ies'}\n </span>\n <span className=\"text-[10px] text-neutral-400\">\n · last reply {timeAgo(thread.replies[thread.replies.length - 1].created_at)}\n </span>\n </div>\n ) : (\n <span className=\"self-start inline-flex items-center gap-1.5 mt-0.5 text-[12px] font-medium text-[#FF5E00]\">\n <CornerUpLeftIcon size={12} strokeWidth={1.5} />\n Reply\n </span>\n )}\n </div>\n );\n}\n","import React, { useRef, useState } from 'react';\nimport type { Attachment, ThreadAnchor } from '../types';\nimport {\n FileTextIcon,\n ImageIcon,\n Link2Icon,\n LockIcon,\n MessageSquareIcon,\n XIcon,\n} from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { sectionLabel } from '../utils/threads';\nimport { MentionTextarea } from './MentionTextarea';\n\nexport interface ThreadComposerProps {\n /** Existing attachments on the task — used to render chips for already-uploaded files. */\n attachments: Attachment[];\n /** Anchor to attach when posting (set by highlight-to-comment). */\n pendingAnchor: ThreadAnchor | null;\n /** Clear the pending anchor (e.g. user dismisses the highlight). */\n onClearAnchor: () => void;\n /** Submit the new thread. */\n onSubmit: (data: {\n title: string;\n content: string;\n isInternal: boolean;\n anchor: ThreadAnchor | null;\n attachmentIds: string[];\n }) => Promise<void>;\n /** Upload a file as an attachment to this task. Returns the new attachment row. */\n onUpload: (file: File) => Promise<Attachment>;\n /** Add a link/recording as an attachment. Returns the new attachment row. */\n onAddLink: (url: string, name?: string) => Promise<Attachment>;\n /** Whether the current user is allowed to post internal-only threads. */\n isInternalUser: boolean;\n /** When false, render the collapsed \"Start a thread\" button instead. */\n open: boolean;\n /** Open the composer (e.g. user clicks the start button). */\n onOpen: () => void;\n /** Close + reset the composer. */\n onClose: () => void;\n}\n\n/**\n * Composer for new threads. Renders a single button when collapsed; when\n * open, renders an optional anchor strip, optional title input, body\n * textarea with @mentions, attachment buttons + chips, internal toggle,\n * and the Post button.\n */\nexport function ThreadComposer({\n attachments,\n pendingAnchor,\n onClearAnchor,\n onSubmit,\n onUpload,\n onAddLink,\n isInternalUser,\n open,\n onOpen,\n onClose,\n}: ThreadComposerProps) {\n const { internalLabel } = useTaskBoardContext();\n const [title, setTitle] = useState('');\n const [body, setBody] = useState('');\n const [internal, setInternal] = useState(false);\n const [attachmentIds, setAttachmentIds] = useState<string[]>([]);\n const [posting, setPosting] = useState(false);\n\n const closeAndReset = () => {\n setTitle('');\n setBody('');\n setInternal(false);\n setAttachmentIds([]);\n onClose();\n };\n\n const handleSubmit = async () => {\n if (!body.trim()) return;\n setPosting(true);\n try {\n await onSubmit({\n title: title.trim(),\n content: body.trim(),\n isInternal: internal,\n anchor: pendingAnchor,\n attachmentIds,\n });\n closeAndReset();\n } finally {\n setPosting(false);\n }\n };\n\n if (!open) {\n return (\n <div className=\"shrink-0 p-3 border-t border-neutral-100 bg-white\">\n <button\n onClick={onOpen}\n className=\"w-full inline-flex items-center justify-center gap-2 font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] rounded-xl h-10 px-4 shadow-sm text-[12px]\"\n >\n <span className=\"inline-flex items-center justify-center w-4 h-4 rounded-full bg-white/20\">+</span>\n Start a thread\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"shrink-0 p-3 border-t border-neutral-100 bg-white\">\n <div className=\"flex flex-col gap-2\">\n {pendingAnchor && (\n <div className=\"flex items-start gap-2 px-2 py-1.5 rounded-md bg-amber-50 border border-amber-200\">\n <MessageSquareIcon\n size={14}\n strokeWidth={1.5}\n className=\"text-amber-600 shrink-0 mt-0.5\"\n />\n <div className=\"flex-1 min-w-0 text-[11px] text-amber-700\">\n <div className=\"font-medium uppercase tracking-wider text-[9px]\">\n {sectionLabel(pendingAnchor.section)} highlight\n </div>\n <div className=\"truncate italic\">“{pendingAnchor.snippet}”</div>\n </div>\n <button\n type=\"button\"\n onClick={onClearAnchor}\n className=\"text-amber-600 hover:text-amber-900\"\n title=\"Remove highlight\"\n >\n <XIcon size={12} strokeWidth={2} />\n </button>\n </div>\n )}\n <input\n type=\"text\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"Add a title (optional)\"\n className=\"w-full rounded-lg border border-neutral-200 px-3 py-2 text-[13px] font-medium text-neutral-900 placeholder:font-normal placeholder:text-neutral-400 focus:outline-none focus:ring-1 focus:ring-neutral-300 focus:border-neutral-300\"\n />\n <MentionTextarea\n value={body}\n onChange={setBody}\n rows={4}\n placeholder=\"Write something… (type @ to mention)\"\n className=\"w-full rounded-lg border border-neutral-200 px-3 py-2 text-[12px] text-neutral-800 min-h-[100px] focus:outline-none focus:ring-1 focus:ring-neutral-300 focus:border-neutral-300 resize-none\"\n />\n <ComposerAttachments\n attachmentIds={attachmentIds}\n attachments={attachments}\n onChange={setAttachmentIds}\n onUpload={onUpload}\n onAddLink={onAddLink}\n />\n <div className=\"flex items-center justify-between gap-2\">\n <button\n onClick={closeAndReset}\n className=\"text-[12px] font-medium text-neutral-500 hover:text-neutral-900 px-2 h-7 rounded hover:bg-neutral-50\"\n >\n Cancel\n </button>\n <div className=\"flex items-center gap-2\">\n {isInternalUser && (\n <button\n type=\"button\"\n onClick={() => setInternal(!internal)}\n aria-pressed={internal}\n className={`inline-flex items-center gap-1.5 px-2 h-7 rounded text-[12px] font-medium transition-colors ${\n internal\n ? 'bg-neutral-100 text-neutral-700'\n : 'bg-white text-neutral-500 border border-neutral-200 hover:bg-neutral-50'\n }`}\n >\n <LockIcon size={14} strokeWidth={1.5} />\n {internal ? internalLabel : 'Public'}\n </button>\n )}\n <button\n onClick={handleSubmit}\n disabled={!body.trim() || posting}\n className=\"inline-flex items-center justify-center px-3 h-7 rounded-lg text-[12px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] disabled:opacity-50\"\n >\n {posting ? 'Posting...' : 'Post'}\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction ComposerAttachments({\n attachmentIds,\n attachments,\n onChange,\n onUpload,\n onAddLink,\n}: {\n attachmentIds: string[];\n attachments: Attachment[];\n onChange: (ids: string[]) => void;\n onUpload: (file: File) => Promise<Attachment>;\n onAddLink: (url: string, name?: string) => Promise<Attachment>;\n}) {\n const [busy, setBusy] = useState(false);\n const [linkOpen, setLinkOpen] = useState(false);\n const [linkUrl, setLinkUrl] = useState('');\n const [linkName, setLinkName] = useState('');\n const imageRef = useRef<HTMLInputElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n\n const selected = attachmentIds\n .map((id) => attachments.find((a) => a.id === id))\n .filter((a): a is Attachment => Boolean(a));\n\n const upload = async (file: File) => {\n setBusy(true);\n try {\n const created = await onUpload(file);\n onChange([...attachmentIds, created.id]);\n } finally {\n setBusy(false);\n }\n };\n\n const submitLink = async () => {\n if (!linkUrl.trim()) return;\n setBusy(true);\n try {\n const created = await onAddLink(linkUrl.trim(), linkName.trim() || undefined);\n onChange([...attachmentIds, created.id]);\n setLinkUrl('');\n setLinkName('');\n setLinkOpen(false);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <>\n {selected.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {selected.map((a) => {\n const IconC =\n a.kind === 'image' ? ImageIcon : a.kind === 'link' ? Link2Icon : FileTextIcon;\n return (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 text-[11px] text-neutral-700 bg-neutral-100 border border-neutral-200 rounded-md px-2 py-1 max-w-full\"\n >\n <IconC size={12} strokeWidth={1.5} />\n <span className=\"truncate max-w-[180px]\">{a.name}</span>\n <button\n type=\"button\"\n onClick={() => onChange(attachmentIds.filter((id) => id !== a.id))}\n className=\"text-neutral-400 hover:text-neutral-700\"\n >\n <XIcon size={12} strokeWidth={2} />\n </button>\n </span>\n );\n })}\n </div>\n )}\n\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => imageRef.current?.click()}\n className=\"w-7 h-7 rounded hover:bg-neutral-100 text-neutral-500 hover:text-neutral-900 flex items-center justify-center disabled:opacity-50\"\n aria-label=\"Attach image\"\n title=\"Attach image\"\n >\n <ImageIcon size={14} strokeWidth={1.5} />\n </button>\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => fileRef.current?.click()}\n className=\"w-7 h-7 rounded hover:bg-neutral-100 text-neutral-500 hover:text-neutral-900 flex items-center justify-center disabled:opacity-50\"\n aria-label=\"Attach file\"\n title=\"Attach file\"\n >\n <FileTextIcon size={14} strokeWidth={1.5} />\n </button>\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => setLinkOpen((v) => !v)}\n className=\"w-7 h-7 rounded hover:bg-neutral-100 text-neutral-500 hover:text-neutral-900 flex items-center justify-center disabled:opacity-50\"\n aria-label=\"Attach link\"\n title=\"Attach link\"\n >\n <Link2Icon size={14} strokeWidth={1.5} />\n </button>\n {busy && <span className=\"text-[10px] text-neutral-400 ml-1\">Uploading…</span>}\n </div>\n\n {linkOpen && (\n <div className=\"rounded-md border border-neutral-200 p-2 flex flex-col gap-1.5\">\n <input\n type=\"url\"\n value={linkUrl}\n onChange={(e) => setLinkUrl(e.target.value)}\n placeholder=\"https://…\"\n className=\"text-[12px] px-2 py-1 border border-neutral-200 rounded focus:outline-none focus:ring-1 focus:ring-neutral-300\"\n />\n <input\n type=\"text\"\n value={linkName}\n onChange={(e) => setLinkName(e.target.value)}\n placeholder=\"Title (optional)\"\n className=\"text-[12px] px-2 py-1 border border-neutral-200 rounded focus:outline-none focus:ring-1 focus:ring-neutral-300\"\n />\n <div className=\"flex justify-end gap-1.5\">\n <button\n type=\"button\"\n onClick={() => {\n setLinkOpen(false);\n setLinkUrl('');\n setLinkName('');\n }}\n className=\"text-[11px] text-neutral-500 hover:text-neutral-900 px-2 h-6 rounded hover:bg-neutral-50\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={submitLink}\n disabled={!linkUrl.trim() || busy}\n className=\"text-[11px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] disabled:opacity-50 px-2 h-6 rounded\"\n >\n Add\n </button>\n </div>\n </div>\n )}\n\n <input\n ref={imageRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) upload(f);\n e.target.value = '';\n }}\n />\n <input\n ref={fileRef}\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) upload(f);\n e.target.value = '';\n }}\n />\n </>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { ThreadAnchor, ThreadStatus } from '../types';\nimport {\n ArrowLeftIcon,\n CheckCircle2Icon,\n LockIcon,\n MessageSquareIcon,\n RotateCcwIcon,\n} from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { getInitials } from '../utils/helpers';\nimport { type Thread, sectionLabel, timeAgo } from '../utils/threads';\nimport { MentionText } from './MentionText';\nimport { MentionTextarea } from './MentionTextarea';\nimport { ContextPill } from './ContextPill';\n\nexport interface ThreadDetailViewProps {\n thread: Thread;\n onBack: () => void;\n onReply: (content: string, isInternal: boolean) => Promise<void>;\n onUpdateThread: (body: { title?: string; thread_status?: ThreadStatus }) => Promise<void>;\n onAnchorClick: (anchor: ThreadAnchor) => void;\n /** Whether the current user can post internal-only replies. */\n isInternalUser: boolean;\n}\n\n/** Detail view shown inside the threads panel when a thread card is clicked. */\nexport function ThreadDetailView({\n thread,\n onBack,\n onReply,\n onUpdateThread,\n onAnchorClick,\n isInternalUser,\n}: ThreadDetailViewProps) {\n const { internalLabel } = useTaskBoardContext();\n const [body, setBody] = useState('');\n const [internal, setInternal] = useState(false);\n const [posting, setPosting] = useState(false);\n const [editingTitle, setEditingTitle] = useState(false);\n const [titleDraft, setTitleDraft] = useState(thread.title);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n setTitleDraft(thread.title);\n }, [thread.title]);\n\n const submit = async () => {\n if (!body.trim()) return;\n setPosting(true);\n try {\n await onReply(body.trim(), internal);\n setBody('');\n setInternal(false);\n setTimeout(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, 100);\n } finally {\n setPosting(false);\n }\n };\n\n const commitTitle = async () => {\n setEditingTitle(false);\n const next = titleDraft.trim();\n if (next && next !== thread.title) {\n await onUpdateThread({ title: next });\n } else {\n setTitleDraft(thread.title);\n }\n };\n\n const toggleStatus = async () => {\n const next: ThreadStatus = thread.status === 'complete' ? 'active' : 'complete';\n await onUpdateThread({ thread_status: next });\n };\n\n const isComplete = thread.status === 'complete';\n\n return (\n <>\n {/* Detail header */}\n <div className=\"shrink-0 bg-white px-4 py-3 border-b border-neutral-100\">\n <div className=\"flex items-start justify-between gap-4\">\n <button\n onClick={onBack}\n className=\"inline-flex items-center gap-2 px-2.5 py-1.5 -ml-2 rounded-lg text-[12px] font-medium text-neutral-500 hover:text-neutral-900 hover:bg-neutral-50\"\n >\n <ArrowLeftIcon size={14} strokeWidth={1.5} />\n <span>All threads</span>\n </button>\n <button\n type=\"button\"\n onClick={toggleStatus}\n className=\"inline-flex items-center justify-center gap-1.5 text-[12px] font-medium text-neutral-600 hover:text-neutral-900 px-3 h-8 rounded-xl border border-neutral-200 bg-white hover:bg-neutral-50\"\n >\n {isComplete ? (\n <>\n <RotateCcwIcon size={12} strokeWidth={1.5} />\n Reopen\n </>\n ) : (\n <>\n <CheckCircle2Icon size={12} strokeWidth={1.5} />\n Mark complete\n </>\n )}\n </button>\n </div>\n {editingTitle ? (\n <input\n value={titleDraft}\n onChange={(e) => setTitleDraft(e.target.value)}\n onBlur={commitTitle}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.target as HTMLInputElement).blur();\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n setTitleDraft(thread.title);\n setEditingTitle(false);\n }\n }}\n autoFocus\n className=\"mt-2 w-full text-[15px] font-semibold text-neutral-900 leading-snug bg-transparent border-b border-[#FF5E00] focus:outline-none -mx-1 px-1\"\n />\n ) : (\n <h3\n onClick={() => setEditingTitle(true)}\n className=\"mt-2 text-[15px] font-semibold text-neutral-900 leading-snug cursor-text rounded -mx-1 px-1 hover:bg-neutral-50/60\"\n title=\"Click to edit\"\n >\n {thread.title}\n </h3>\n )}\n {thread.anchor && (\n <div className=\"mt-2\">\n <ContextPill\n variant=\"amber\"\n icon={MessageSquareIcon}\n label={`Highlight · ${sectionLabel(thread.anchor.section)}`}\n onClick={() => thread.anchor && onAnchorClick(thread.anchor)}\n />\n </div>\n )}\n </div>\n\n {/* Messages */}\n <div className=\"flex-1 overflow-y-auto p-3 flex flex-col gap-4\">\n <ThreadMessage\n authorName={thread.author_name}\n createdAt={thread.created_at}\n content={thread.rawContent}\n isInternal={thread.is_internal}\n internalLabel={internalLabel}\n />\n {thread.replies.map((r) => (\n <ThreadMessage\n key={r.id}\n authorName={r.author_name}\n createdAt={r.created_at}\n content={r.content}\n isInternal={r.is_internal}\n internalLabel={internalLabel}\n />\n ))}\n <div ref={messagesEndRef} />\n </div>\n\n {/* Reply composer */}\n <div className=\"shrink-0 p-3 border-t border-neutral-100 bg-white\">\n <MentionTextarea\n value={body}\n onChange={setBody}\n rows={3}\n placeholder=\"Reply… (type @ to mention)\"\n className=\"w-full rounded-lg border border-neutral-200 px-3 py-2 text-[12px] text-neutral-800 min-h-[80px] focus:outline-none focus:ring-1 focus:ring-neutral-300 focus:border-neutral-300 resize-none\"\n />\n <div className=\"flex items-center justify-end gap-2 mt-2\">\n {isInternalUser && (\n <button\n type=\"button\"\n onClick={() => setInternal(!internal)}\n aria-pressed={internal}\n className={`inline-flex items-center gap-1.5 px-2 h-7 rounded text-[12px] font-medium transition-colors ${\n internal\n ? 'bg-neutral-100 text-neutral-700'\n : 'bg-white text-neutral-500 border border-neutral-200 hover:bg-neutral-50'\n }`}\n >\n <LockIcon size={14} strokeWidth={1.5} />\n {internal ? internalLabel : 'Public'}\n </button>\n )}\n <button\n onClick={submit}\n disabled={!body.trim() || posting}\n className=\"inline-flex items-center justify-center px-3 h-7 rounded-lg text-[12px] font-medium text-white bg-[#FF5E00] hover:bg-[#E05200] disabled:opacity-50\"\n >\n {posting ? 'Posting...' : 'Reply'}\n </button>\n </div>\n </div>\n </>\n );\n}\n\nfunction ThreadMessage({\n authorName,\n createdAt,\n content,\n isInternal,\n internalLabel,\n}: {\n authorName: string;\n createdAt: string;\n content: string;\n isInternal: boolean;\n internalLabel: string;\n}) {\n const initials = getInitials(authorName || '?');\n return (\n <div className=\"flex gap-2.5\">\n <div\n className={`w-7 h-7 rounded-full flex items-center justify-center text-[10px] font-semibold shrink-0 ${\n isInternal ? 'bg-neutral-200 text-neutral-700' : 'bg-[#FF5E00] text-white'\n }`}\n >\n {initials}\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-0.5 flex-wrap\">\n <span className=\"text-[13px] font-medium text-neutral-900\">{authorName}</span>\n <span className=\"text-[10px] text-neutral-400\">{timeAgo(createdAt)}</span>\n {isInternal && (\n <span className=\"text-[10px] text-neutral-500 bg-neutral-100 px-1.5 py-0.5 rounded inline-flex items-center gap-1\">\n <LockIcon size={10} strokeWidth={1.5} />\n {internalLabel}\n </span>\n )}\n </div>\n <div className=\"text-[12px] text-neutral-700 leading-relaxed whitespace-pre-wrap\">\n <MentionText text={content} />\n </div>\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { MessageSquareIcon } from '../icons';\nimport type { BubbleState } from '../hooks/useHighlightAnchor';\n\nexport interface HighlightBubbleProps {\n bubble: BubbleState | null;\n /** Called when the user clicks the bubble to start a new anchored thread. */\n onComment: () => void;\n}\n\n/**\n * Floating \"Comment\" button shown above a text selection inside a\n * `[data-section]` block. The page should render this once at top level\n * and pass `bubble` / `onComment` from `useHighlightAnchor`.\n *\n * Bug #1 fix: onMouseDown.preventDefault keeps focus on the selection so\n * the snippet survives until onClick reads it.\n */\nexport function HighlightBubble({ bubble, onComment }: HighlightBubbleProps) {\n if (!bubble) return null;\n\n return (\n <div\n data-annot-bubble\n style={{\n position: 'absolute',\n left: bubble.x,\n top: bubble.y,\n transform: 'translate(-50%, -100%)',\n }}\n className=\"z-[90] pointer-events-auto\"\n >\n <button\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={onComment}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-neutral-900 text-white text-[12px] font-medium shadow-lg hover:bg-neutral-800\"\n >\n <MessageSquareIcon size={14} strokeWidth={1.5} />\n Comment\n </button>\n </div>\n );\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Question, QuestionStatus } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\nexport interface UseTaskQuestionsResult {\n questions: Question[];\n loading: boolean;\n /** Re-fetch from the server. Use after mutations to refresh state. */\n refresh: () => Promise<void>;\n /** Optimistic local replace (e.g. when the parent page re-fetches the whole task). */\n setQuestions: (next: Question[]) => void;\n\n createQuestion: (text: string) => Promise<void>;\n updateQuestion: (questionId: string, text: string) => Promise<void>;\n setStatus: (questionId: string, status: QuestionStatus) => Promise<void>;\n deleteQuestion: (questionId: string) => Promise<void>;\n addReply: (questionId: string, content: string) => Promise<void>;\n deleteReply: (questionId: string, replyId: string) => Promise<void>;\n}\n\n/**\n * Manage the structured Outstanding Questions list for a single task.\n *\n * The hook owns its own loading state and re-fetches after each mutation\n * so the parent component can stay simple. Pass `initial` from the\n * embedded `TaskDetailResponse.questions` to avoid an extra request on\n * mount.\n */\nexport function useTaskQuestions(taskId: string | null, initial?: Question[]): UseTaskQuestionsResult {\n const { service } = useTaskBoardContext();\n const [questions, setQuestions] = useState<Question[]>(initial ?? []);\n const [loading, setLoading] = useState(false);\n\n const refresh = useCallback(async () => {\n if (!taskId) return;\n setLoading(true);\n try {\n const list = await service.listQuestions(taskId);\n setQuestions(list);\n } finally {\n setLoading(false);\n }\n }, [service, taskId]);\n\n // Hydrate on mount when no `initial` was passed.\n useEffect(() => {\n if (initial !== undefined) return;\n if (!taskId) return;\n refresh();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [taskId]);\n\n const createQuestion = useCallback(\n async (text: string) => {\n if (!taskId) return;\n await service.createQuestion(taskId, { text });\n await refresh();\n },\n [service, taskId, refresh]\n );\n\n const updateQuestion = useCallback(\n async (questionId: string, text: string) => {\n if (!taskId) return;\n await service.updateQuestion(taskId, questionId, { text });\n await refresh();\n },\n [service, taskId, refresh]\n );\n\n const setStatus = useCallback(\n async (questionId: string, status: QuestionStatus) => {\n if (!taskId) return;\n await service.updateQuestion(taskId, questionId, { status });\n await refresh();\n },\n [service, taskId, refresh]\n );\n\n const deleteQuestion = useCallback(\n async (questionId: string) => {\n if (!taskId) return;\n await service.deleteQuestion(taskId, questionId);\n await refresh();\n },\n [service, taskId, refresh]\n );\n\n const addReply = useCallback(\n async (questionId: string, content: string) => {\n if (!taskId) return;\n await service.addQuestionReply(taskId, questionId, { content });\n await refresh();\n },\n [service, taskId, refresh]\n );\n\n const deleteReply = useCallback(\n async (questionId: string, replyId: string) => {\n if (!taskId) return;\n await service.deleteQuestionReply(taskId, questionId, replyId);\n await refresh();\n },\n [service, taskId, refresh]\n );\n\n return {\n questions,\n loading,\n refresh,\n setQuestions,\n createQuestion,\n updateQuestion,\n setStatus,\n deleteQuestion,\n addReply,\n deleteReply,\n };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Attachment, CreateLinkAttachmentPayload } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\nexport interface UseTaskAttachmentsResult {\n attachments: Attachment[];\n loading: boolean;\n /** Re-fetch from the server. */\n refresh: () => Promise<void>;\n setAttachments: (next: Attachment[]) => void;\n\n /** Upload a single file (image or document). Returns the new attachment. */\n uploadFile: (file: File) => Promise<Attachment>;\n /** Add an external link / recording. Returns the new attachment. */\n addLink: (payload: CreateLinkAttachmentPayload) => Promise<Attachment>;\n /** Delete an attachment (and its underlying GCS object, if any). */\n remove: (attachmentId: string) => Promise<void>;\n}\n\n/**\n * Manage the attachments collection for a single task.\n *\n * Pass `initial` from the embedded `TaskDetailResponse.attachments` to\n * avoid an extra request on mount.\n */\nexport function useTaskAttachments(taskId: string | null, initial?: Attachment[]): UseTaskAttachmentsResult {\n const { service } = useTaskBoardContext();\n const [attachments, setAttachments] = useState<Attachment[]>(initial ?? []);\n const [loading, setLoading] = useState(false);\n\n const refresh = useCallback(async () => {\n if (!taskId) return;\n setLoading(true);\n try {\n const list = await service.listAttachments(taskId);\n setAttachments(list);\n } finally {\n setLoading(false);\n }\n }, [service, taskId]);\n\n useEffect(() => {\n if (initial !== undefined) return;\n if (!taskId) return;\n refresh();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [taskId]);\n\n const uploadFile = useCallback(\n async (file: File): Promise<Attachment> => {\n if (!taskId) throw new Error('No taskId');\n const created = await service.uploadAttachment(taskId, file);\n await refresh();\n return created;\n },\n [service, taskId, refresh]\n );\n\n const addLink = useCallback(\n async (payload: CreateLinkAttachmentPayload): Promise<Attachment> => {\n if (!taskId) throw new Error('No taskId');\n const created = await service.addLinkAttachment(taskId, payload);\n await refresh();\n return created;\n },\n [service, taskId, refresh]\n );\n\n const remove = useCallback(\n async (attachmentId: string) => {\n if (!taskId) return;\n await service.deleteAttachment(taskId, attachmentId);\n await refresh();\n },\n [service, taskId, refresh]\n );\n\n return { attachments, loading, refresh, setAttachments, uploadFile, addLink, remove };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { SectionKey, ThreadAnchor } from '../types';\n\nexport interface BubbleState {\n /** X coordinate (page-relative, viewport center of the selection rect). */\n x: number;\n /** Y coordinate (page-relative, scroll-aware). */\n y: number;\n section: SectionKey;\n snippet: string;\n}\n\nexport interface UseHighlightAnchorResult {\n /** Transient bubble state — set when the user has selected text inside a [data-section] block. */\n bubble: BubbleState | null;\n /** Manually clear the bubble (e.g. after user clicks the Comment button). */\n clearBubble: () => void;\n\n /** The anchor pending placement on a new thread, or null. */\n pendingAnchor: ThreadAnchor | null;\n /** Promote the current bubble to a pendingAnchor (the new-thread composer should react to this). */\n beginAnchoredThread: () => ThreadAnchor | null;\n /** Clear `pendingAnchor` after the thread is posted or the composer is dismissed. */\n clearPendingAnchor: () => void;\n\n /** Scroll the anchored section into view and pulse it briefly. Pass to ThreadCard / ThreadDetailView. */\n focusAnchor: (anchor: ThreadAnchor) => void;\n}\n\n/**\n * Wires up highlight-to-comment selection behaviour. The consuming page\n * needs to render the description sections with `data-section={sectionKey}`\n * for the bubble + focusAnchor to find the right element. Pair this hook\n * with `<HighlightBubble bubble={bubble} onComment={beginAnchoredThread} />`\n * and pass `pendingAnchor` / `clearPendingAnchor` to `<ThreadsPanel>`.\n *\n * Bug #1 fix lives in `<HighlightBubble>`: the button uses\n * onMouseDown.preventDefault so clicking it doesn't blow away the selection.\n */\nexport function useHighlightAnchor(): UseHighlightAnchorResult {\n const [bubble, setBubble] = useState<BubbleState | null>(null);\n const [pendingAnchor, setPendingAnchor] = useState<ThreadAnchor | null>(null);\n\n useEffect(() => {\n const onMouseUp = () => {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0 || sel.isCollapsed) {\n setBubble(null);\n return;\n }\n const text = sel.toString().trim();\n if (!text) {\n setBubble(null);\n return;\n }\n const range = sel.getRangeAt(0);\n const container = range.commonAncestorContainer;\n const el =\n container.nodeType === 1\n ? (container as HTMLElement)\n : container.parentElement;\n const sectionEl = el?.closest('[data-section]') as HTMLElement | null;\n if (!sectionEl) {\n setBubble(null);\n return;\n }\n const sectionKey = sectionEl.dataset.section as SectionKey | undefined;\n if (!sectionKey) {\n setBubble(null);\n return;\n }\n const rect = range.getBoundingClientRect();\n setBubble({\n x: rect.left + rect.width / 2,\n y: rect.top - 8 + window.scrollY,\n section: sectionKey,\n snippet: text.slice(0, 200),\n });\n };\n\n const onClickAway = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n // Don't dismiss if the click landed on our bubble — the bubble's onClick\n // should run first.\n if (target.closest('[data-annot-bubble]')) return;\n // If the click clears the selection, drop the bubble after the browser\n // has updated the selection state.\n setTimeout(() => {\n const sel = window.getSelection();\n if (!sel || sel.isCollapsed) setBubble(null);\n }, 0);\n };\n\n document.addEventListener('mouseup', onMouseUp);\n document.addEventListener('mousedown', onClickAway);\n return () => {\n document.removeEventListener('mouseup', onMouseUp);\n document.removeEventListener('mousedown', onClickAway);\n };\n }, []);\n\n const clearBubble = useCallback(() => setBubble(null), []);\n const clearPendingAnchor = useCallback(() => setPendingAnchor(null), []);\n\n const beginAnchoredThread = useCallback((): ThreadAnchor | null => {\n if (!bubble) return null;\n const anchor: ThreadAnchor = { section: bubble.section, snippet: bubble.snippet };\n setPendingAnchor(anchor);\n setBubble(null);\n return anchor;\n }, [bubble]);\n\n const focusAnchor = useCallback((anchor: ThreadAnchor) => {\n const el = document.querySelector(`[data-section=\"${anchor.section}\"]`);\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.classList.add('ring-2', 'ring-amber-300', 'rounded-lg', 'transition-all');\n setTimeout(() => {\n el.classList.remove('ring-2', 'ring-amber-300', 'rounded-lg');\n }, 1500);\n }, []);\n\n return {\n bubble,\n clearBubble,\n pendingAnchor,\n beginAnchoredThread,\n clearPendingAnchor,\n focusAnchor,\n };\n}\n"],"mappings":"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","names":["import_react","import_dnd","import_react","import_react","import_react","import_jsx_runtime","import_react","import_dnd","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","TaskCard","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","handleClick","import_react","import_jsx_runtime","import_react","import_react","comments","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_react","import_jsx_runtime","React","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","timeAgo","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_react","import_jsx_runtime"]}
|