@emberai-engg/task-board 0.5.1 → 0.6.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/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","../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&apos;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 /** Focus the underlying textarea on mount. Use for composers that should be\n * immediately writable (e.g. when the user opens the new-thread composer\n * from a highlight-to-comment selection). */\n autoFocus?: boolean;\n}\n\nexport function MentionTextarea({\n value,\n onChange,\n onKeyDown,\n placeholder = \"\",\n rows = 2,\n className = \"\",\n disabled = false,\n autoFocus = 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 autoFocus={autoFocus}\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 // Edit a single comment (thread root or reply). Author-only on the backend.\n const handleEditMessage = async (messageId: string, content: string) => {\n try {\n await service.editComment(taskId, messageId, { content });\n await fetchTask();\n } catch {\n // silent\n }\n };\n\n // Delete a single reply. The backend keeps the parent thread intact.\n const handleDeleteMessage = async (messageId: string) => {\n try {\n await service.deleteComment(taskId, messageId);\n await fetchTask();\n } catch {\n // silent\n }\n };\n\n // Delete a whole thread (root + replies). Backend cascades; close the detail\n // view first so we don't try to render a thread that's gone.\n const handleDeleteThread = async (threadId: string) => {\n try {\n await service.deleteComment(taskId, threadId);\n setOpenThreadId(null);\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 // Group anchors by section for the inline <mark> highlights.\n const anchorsBySection = useMemo(() => {\n const map: Record<string, Array<{ snippet: string; threadId: string }>> = {};\n for (const t of threads) {\n if (!t.anchor) continue;\n const key = t.anchor.section;\n if (!map[key]) map[key] = [];\n map[key].push({ snippet: t.anchor.snippet, threadId: t.id });\n }\n return map;\n }, [threads]);\n\n // Open a thread in the right panel — used both when a description-section\n // <mark> is clicked and when an anchor pill is clicked elsewhere.\n const openThreadFromAnchor = useCallback(\n (threadId: string) => {\n setOpenThreadId(threadId);\n if (!panelOpen) {\n setPanelOpen(true);\n try {\n window.localStorage.setItem(PANEL_OPEN_KEY, 'true');\n } catch {\n // ignore\n }\n }\n },\n [panelOpen]\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 anchors={anchorsBySection[section.key]}\n onAnchorClick={openThreadFromAnchor}\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 currentUsername={user.username}\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 onEditMessage={handleEditMessage}\n onDeleteMessage={handleDeleteMessage}\n onDeleteThread={handleDeleteThread}\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 /** Whether the thread root has been edited at least once. */\n edited?: boolean;\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 edited?: 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 edited: !!r.edited,\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 edited: !!c.edited,\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, { useEffect, useRef, 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 /** Threads anchored to this section — drives the inline `<mark>` highlights. */\n anchors?: Array<{ snippet: string; threadId: string }>;\n /** Click handler when the user clicks on a highlighted snippet. */\n onAnchorClick?: (threadId: string) => void;\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 * - inline `<mark class=\"eb-tb-annot\">` wrapping each anchor's snippet\n * (clicking the mark opens that thread in the right panel)\n */\nexport function DescriptionSection({\n sectionKey,\n label,\n placeholder,\n value,\n onChange,\n status,\n onStatusChange,\n saving,\n anchors,\n onAnchorClick,\n}: DescriptionSectionProps) {\n const [editing, setEditing] = useState(false);\n const [openHelp, setOpenHelp] = useState<null | SectionStatus>(null);\n const readRef = useRef<HTMLDivElement>(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 // Walk the rendered MarkdownView output and wrap each anchor's snippet in\n // <mark class=\"eb-tb-annot\"> so the source text shows where threads attach.\n // Done as a post-render DOM pass so MarkdownView itself stays untouched.\n useEffect(() => {\n if (editing) return;\n const root = readRef.current;\n if (!root) return;\n\n // Clear marks from a previous pass before re-applying.\n root.querySelectorAll('mark.eb-tb-annot').forEach((m) => {\n const text = m.textContent || '';\n m.replaceWith(document.createTextNode(text));\n });\n root.normalize();\n\n if (!anchors || anchors.length === 0) return;\n\n for (const anchor of anchors) {\n const snippet = anchor.snippet?.trim();\n if (!snippet) continue;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n let node = walker.nextNode();\n while (node) {\n const txt = node.textContent || '';\n const idx = txt.indexOf(snippet);\n if (idx !== -1) {\n const range = document.createRange();\n try {\n range.setStart(node, idx);\n range.setEnd(node, idx + snippet.length);\n const mark = document.createElement('mark');\n mark.className = 'eb-tb-annot';\n mark.dataset.threadId = anchor.threadId;\n range.surroundContents(mark);\n } catch {\n // surroundContents throws if the range straddles element boundaries;\n // we just skip that anchor rather than crash.\n }\n break;\n }\n node = walker.nextNode();\n }\n }\n }, [anchors, value, editing]);\n\n // Click on a marked span opens its thread; click anywhere else starts edit.\n const handleReadClick = (e: React.MouseEvent) => {\n const target = e.target as HTMLElement | null;\n const mark = target?.closest('mark.eb-tb-annot') as HTMLElement | null;\n if (mark && mark.dataset.threadId && onAnchorClick) {\n e.preventDefault();\n e.stopPropagation();\n onAnchorClick(mark.dataset.threadId);\n return;\n }\n startEdit();\n };\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 <div\n ref={readRef}\n role=\"button\"\n tabIndex={0}\n onClick={handleReadClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n startEdit();\n }\n }}\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 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#FF5E00]/20\"\n >\n {hasContent ? (\n <MarkdownView content={value} className=\"text-[13px]\" />\n ) : (\n <p className=\"text-[13px] text-neutral-400 italic\">{placeholder}</p>\n )}\n </div>\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, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\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 &amp; 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 /** Username of the logged-in user — used by the detail view to flag own messages. */\n currentUsername: string;\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 /** Edit a single comment (thread root or reply). Author-only on the backend. */\n onEditMessage: (messageId: string, content: string) => Promise<void>;\n /** Delete a single reply. Backend keeps the parent thread intact. */\n onDeleteMessage: (messageId: string) => Promise<void>;\n /** Delete the whole thread (root + replies). Backend cascades. */\n onDeleteThread: (threadId: string) => 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 currentUsername,\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 onEditMessage,\n onDeleteMessage,\n onDeleteThread,\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 currentUsername={currentUsername}\n onBack={() => onOpenThread(null)}\n onReply={(content, isInternal) => onCreateReply(openThread.id, content, isInternal)}\n onUpdateThread={(body) => onUpdateThread(openThread.id, body)}\n onEditMessage={onEditMessage}\n onDeleteMessage={onDeleteMessage}\n onDeleteThread={onDeleteThread}\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\">&ldquo;{pendingAnchor.snippet}&rdquo;</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 autoFocus\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 MoreVerticalIcon,\n PencilIcon,\n RotateCcwIcon,\n TrashIcon,\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 /** Username of the logged-in user, for own-message detection. */\n currentUsername: string;\n onBack: () => void;\n onReply: (content: string, isInternal: boolean) => Promise<void>;\n onUpdateThread: (body: { title?: string; thread_status?: ThreadStatus }) => Promise<void>;\n /** Edit a single message (thread root or reply). Author-only on the backend. */\n onEditMessage: (messageId: string, content: string) => Promise<void>;\n /** Delete a single reply. Backend keeps the parent thread intact. */\n onDeleteMessage: (messageId: string) => Promise<void>;\n /** Delete the whole thread (root + replies). Backend cascades. */\n onDeleteThread: (threadId: string) => 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 currentUsername,\n onBack,\n onReply,\n onUpdateThread,\n onEditMessage,\n onDeleteMessage,\n onDeleteThread,\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 [editingMessageId, setEditingMessageId] = useState<string | null>(null);\n const [editDraft, setEditDraft] = useState('');\n const [savingEdit, setSavingEdit] = useState(false);\n const [headerMenuOpen, setHeaderMenuOpen] = useState(false);\n const headerMenuRef = useRef<HTMLDivElement>(null);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n setTitleDraft(thread.title);\n }, [thread.title]);\n\n // Reset inline-edit state when switching threads.\n useEffect(() => {\n setEditingMessageId(null);\n setEditDraft('');\n }, [thread.id]);\n\n // Outside-click closes the header kebab.\n useEffect(() => {\n if (!headerMenuOpen) return;\n const onClick = (e: MouseEvent) => {\n if (headerMenuRef.current && !headerMenuRef.current.contains(e.target as Node)) {\n setHeaderMenuOpen(false);\n }\n };\n document.addEventListener('mousedown', onClick);\n return () => document.removeEventListener('mousedown', onClick);\n }, [headerMenuOpen]);\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 startEditMessage = (id: string, content: string) => {\n setEditingMessageId(id);\n setEditDraft(content);\n };\n\n const cancelEditMessage = () => {\n setEditingMessageId(null);\n setEditDraft('');\n };\n\n const commitEditMessage = async () => {\n const id = editingMessageId;\n const next = editDraft.trim();\n if (!id || !next) {\n cancelEditMessage();\n return;\n }\n setSavingEdit(true);\n try {\n await onEditMessage(id, next);\n cancelEditMessage();\n } finally {\n setSavingEdit(false);\n }\n };\n\n const handleDeleteMessage = async (id: string, isThreadRoot: boolean) => {\n const msg = isThreadRoot\n ? 'Delete this thread and all of its replies? This cannot be undone.'\n : 'Delete this message? This cannot be undone.';\n if (!confirm(msg)) return;\n if (isThreadRoot) {\n await onDeleteThread(id);\n } else {\n await onDeleteMessage(id);\n }\n };\n\n const isComplete = thread.status === 'complete';\n const isThreadAuthor = thread.author_id === currentUsername;\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 <div className=\"flex items-center gap-1.5 shrink-0\">\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 ref={headerMenuRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setHeaderMenuOpen((v) => !v)}\n aria-label=\"Thread actions\"\n className=\"w-8 h-8 flex items-center justify-center rounded-xl border border-neutral-200 bg-white text-neutral-500 hover:text-neutral-900 hover:border-neutral-300 transition-colors\"\n >\n <MoreVerticalIcon size={14} strokeWidth={1.5} />\n </button>\n {headerMenuOpen && (\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 {isThreadAuthor && (\n <button\n type=\"button\"\n onClick={() => {\n setHeaderMenuOpen(false);\n setEditingTitle(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 <PencilIcon size={14} strokeWidth={1.5} />\n Edit title\n </button>\n )}\n <button\n type=\"button\"\n onClick={async () => {\n setHeaderMenuOpen(false);\n if (\n !confirm(\n 'Delete this thread and all of its replies? This cannot be undone.'\n )\n )\n return;\n await onDeleteThread(thread.id);\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 thread\n </button>\n </div>\n )}\n </div>\n </div>\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 {/* Original message */}\n {editingMessageId === thread.id ? (\n <ThreadMessageEditor\n authorName={thread.author_name}\n isInternal={thread.is_internal}\n value={editDraft}\n onChange={setEditDraft}\n onCommit={commitEditMessage}\n onCancel={cancelEditMessage}\n saving={savingEdit}\n />\n ) : (\n <ThreadMessage\n authorName={thread.author_name}\n createdAt={thread.created_at}\n content={thread.rawContent}\n isInternal={thread.is_internal}\n edited={thread.edited}\n isOwn={isThreadAuthor}\n internalLabel={internalLabel}\n onEdit={() => startEditMessage(thread.id, thread.rawContent)}\n onDelete={() => handleDeleteMessage(thread.id, true)}\n />\n )}\n\n {thread.replies.map((r) =>\n editingMessageId === r.id ? (\n <ThreadMessageEditor\n key={r.id}\n authorName={r.author_name}\n isInternal={r.is_internal}\n value={editDraft}\n onChange={setEditDraft}\n onCommit={commitEditMessage}\n onCancel={cancelEditMessage}\n saving={savingEdit}\n />\n ) : (\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 edited={r.edited}\n isOwn={r.author_id === currentUsername}\n internalLabel={internalLabel}\n onEdit={() => startEditMessage(r.id, r.content)}\n onDelete={() => handleDeleteMessage(r.id, false)}\n />\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\n/**\n * Read-mode rendering of a single thread message (root or reply). When `isOwn`\n * + handlers are passed, a hover kebab exposes Edit / Delete.\n */\nfunction ThreadMessage({\n authorName,\n createdAt,\n content,\n isInternal,\n edited = false,\n isOwn = false,\n internalLabel,\n onEdit,\n onDelete,\n}: {\n authorName: string;\n createdAt: string;\n content: string;\n isInternal: boolean;\n edited?: boolean;\n isOwn?: boolean;\n internalLabel: string;\n onEdit?: () => void;\n onDelete?: () => void;\n}) {\n const initials = getInitials(authorName || '?');\n const [menuOpen, setMenuOpen] = useState(false);\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 showActions = isOwn && (onEdit || onDelete);\n\n return (\n <div className=\"group 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 {edited && <span className=\"text-[10px] text-neutral-400 italic\">(edited)</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 {showActions && (\n <div\n ref={menuRef}\n className=\"ml-auto relative opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity\"\n >\n <button\n type=\"button\"\n onClick={() => setMenuOpen((v) => !v)}\n aria-label=\"Message actions\"\n className=\"w-6 h-6 flex items-center justify-center rounded text-neutral-400 hover:text-neutral-700 hover:bg-neutral-100\"\n >\n <MoreVerticalIcon size={12} strokeWidth={1.5} />\n </button>\n {menuOpen && (\n <div className=\"absolute right-0 top-full mt-1 w-36 bg-white border border-neutral-200 rounded-xl shadow-lg py-1 z-30\">\n {onEdit && (\n <button\n type=\"button\"\n onClick={() => {\n setMenuOpen(false);\n onEdit();\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\"\n >\n <PencilIcon size={12} strokeWidth={1.5} />\n Edit\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={() => {\n setMenuOpen(false);\n onDelete();\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\"\n >\n <TrashIcon size={12} strokeWidth={1.5} />\n Delete\n </button>\n )}\n </div>\n )}\n </div>\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\n/**\n * Inline editor for a thread message. Mirrors the read-mode `ThreadMessage`\n * avatar/header layout but swaps the body for a MentionTextarea + Save/Cancel\n * buttons. Cmd/Ctrl+Enter submits, Escape cancels.\n */\nfunction ThreadMessageEditor({\n authorName,\n isInternal,\n value,\n onChange,\n onCommit,\n onCancel,\n saving,\n}: {\n authorName: string;\n isInternal: boolean;\n value: string;\n onChange: (v: string) => void;\n onCommit: () => void;\n onCancel: () => void;\n saving?: boolean;\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 flex flex-col gap-2\">\n <MentionTextarea\n value={value}\n onChange={onChange}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault();\n onCommit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n onCancel();\n }\n }}\n rows={3}\n placeholder=\"Edit message…\"\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 autoFocus\n />\n <div className=\"flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\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 type=\"button\"\n onClick={onCommit}\n disabled={saving || !value.trim()}\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 {saving ? 'Saving...' : 'Save'}\n </button>\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 sectionEl = document.querySelector(`[data-section=\"${anchor.section}\"]`);\n if (!sectionEl) return;\n sectionEl.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // If <DescriptionSection>'s post-render pass wrapped this snippet in a\n // <mark>, pulse just the mark for a tighter visual cue. Otherwise fall\n // back to ringing the whole section so something still flashes.\n const markEl =\n Array.from(sectionEl.querySelectorAll<HTMLElement>('mark.eb-tb-annot')).find((m) =>\n (m.textContent || '').includes(anchor.snippet)\n ) || (sectionEl.querySelector('mark.eb-tb-annot') as HTMLElement | null);\n if (markEl) {\n markEl.classList.add('eb-tb-annot-pulse');\n setTimeout(() => markEl.classList.remove('eb-tb-annot-pulse'), 1500);\n } else {\n sectionEl.classList.add('ring-2', 'ring-amber-300', 'rounded-lg', 'transition-all');\n setTimeout(() => {\n sectionEl.classList.remove('ring-2', 'ring-amber-300', 'rounded-lg');\n }, 1500);\n }\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"]}
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/hooks/useTagPool.ts","../src/components/SkeletonPulse.tsx","../src/components/KanbanColumn.tsx","../src/components/TaskCard.tsx","../src/utils/mentions.ts","../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/TagManagerPopover.tsx","../src/components/OverviewPanel.tsx","../src/components/ListLayout.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// ─── v0.6 additions: workspace tag pool + Tasks/Overview + Board/List ───\nexport { TagManagerPopover } from './components/TagManagerPopover';\nexport type { TagManagerPopoverProps } from './components/TagManagerPopover';\nexport { OverviewPanel } from './components/OverviewPanel';\nexport type { OverviewPanelProps } from './components/OverviewPanel';\nexport { ListLayout } from './components/ListLayout';\nexport type { ListLayoutProps } from './components/ListLayout';\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';\nexport { useTagPool } from './hooks/useTagPool';\nexport type { TagPool } from './hooks/useTagPool';\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 // v0.6 additions\n Tag,\n CreateTagPayload,\n UpdateTagPayload,\n ActivityFeedItem,\n OutstandingQuestion,\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 { useTagPool } from '../hooks/useTagPool';\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 { TagManagerPopover } from './TagManagerPopover';\nimport { OverviewPanel } from './OverviewPanel';\nimport { ListLayout } from './ListLayout';\nimport { PlusIcon, XIcon, FeedbackIcon } from '../icons';\n\nconst LAYOUT_KEY = 'taskboard:layout';\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 const tagPool = useTagPool();\n\n const [selectedTask, setSelectedTask] = useState<Task | null>(null);\n const [createForStatus, setCreateForStatus] = useState('');\n const [filterTagIds, setFilterTagIds] = useState<string[]>([]);\n\n // Top-level Tasks / Overview toggle.\n const [view, setView] = useState<'tasks' | 'overview'>('tasks');\n\n // Board / List layout (only meaningful when view === 'tasks'). Persisted.\n const [layout, setLayout] = useState<'board' | 'list'>(() => {\n if (typeof window === 'undefined') return 'board';\n return (window.localStorage.getItem(LAYOUT_KEY) as 'board' | 'list') || 'board';\n });\n useEffect(() => {\n try {\n window.localStorage.setItem(LAYOUT_KEY, layout);\n } catch {\n // ignore\n }\n }, [layout]);\n\n // Card-level tag-manager popover.\n const [tagPopover, setTagPopover] = useState<{ taskId: string; anchor: DOMRect } | null>(null);\n\n // Handle shared task URL (?task=id) — legacy support.\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 () => {\n cancelled = true;\n };\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(\n (result: DropResult) => {\n const { draggableId, source, destination } = result;\n if (!destination) return;\n if (source.droppableId === destination.droppableId && source.index === destination.index) return;\n actions.moveTask(\n draggableId,\n source.droppableId,\n destination.droppableId,\n source.index,\n destination.index\n );\n },\n [actions]\n );\n\n const handleTaskClick = (task: Task) => {\n if (!onTaskOpen) {\n setSelectedTask(task);\n }\n onTaskOpen?.(task);\n actions.markTaskRead(task.id);\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 // Tag pool helpers wired through to the popover.\n const handleApplyTagIds = (taskId: string, nextIds: string[]) => {\n // Optimistic local update across every column.\n board.setTasks((prev) => {\n const next: Record<string, Task[]> = { ...prev };\n for (const status of Object.keys(next)) {\n next[status] = next[status].map((t) =>\n t.id === taskId ? { ...t, applied_tag_ids: nextIds } : t\n );\n }\n return next;\n });\n service.updateTask(taskId, { applied_tag_ids: nextIds }).catch(() => {\n board.setError('Failed to save tags');\n setTimeout(() => board.setError(''), 3000);\n board.fetchTasks();\n });\n };\n\n const popoverTask = tagPopover\n ? Object.values(board.tasks).flat().find((t) => t.id === tagPopover.taskId)\n : undefined;\n\n // Built-in create/detail handlers\n const handleCreateClose = () => setCreateForStatus('');\n const handleCreateDone = () => {\n board.fetchTasks();\n board.showSuccess('Task created');\n };\n const handleDetailClose = () => setSelectedTask(null);\n\n // Board / List layout icon toggle — rendered into FilterBar's right slot.\n const layoutToggle = (\n <div\n role=\"tablist\"\n aria-label=\"Layout\"\n className=\"inline-flex items-center h-9 p-1 rounded-lg border border-neutral-200 bg-white shrink-0\"\n >\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={layout === 'board'}\n aria-label=\"Board view\"\n onClick={() => setLayout('board')}\n className={`w-7 h-7 flex items-center justify-center rounded transition-colors ${\n layout === 'board'\n ? 'bg-neutral-100 text-neutral-900'\n : 'text-neutral-500 hover:text-neutral-900'\n }`}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />\n </svg>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={layout === 'list'}\n aria-label=\"List view\"\n onClick={() => setLayout('list')}\n className={`w-7 h-7 flex items-center justify-center rounded transition-colors ${\n layout === 'list'\n ? 'bg-neutral-100 text-neutral-900'\n : 'text-neutral-500 hover:text-neutral-900'\n }`}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"8\" x2=\"21\" y1=\"6\" y2=\"6\" />\n <line x1=\"8\" x2=\"21\" y1=\"12\" y2=\"12\" />\n <line x1=\"8\" x2=\"21\" y1=\"18\" y2=\"18\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"6\" y2=\"6\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"12\" y2=\"12\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n );\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 {/* Tasks / Overview toggle */}\n <div\n role=\"tablist\"\n aria-label=\"Board view\"\n className=\"inline-flex items-center h-9 sm:h-10 p-1 rounded-lg border border-neutral-200 bg-white\"\n >\n {(['tasks', 'overview'] as const).map((v) => {\n const active = view === v;\n return (\n <button\n key={v}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => setView(v)}\n className={`h-7 sm:h-8 px-3 rounded-md text-xs font-medium transition-colors ${\n active\n ? 'bg-[#FF5E00] text-white'\n : 'text-neutral-600 hover:text-neutral-900'\n }`}\n >\n {v === 'tasks' ? 'Tasks' : 'Overview'}\n </button>\n );\n })}\n </div>\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('draft')}\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&apos;t have access to any projects yet.</p>\n </div>\n </div>\n ) : view === 'overview' ? (\n <OverviewPanel\n availableProjects={board.projects}\n initialProjectSlug={board.selectedProject || 'all'}\n onOpenTask={handleOpenTaskFromNotification}\n />\n ) : (\n <>\n {/* Filter bar (with layout toggle on the right) */}\n <FilterBar\n projects={board.projects}\n selectedProject={board.selectedProject}\n onSelectProject={board.setSelectedProject}\n tagPool={tagPool.tags}\n filterTagIds={filterTagIds}\n onSetFilterTagIds={setFilterTagIds}\n rightSlot={layoutToggle}\n />\n\n {/* Tasks layout */}\n {board.boardLoading ? (\n <BoardSkeleton />\n ) : layout === 'list' ? (\n <ListLayout\n tasks={board.tasks}\n columnTotals={board.columnTotals}\n filterTagIds={filterTagIds}\n tagsById={tagPool.byId}\n onTaskClick={handleTaskClick}\n onAddTag={(e, taskId) => {\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n setTagPopover({ taskId, anchor: rect });\n }}\n onAddTaskToColumn={(statusKey) => setCreateForStatus(statusKey)}\n />\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 =\n filterTagIds.length > 0\n ? allColumnTasks.filter((t) =>\n filterTagIds.some((id) => (t.applied_tag_ids || []).includes(id))\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) => copyShareLink(taskId, board.selectedProject)}\n copiedTaskId={copiedTaskId}\n onLoadMore={() => board.loadMoreTasks(col.key)}\n tagsById={tagPool.byId}\n onAddTag={(e, taskId) => {\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n setTagPopover({ taskId, anchor: rect });\n }}\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\n {/* Card-level tag manager popover */}\n {tagPopover && (\n <TagManagerPopover\n anchor={tagPopover.anchor}\n appliedTagIds={popoverTask?.applied_tag_ids || []}\n pool={tagPool.tags}\n onApplyTagIds={(next) => handleApplyTagIds(tagPopover.taskId, next)}\n onCreateTag={tagPool.create}\n onRenameTag={(id, name) => {\n tagPool.update(id, { name }).catch(() => {});\n }}\n onClose={() => setTagPopover(null)}\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 Tag,\n CreateTaskPayload,\n UpdateTaskPayload,\n CreateCommentPayload,\n EditCommentPayload,\n UpdateThreadPayload,\n CreateQuestionPayload,\n UpdateQuestionPayload,\n CreateQuestionReplyPayload,\n CreateLinkAttachmentPayload,\n CreateTagPayload,\n UpdateTagPayload,\n ActivityFeedItem,\n OutstandingQuestion,\n QuestionStatus,\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 // ─── Workspace tag pool ───\n listTags(): Promise<Tag[]>;\n createTag(data: CreateTagPayload): Promise<Tag>;\n updateTag(tagId: string, data: UpdateTagPayload): Promise<Tag>;\n deleteTag(tagId: string): Promise<void>;\n\n // ─── Overview feed (cross-task activity + outstanding questions) ───\n listActivityFeed(projectSlug?: string, limit?: number): Promise<ActivityFeedItem[]>;\n listOutstandingQuestions(\n projectSlug?: string,\n statusFilter?: QuestionStatus,\n limit?: number\n ): Promise<OutstandingQuestion[]>;\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 // ─── Workspace tag pool ───\n\n async listTags() {\n const { data } = await apiClient.get<Tag[]>(`${basePath}/tags`);\n return data;\n },\n\n async createTag(payload) {\n const { data } = await apiClient.post<Tag>(`${basePath}/tags`, payload);\n return data;\n },\n\n async updateTag(tagId, payload) {\n const { data } = await apiClient.patch<Tag>(`${basePath}/tags/${tagId}`, payload);\n return data;\n },\n\n async deleteTag(tagId) {\n await apiClient.delete(`${basePath}/tags/${tagId}`);\n },\n\n // ─── Overview feed ───\n\n async listActivityFeed(projectSlug, limit = 100) {\n const params = new URLSearchParams();\n if (projectSlug) params.set('project_slug', projectSlug);\n params.set('limit', String(limit));\n const { data } = await apiClient.get<ActivityFeedItem[]>(\n `${basePath}/activity?${params.toString()}`\n );\n return data;\n },\n\n async listOutstandingQuestions(projectSlug, statusFilter, limit = 200) {\n const params = new URLSearchParams();\n if (projectSlug) params.set('project_slug', projectSlug);\n if (statusFilter) params.set('status_filter', statusFilter);\n params.set('limit', String(limit));\n const { data } = await apiClient.get<OutstandingQuestion[]>(\n `${basePath}/questions?${params.toString()}`\n );\n return data;\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: \"draft\", label: \"Draft\", color: \"bg-amber-400\", chip: \"bg-amber-50 text-amber-700\", description: \"Drafted — not yet ready for review\" },\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 technical_details: \"\",\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 { useCallback, useEffect, useMemo, useState } from 'react';\nimport type { Tag } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\n/**\n * Workspace-level tag pool. Every consumer reads from the same server-backed\n * list and mutates through the same CRUD endpoints, so a rename or create on\n * one surface (e.g. the board's tag popover) is instantly reflected on every\n * other surface (e.g. the task detail page) on the next render.\n */\nexport interface TagPool {\n tags: Tag[];\n byId: Map<string, Tag>;\n loading: boolean;\n refresh: () => Promise<void>;\n /** Create a pool tag by name (idempotent — returns the existing one if the name matches). */\n create: (name: string, color?: string) => Promise<Tag | null>;\n /** Rename and/or recolor an existing pool tag. */\n update: (id: string, body: { name?: string; color?: string }) => Promise<Tag | null>;\n /** Delete a pool tag (and remove it from every task that references it). */\n remove: (id: string) => Promise<boolean>;\n}\n\nexport function useTagPool(): TagPool {\n const { service } = useTaskBoardContext();\n const [tags, setTags] = useState<Tag[]>([]);\n const [loading, setLoading] = useState(false);\n\n const refresh = useCallback(async () => {\n setLoading(true);\n try {\n const list = await service.listTags();\n setTags(Array.isArray(list) ? list : []);\n } catch {\n // ignore — leave the previous list in place\n } finally {\n setLoading(false);\n }\n }, [service]);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n const create = useCallback(\n async (name: string, color?: string) => {\n const trimmed = name.trim();\n if (!trimmed) return null;\n try {\n const created = await service.createTag(color ? { name: trimmed, color } : { name: trimmed });\n setTags((prev) => {\n // Dedupe on id — the backend treats create-by-name as idempotent.\n const filtered = prev.filter((t) => t.id !== created.id);\n return [...filtered, created].sort((a, b) => a.name.localeCompare(b.name));\n });\n return created;\n } catch {\n return null;\n }\n },\n [service]\n );\n\n const update = useCallback(\n async (id: string, body: { name?: string; color?: string }) => {\n try {\n const updated = await service.updateTag(id, body);\n setTags((prev) =>\n prev\n .map((t) => (t.id === id ? updated : t))\n .sort((a, b) => a.name.localeCompare(b.name))\n );\n return updated;\n } catch {\n return null;\n }\n },\n [service]\n );\n\n const remove = useCallback(\n async (id: string) => {\n try {\n await service.deleteTag(id);\n setTags((prev) => prev.filter((t) => t.id !== id));\n return true;\n } catch {\n return false;\n }\n },\n [service]\n );\n\n const byId = useMemo(() => new Map(tags.map((t) => [t.id, t])), [tags]);\n return { tags, byId, loading, refresh, create, update, remove };\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 { Tag, 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 /** Workspace tag pool keyed by ID. Forwarded to each TaskCard. */\n tagsById?: Map<string, Tag>;\n /** Click handler for the dashed \"+\" tag button on each card. */\n onAddTag?: (e: React.MouseEvent<HTMLButtonElement>, taskId: string) => 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 tagsById,\n onAddTag,\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 tagsById={tagsById}\n onAddTag={onAddTag}\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 { Tag, Task } from '../types';\nimport { PriorityBadge } from './PriorityBadge';\nimport { TagBadge } from './TagBadge';\nimport { UserAvatar } from './UserAvatar';\nimport { MessageSquareIcon, LinkIcon, CheckIcon, PlusIcon } 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 * Workspace tag pool, keyed by ID. When provided, `task.applied_tag_ids` are\n * resolved through this map; otherwise the card falls back to the legacy\n * string-based `task.tags` field.\n */\n tagsById?: Map<string, Tag>;\n /**\n * Optional handler for the dashed \"+\" tag button on the card. When omitted\n * the button is hidden — keeps existing consumers backwards-compatible.\n */\n onAddTag?: (e: React.MouseEvent<HTMLButtonElement>, taskId: string) => void;\n}\n\nexport const TaskCard = memo(function TaskCard({\n task,\n index,\n onClick,\n onShare,\n copied,\n tagsById,\n onAddTag,\n}: TaskCardProps) {\n // Prefer applied_tag_ids when we have a pool; otherwise fall back to legacy\n // string-based tags so unmigrated tasks still display.\n const appliedFromPool: Tag[] =\n tagsById && task.applied_tag_ids\n ? task.applied_tag_ids\n .map((id) => tagsById.get(id))\n .filter((t): t is Tag => Boolean(t))\n : [];\n const legacyTags = appliedFromPool.length === 0 ? task.tags || [] : [];\n const totalTagCount = appliedFromPool.length + legacyTags.length;\n const showAddTagButton = !!onAddTag;\n\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 {/* Tags row — tags + add-tag button on the left, priority pinned top-right.\n The tags row wraps onto multiple lines while the priority chip stays put. */}\n <div className=\"flex items-start justify-between gap-2 mb-2\">\n <div className=\"flex flex-wrap items-center gap-1 min-w-0 flex-1\">\n {task.has_unread && (\n <span className=\"relative group/unread 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 {appliedFromPool.slice(0, 4).map((tag) => (\n <span\n key={tag.id}\n className={`inline-flex items-center px-1.5 py-px text-[9px] font-medium rounded ${tag.color}`}\n >\n {tag.name}\n </span>\n ))}\n {legacyTags.slice(0, 4).map((slug) => (\n <TagBadge key={slug} tag={slug} />\n ))}\n {totalTagCount > 4 && (\n <span className=\"text-[9px] text-neutral-400 px-1 py-px\">\n +{totalTagCount - 4}\n </span>\n )}\n {showAddTagButton && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onAddTag?.(e, task.id);\n }}\n aria-label=\"Add tag\"\n title=\"Manage tags\"\n className=\"inline-flex items-center justify-center w-4 h-4 rounded border border-dashed border-neutral-300 text-neutral-400 hover:text-neutral-700 hover:border-neutral-400 transition-colors\"\n >\n <PlusIcon size={9} strokeWidth={2.5} />\n </button>\n )}\n </div>\n <PriorityBadge priority={task.priority} />\n </div>\n\n {/* Title */}\n <h4 className=\"text-[13px] font-medium text-neutral-900 leading-snug line-clamp-2\">\n {task.title}\n </h4>\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","/**\n * Linear-time mention parser.\n *\n * The package previously used regexes like `/@\\[(.*?)\\]\\(.*?\\)/g` to find\n * `@[Name](username)` markup. Even with negated character classes\n * (`[^\\]]*` / `[^)]*`), the JS engine still does O(n) work per starting\n * position when the closing delimiter is missing — CodeQL flags this as\n * `js/polynomial-redos` because adversarial input like `@[@[@[…` triggers\n * O(n²) total scanning.\n *\n * This module replaces those regexes with hand-written scanners that walk\n * the input once with `indexOf`, so every operation is provably O(n).\n *\n * All functions here are pure and side-effect free.\n */\n\nexport interface ParsedMention {\n /** Inclusive start index in the source string (position of `@`). */\n start: number;\n /** Exclusive end index (one past the closing `)`). */\n end: number;\n /** Display name (the part inside `[...]`). */\n name: string;\n /** Username (the part inside `(...)`). */\n username: string;\n}\n\n/**\n * Walk `text` once and return every `@[Name](username)` mention with its\n * source positions. Skips malformed markup (`@[` without `]`, `]` without\n * `(`, etc.) and continues past the next character.\n *\n * O(n) in the length of `text`.\n */\nexport function findMentions(text: string): ParsedMention[] {\n const out: ParsedMention[] = [];\n if (!text) return out;\n let i = 0;\n const n = text.length;\n while (i < n) {\n const at = text.indexOf('@[', i);\n if (at < 0) break;\n const closeB = text.indexOf(']', at + 2);\n if (closeB < 0) break;\n if (text.charCodeAt(closeB + 1) !== 40 /* '(' */) {\n // `]` not immediately followed by `(` — not a mention; resume just\n // past this `@[` so we don't loop forever.\n i = at + 2;\n continue;\n }\n const closeP = text.indexOf(')', closeB + 2);\n if (closeP < 0) break;\n out.push({\n start: at,\n end: closeP + 1,\n name: text.substring(at + 2, closeB),\n username: text.substring(closeB + 2, closeP),\n });\n i = closeP + 1;\n }\n return out;\n}\n\n/**\n * Strip `@[Name](username)` markup down to plain `@Name`. Anything that\n * isn't a mention is preserved verbatim.\n *\n * O(n) in the length of `text`.\n */\nexport function stripMentionMarkup(text: string): string {\n if (!text) return text;\n const mentions = findMentions(text);\n if (mentions.length === 0) return text;\n let out = '';\n let cursor = 0;\n for (const m of mentions) {\n if (m.start > cursor) out += text.substring(cursor, m.start);\n out += '@' + m.name;\n cursor = m.end;\n }\n if (cursor < text.length) out += text.substring(cursor);\n return out;\n}\n\n/** A segment of a mention-aware split: either plain text or a mention. */\nexport type MentionSegment =\n | { kind: 'text'; value: string }\n | { kind: 'mention'; name: string; username: string };\n\n/**\n * Split `text` into a sequence of text and mention segments. The\n * concatenation of `value`s plus reconstructed `@[name](username)` strings\n * round-trips to the original input.\n *\n * O(n) in the length of `text`.\n */\nexport function splitOnMentions(text: string): MentionSegment[] {\n const segments: MentionSegment[] = [];\n if (!text) return segments;\n const mentions = findMentions(text);\n if (mentions.length === 0) {\n segments.push({ kind: 'text', value: text });\n return segments;\n }\n let cursor = 0;\n for (const m of mentions) {\n if (m.start > cursor) {\n segments.push({ kind: 'text', value: text.substring(cursor, m.start) });\n }\n segments.push({ kind: 'mention', name: m.name, username: m.username });\n cursor = m.end;\n }\n if (cursor < text.length) {\n segments.push({ kind: 'text', value: text.substring(cursor) });\n }\n return segments;\n}\n","import type { StructuredDescription, PriorityConfig, TagConfig } from '../types';\nimport { DEFAULT_PRIORITIES, PREDEFINED_TAGS, DESCRIPTION_SECTIONS } from './constants';\nimport { stripMentionMarkup as _stripMentions } from './mentions';\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/**\n * Strip `@[Name](username)` mention markup to plain `@Name` for previews.\n * Delegates to the linear-time `indexOf` parser in `./mentions` so the\n * function is provably O(n) and doesn't trip CodeQL's polynomial-redos.\n */\nfunction stripMentionMarkup(text: string): string {\n return _stripMentions(text);\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, Tag } from '../types';\nimport { FilterIcon, CheckIcon } from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\n\nexport interface FilterBarProps {\n projects: Project[];\n selectedProject: string;\n onSelectProject: (slug: string) => void;\n /** Workspace tag pool — filter dropdown lists every tag in here. */\n tagPool?: Tag[];\n /** Selected workspace tag IDs that the filter is currently active for. */\n filterTagIds?: string[];\n onSetFilterTagIds?: (ids: string[]) => void;\n /** Extra controls rendered on the right of the bar (e.g. layout toggle). */\n rightSlot?: React.ReactNode;\n}\n\nexport function FilterBar({\n projects,\n selectedProject,\n onSelectProject,\n tagPool = [],\n filterTagIds = [],\n onSetFilterTagIds,\n rightSlot,\n}: FilterBarProps) {\n const { 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 toggleTagId = (id: string) => {\n if (!onSetFilterTagIds) return;\n onSetFilterTagIds(\n filterTagIds.includes(id) ? filterTagIds.filter((t) => t !== id) : [...filterTagIds, id]\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 && onSetFilterTagIds && (\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 filterTagIds.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 {filterTagIds.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 {filterTagIds.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 eb-tb-animate-zoom-in\">\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 {filterTagIds.length > 0 && (\n <button\n onClick={() => onSetFilterTagIds([])}\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 max-h-72 overflow-y-auto\">\n {tagPool.length === 0 ? (\n <div className=\"px-3 py-2 text-[11px] text-neutral-400 italic\">\n No tags in this workspace yet\n </div>\n ) : (\n tagPool.map((tag) => {\n const isActive = filterTagIds.includes(tag.id);\n return (\n <button\n key={tag.id}\n onClick={() => toggleTagId(tag.id)}\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\n className={`inline-flex items-center px-2 py-0.5 text-[10px] font-medium rounded ${tag.color}`}\n >\n {tag.name}\n </span>\n {isActive && <CheckIcon size={13} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n );\n })\n )}\n </div>\n </div>\n )}\n </div>\n )}\n\n {rightSlot}\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, Tag } 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';\nimport { useTagPool } from '../hooks/useTagPool';\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 = 'draft',\n onClose,\n onCreate,\n}: CreateTaskModalProps) {\n const { columns, priorities, service, config } = useTaskBoardContext();\n const pool = useTagPool();\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 [selectedTagIds, setSelectedTagIds] = 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 toggleTagId = (id: string) => {\n setSelectedTagIds((prev) =>\n prev.includes(id) ? prev.filter((t) => t !== id) : [...prev, id]\n );\n };\n\n const addCustomTag = async () => {\n const name = customTag.trim();\n if (!name) return;\n setCustomTag('');\n const created = await pool.create(name);\n if (created && !selectedTagIds.includes(created.id)) {\n setSelectedTagIds((prev) => [...prev, created.id]);\n }\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 applied_tag_ids: selectedTagIds,\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 — pick from the workspace pool, or type a new name to add one. */}\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 max-h-64 overflow-y-auto\">\n {pool.tags.length === 0 ? (\n <div className=\"text-[11px] text-neutral-400 italic px-1 py-1\">\n No tags in this workspace yet — add one below.\n </div>\n ) : (\n pool.tags.map((tag) => {\n const isSelected = selectedTagIds.includes(tag.id);\n return (\n <button\n key={tag.id}\n type=\"button\"\n onClick={() => toggleTagId(tag.id)}\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\n className={`inline-flex items-center px-1.5 py-px text-[10px] font-medium rounded ${tag.color}`}\n >\n {tag.name}\n </span>\n {isSelected && <CheckIcon size={13} strokeWidth={2.5} className=\"text-[#FF5E00]\" />}\n </button>\n );\n })\n )}\n </div>\n {/* Add a brand-new pool tag */}\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=\"New tag name...\"\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 </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';\nimport { splitOnMentions, stripMentionMarkup } from '../utils/mentions';\n\n/**\n * Renders text with `@[Name](username)` mention markup highlighted as\n * styled badges. Plain text is rendered verbatim.\n *\n * Splitting and stripping go through hand-written `indexOf` scanners in\n * `utils/mentions` to keep parsing linear-time on adversarial input\n * (CodeQL js/polynomial-redos).\n */\nexport function MentionText({ text, className = \"\" }: { text: string; className?: string }) {\n if (!text) return null;\n\n const segments = splitOnMentions(text);\n\n return (\n <span className={className}>\n {segments.map((seg, i) => {\n if (seg.kind === 'mention') {\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={`@${seg.username}`}\n >\n @{seg.name}\n </span>\n );\n }\n return <span key={i}>{seg.value}</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 stripMentionMarkup(stored);\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(\n new RegExp(`@${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`, 'g'),\n `@[${name}](${username})`\n );\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';\nimport { findMentions } from '../utils/mentions';\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 /** Focus the underlying textarea on mount. Use for composers that should be\n * immediately writable (e.g. when the user opens the new-thread composer\n * from a highlight-to-comment selection). */\n autoFocus?: boolean;\n}\n\nexport function MentionTextarea({\n value,\n onChange,\n onKeyDown,\n placeholder = \"\",\n rows = 2,\n className = \"\",\n disabled = false,\n autoFocus = 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. Uses the O(n) `indexOf`\n // parser in `utils/mentions` so adversarial input can't trigger\n // polynomial regex scanning (CodeQL js/polynomial-redos).\n useEffect(() => {\n for (const m of findMentions(value)) {\n mentionMapRef.current.set(m.name, m.username);\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 autoFocus={autoFocus}\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, { useEffect, useRef, useState } from 'react';\nimport type { Tag } from '../types';\nimport { PlusIcon } from '../icons';\n\n// Workspace-level tag manager. Renders:\n// 1) Applied tags with a checkbox (uncheck to remove from this task) and\n// inline-editable name (click to rename — propagates everywhere since\n// tasks reference tags by ID, not by name).\n// 2) An Add-tag input + filterable dropdown of every workspace tag that's\n// not already applied. Enter / \"Create\" creates a new pool tag and\n// applies it.\n//\n// All changes are immediate. The dropdown stays mounted so you can apply\n// several tags in a row without losing focus.\n\nconst POP_WIDTH = 288;\n\nexport interface TagManagerPopoverProps {\n /** Trigger button rect (viewport coords). Used for fixed positioning. */\n anchor: DOMRect;\n /** IDs of tags currently applied to this task. */\n appliedTagIds: string[];\n /** The full workspace tag pool. */\n pool: Tag[];\n /** Persist the next set of applied tag IDs. */\n onApplyTagIds: (nextIds: string[]) => void;\n /** Create a new pool tag and resolve with its persisted form. */\n onCreateTag: (name: string) => Promise<Tag | null>;\n /** Rename a pool tag (propagates everywhere). */\n onRenameTag: (id: string, newName: string) => void;\n onClose: () => void;\n}\n\nexport function TagManagerPopover({\n anchor,\n appliedTagIds,\n pool,\n onApplyTagIds,\n onCreateTag,\n onRenameTag,\n onClose,\n}: TagManagerPopoverProps) {\n const [query, setQuery] = useState('');\n const popRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n // Outside-click close.\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (popRef.current && !popRef.current.contains(e.target as Node)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [onClose]);\n\n const appliedSet = new Set(appliedTagIds);\n const appliedTags = appliedTagIds\n .map((id) => pool.find((t) => t.id === id))\n .filter((t): t is Tag => Boolean(t));\n\n const ql = query.trim().toLowerCase();\n const available = pool.filter((t) => !appliedSet.has(t.id));\n const matches = ql\n ? available.filter((t) => t.name.toLowerCase().includes(ql))\n : available;\n const exactMatch = available.find((t) => t.name.toLowerCase() === ql);\n\n const toggleApplied = (id: string) => {\n if (appliedSet.has(id)) {\n onApplyTagIds(appliedTagIds.filter((x) => x !== id));\n } else {\n onApplyTagIds([...appliedTagIds, id]);\n }\n };\n\n const applyExisting = (id: string) => {\n if (!appliedSet.has(id)) onApplyTagIds([...appliedTagIds, id]);\n };\n\n const createAndApply = async () => {\n const name = query.trim();\n if (!name) return;\n const created = await onCreateTag(name);\n if (created && !appliedSet.has(created.id)) {\n onApplyTagIds([...appliedTagIds, created.id]);\n }\n setQuery('');\n inputRef.current?.focus();\n };\n\n // Position: under the trigger, clamped to the viewport.\n let left = anchor.left;\n if (typeof window !== 'undefined' && left + POP_WIDTH + 12 > window.innerWidth) {\n left = Math.max(8, window.innerWidth - POP_WIDTH - 12);\n }\n const top = anchor.bottom + 6;\n\n return (\n <div\n ref={popRef}\n role=\"dialog\"\n aria-label=\"Manage tags\"\n style={{ position: 'fixed', left, top, width: POP_WIDTH }}\n className=\"z-[60] bg-white border border-neutral-200 rounded-xl shadow-lg overflow-hidden\"\n >\n <div className=\"px-3 pt-3 pb-2 text-[11px] font-semibold text-neutral-700\">Tags</div>\n\n {/* Applied tags */}\n <div className=\"px-2 pb-2 max-h-56 overflow-y-auto flex flex-col gap-0.5\">\n {appliedTags.length === 0 ? (\n <div className=\"px-2 pb-1 text-[10px] text-neutral-400 italic\">\n No tags on this task yet\n </div>\n ) : (\n appliedTags.map((tag) => (\n <div\n key={tag.id}\n className=\"flex items-center gap-2 px-2 py-1 rounded hover:bg-neutral-50\"\n >\n <input\n type=\"checkbox\"\n className=\"w-3.5 h-3.5 rounded cursor-pointer\"\n checked\n onChange={() => toggleApplied(tag.id)}\n />\n <span\n className={`inline-block w-2 h-2 rounded-full shrink-0 ${tag.color.split(' ')[0]}`}\n />\n <span\n contentEditable\n suppressContentEditableWarning\n spellCheck={false}\n className=\"flex-1 text-[12px] text-neutral-800 outline-none rounded px-1 -mx-1 focus:bg-white focus:ring-1 focus:ring-neutral-300\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).textContent = tag.name;\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n onBlur={(e) => {\n const next = (e.currentTarget.textContent || '').trim();\n if (!next || next === tag.name) {\n e.currentTarget.textContent = tag.name;\n return;\n }\n onRenameTag(tag.id, next);\n }}\n >\n {tag.name}\n </span>\n </div>\n ))\n )}\n </div>\n\n <div className=\"border-t border-neutral-100\" />\n\n {/* Add tag input + filterable dropdown */}\n <div className=\"p-2\">\n <input\n ref={inputRef}\n type=\"text\"\n placeholder=\"Add tag…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n const lower = query.trim().toLowerCase();\n if (!lower) return;\n const existing = available.find((t) => t.name.toLowerCase() === lower);\n if (existing) {\n applyExisting(existing.id);\n setQuery('');\n } else {\n createAndApply();\n }\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n }\n }}\n className=\"w-full h-8 px-2 text-[12px] rounded-lg border border-neutral-200 focus:outline-none focus:ring-1 focus:ring-neutral-300 focus:border-neutral-300\"\n />\n\n <div className=\"mt-1 max-h-48 overflow-y-auto rounded-lg border border-neutral-200 bg-white flex flex-col\">\n {matches.map((tag) => (\n <button\n key={tag.id}\n type=\"button\"\n onMouseDown={(e) => {\n e.preventDefault();\n applyExisting(tag.id);\n }}\n className=\"flex items-center gap-2 px-2 py-1 text-left hover:bg-neutral-50\"\n >\n <span\n className={`inline-block w-2 h-2 rounded-full shrink-0 ${tag.color.split(' ')[0]}`}\n />\n <span className=\"text-[12px] text-neutral-800\">{tag.name}</span>\n </button>\n ))}\n {query.trim() && !exactMatch && (\n <button\n type=\"button\"\n onMouseDown={(e) => {\n e.preventDefault();\n createAndApply();\n }}\n className=\"flex items-center gap-2 px-2 py-1 text-left hover:bg-neutral-50 text-[#FF5E00]\"\n >\n <PlusIcon size={12} strokeWidth={2} />\n <span className=\"text-[12px]\">Create &quot;{query.trim()}&quot;</span>\n </button>\n )}\n {matches.length === 0 && !query.trim() && (\n <div className=\"px-2 py-1 text-[10px] text-neutral-400 italic\">\n No more tags to add\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n","import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n ActivityFeedItem,\n ColumnConfig,\n OutstandingQuestion,\n Project,\n} from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { ChevronDownIcon, MessageSquareIcon, PlusIcon } from '../icons';\nimport { formatDate, formatDateTime, getInitials } from '../utils/helpers';\n\n// Cross-project Overview view — the alternate top-level mode reachable from\n// the Tasks/Overview toggle. Shows a project filter, an Updates feed grouped\n// by day, and an Outstanding-questions list split into New (< 10 days) and\n// Old (≥ 10 days).\n\nexport interface OverviewPanelProps {\n /** Projects the current user has access to (drives the filter dropdown). */\n availableProjects: Project[];\n /** Initial project filter — defaults to \"all\". */\n initialProjectSlug?: string;\n /** Open a task in the consumer's preferred way (route push, slide-over, etc). */\n onOpenTask?: (taskId: string, projectSlug: string) => void;\n /** Optional column registry — used to render coloured status pills in moves. */\n columns?: ColumnConfig[];\n}\n\nfunction dayBucket(iso: string): { key: string; label: string } {\n const d = new Date(iso);\n const now = new Date();\n const startOfDay = (x: Date) =>\n new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const diffDays = Math.floor((startOfDay(now) - startOfDay(d)) / 86400000);\n if (diffDays === 0) return { key: 'today', label: 'Today' };\n if (diffDays === 1) return { key: 'yesterday', label: 'Yesterday' };\n return { key: d.toISOString().slice(0, 10), label: formatDate(iso) };\n}\n\nexport function OverviewPanel({\n availableProjects,\n initialProjectSlug,\n onOpenTask,\n columns: columnsOverride,\n}: OverviewPanelProps) {\n const { service, columns: defaultColumns } = useTaskBoardContext();\n const columns = columnsOverride ?? defaultColumns;\n const [projectFilter, setProjectFilter] = useState<string>(initialProjectSlug || 'all');\n const [activity, setActivity] = useState<ActivityFeedItem[]>([]);\n const [questions, setQuestions] = useState<OutstandingQuestion[]>([]);\n const [loading, setLoading] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\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 fetchData = useCallback(async () => {\n setLoading(true);\n try {\n const projectArg = projectFilter === 'all' ? undefined : projectFilter;\n const [act, q] = await Promise.all([\n service.listActivityFeed(projectArg),\n service.listOutstandingQuestions(projectArg, 'awaiting'),\n ]);\n setActivity(act || []);\n setQuestions(q || []);\n } catch {\n setActivity([]);\n setQuestions([]);\n } finally {\n setLoading(false);\n }\n }, [service, projectFilter]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n const grouped = useMemo(() => {\n const map = new Map<string, { label: string; items: ActivityFeedItem[] }>();\n for (const a of activity) {\n const { key, label } = dayBucket(a.created_at);\n if (!map.has(key)) map.set(key, { label, items: [] });\n map.get(key)!.items.push(a);\n }\n return Array.from(map.values());\n }, [activity]);\n\n // Split outstanding questions into \"New\" (< 10 days) and \"Old\" (≥ 10 days).\n const { newQuestions, oldQuestions } = useMemo(() => {\n const now = Date.now();\n const TEN_DAYS_MS = 10 * 86_400_000;\n const fresh: OutstandingQuestion[] = [];\n const stale: OutstandingQuestion[] = [];\n for (const q of questions) {\n const ageMs = now - new Date(q.created_at).getTime();\n if (ageMs >= TEN_DAYS_MS) stale.push(q);\n else fresh.push(q);\n }\n return { newQuestions: fresh, oldQuestions: stale };\n }, [questions]);\n\n const projectName = (slug: string) =>\n availableProjects.find((p) => p.slug === slug)?.name || slug;\n\n const handleOpen = (taskId: string, projectSlug: string) => {\n onOpenTask?.(taskId, projectSlug);\n };\n\n const filterLabel = projectFilter === 'all' ? 'All Projects' : projectName(projectFilter);\n\n return (\n <div className=\"flex-1 min-h-0 overflow-y-auto pb-6\">\n {/* Project filter */}\n <div className=\"mb-6 flex items-center gap-2\">\n <div className=\"relative\" ref={menuRef}>\n <button\n type=\"button\"\n onClick={() => setMenuOpen((v) => !v)}\n className=\"inline-flex items-center gap-2 h-10 px-3 rounded-xl border border-neutral-200 bg-white hover:bg-neutral-50 text-xs font-medium text-neutral-700 transition-colors\"\n >\n <span>{filterLabel}</span>\n <ChevronDownIcon size={14} className=\"text-neutral-400\" />\n </button>\n {menuOpen && (\n <div className=\"absolute left-0 top-full mt-1 z-20 min-w-[260px] py-1 rounded-xl border border-neutral-200 bg-white shadow-lg\">\n {[{ slug: 'all', name: 'All Projects' } as Project, ...availableProjects].map((p) => (\n <button\n key={p.slug}\n type=\"button\"\n onClick={() => {\n setProjectFilter(p.slug);\n setMenuOpen(false);\n }}\n className={`w-full text-left px-3 py-2 text-xs hover:bg-neutral-50 ${\n projectFilter === p.slug\n ? 'text-[#FF5E00] font-semibold'\n : 'text-neutral-700'\n }`}\n >\n {p.name}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n {/* Updates feed */}\n <section>\n <div className=\"flex items-center gap-2 mb-4\">\n <h2 className=\"text-[15px] font-semibold text-neutral-900\">Updates</h2>\n <span className=\"text-[11px] text-neutral-400\">·</span>\n <span className=\"text-[11px] text-neutral-500\">\n {activity.length} {activity.length === 1 ? 'entry' : 'entries'}\n </span>\n </div>\n\n {loading && activity.length === 0 ? (\n <div className=\"text-[12px] text-neutral-400 px-1\">Loading…</div>\n ) : grouped.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <span className=\"text-[12px] text-neutral-400\">No updates yet</span>\n </div>\n ) : (\n grouped.map((day) => (\n <div key={day.label} className=\"mb-6\">\n <h3 className=\"text-[11px] font-semibold tracking-wide text-neutral-500 uppercase mb-3\">\n {day.label}\n </h3>\n <div className=\"flex flex-col gap-3\">\n {day.items.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 <button\n key={a.id}\n type=\"button\"\n onClick={() => handleOpen(a.task_id, a.project_slug)}\n className=\"flex flex-col px-4 py-3 bg-white border border-neutral-200 rounded-xl hover:border-neutral-300 hover:shadow-[0_2px_8px_rgba(0,0,0,0.06)] transition-all text-left\"\n >\n <div className=\"flex items-start gap-3 mb-2\">\n <div className=\"w-6 h-6 rounded-full bg-neutral-100 text-neutral-500 flex items-center justify-center shrink-0\">\n {isCreated ? (\n <PlusIcon size={14} />\n ) : (\n <MessageSquareIcon size={14} />\n )}\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-[12px] text-neutral-700 leading-relaxed flex flex-wrap items-center gap-x-1.5 gap-y-1\">\n <span className=\"w-5 h-5 rounded-full bg-[#FF5E00] text-white text-[9px] font-semibold inline-flex items-center justify-center shrink-0\">\n {getInitials(a.user_name || a.user || '?')}\n </span>\n <span className=\"font-medium text-neutral-900\">\n {a.user_name || a.user}\n </span>\n {isCreated ? (\n <span>created a new task</span>\n ) : (\n <>\n <span>moved</span>\n <span className=\"text-neutral-500\">from</span>\n <span\n className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium ${\n fromCol?.chip ?? 'bg-neutral-100 text-neutral-700'\n }`}\n >\n <span\n className={`w-1.5 h-1.5 rounded-full ${\n fromCol?.color ?? 'bg-neutral-300'\n }`}\n />\n {fromCol?.label ?? a.from_status}\n </span>\n <span className=\"text-neutral-500\">to</span>\n <span\n className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium ${\n toCol?.chip ?? 'bg-neutral-100 text-neutral-700'\n }`}\n >\n <span\n className={`w-1.5 h-1.5 rounded-full ${\n toCol?.color ?? 'bg-neutral-300'\n }`}\n />\n {toCol?.label ?? a.to_status}\n </span>\n </>\n )}\n </div>\n </div>\n <span className=\"text-[11px] text-neutral-400 shrink-0\">\n {formatDateTime(a.created_at)}\n </span>\n </div>\n <div className=\"flex items-center gap-2 mt-1 pt-2 border-t border-neutral-100\">\n <span className=\"text-[11px] text-neutral-500 truncate\">{a.task_title}</span>\n <span className=\"text-[11px] text-neutral-300\">·</span>\n <span className=\"text-[11px] text-neutral-400\">\n {projectName(a.project_slug)}\n </span>\n </div>\n </button>\n );\n })}\n </div>\n </div>\n ))\n )}\n </section>\n\n {/* Outstanding questions — New / Old buckets */}\n <section>\n <div className=\"flex items-center gap-2 mb-4\">\n <h2 className=\"text-[15px] font-semibold text-neutral-900\">Outstanding questions</h2>\n <span className=\"text-[11px] text-neutral-400\">·</span>\n <span className=\"text-[11px] text-neutral-500\">{questions.length}</span>\n </div>\n {questions.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <span className=\"text-[12px] text-neutral-400\">No outstanding questions</span>\n </div>\n ) : (\n <>\n {newQuestions.length > 0 && (\n <QuestionBucket\n label=\"New\"\n items={newQuestions}\n projectName={projectName}\n onOpen={handleOpen}\n />\n )}\n {oldQuestions.length > 0 && (\n <QuestionBucket\n label=\"Old\"\n items={oldQuestions}\n projectName={projectName}\n onOpen={handleOpen}\n />\n )}\n </>\n )}\n </section>\n </div>\n </div>\n );\n}\n\nfunction QuestionBucket({\n label,\n items,\n projectName,\n onOpen,\n}: {\n label: string;\n items: OutstandingQuestion[];\n projectName: (slug: string) => string;\n onOpen: (taskId: string, projectSlug: string) => void;\n}) {\n return (\n <div className=\"mb-6\">\n <div className=\"flex items-center gap-2 mb-3\">\n <h3 className=\"text-[11px] font-semibold tracking-wide text-neutral-500 uppercase\">\n {label}\n </h3>\n <span className=\"text-[11px] text-neutral-400\">·</span>\n <span className=\"text-[11px] text-neutral-500\">{items.length}</span>\n </div>\n <div className=\"flex flex-col gap-3\">\n {items.map((q) => (\n <button\n key={q.id}\n type=\"button\"\n onClick={() => onOpen(q.task_id, q.project_slug)}\n className=\"flex flex-col px-4 py-3 bg-white border border-neutral-200 rounded-xl hover:border-neutral-300 hover:shadow-[0_2px_8px_rgba(0,0,0,0.06)] transition-all text-left\"\n >\n <div className=\"flex items-start gap-3 mb-2\">\n <span className=\"w-5 h-5 rounded-full bg-[#FF5E00] text-white text-[9px] font-semibold inline-flex items-center justify-center shrink-0\">\n {getInitials(q.asked_by_name || q.asked_by || '?')}\n </span>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-[12px] text-neutral-800 leading-relaxed line-clamp-2\">{q.text}</p>\n </div>\n <span className=\"text-[11px] text-neutral-400 shrink-0\">\n {formatDateTime(q.created_at)}\n </span>\n </div>\n <div className=\"flex items-center gap-2 mt-1 pt-2 border-t border-neutral-100\">\n <span className=\"text-[11px] text-neutral-500 truncate\">{q.task_title}</span>\n <span className=\"text-[11px] text-neutral-300\">·</span>\n <span className=\"text-[11px] text-neutral-400\">{projectName(q.project_slug)}</span>\n </div>\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport type { ColumnConfig, Tag, Task } from '../types';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport {\n formatDate,\n getDescriptionPreview,\n getInitials,\n getPriorityStyle,\n getTagStyle,\n hasDescription,\n} from '../utils/helpers';\nimport { ChevronDownIcon, MessageSquareIcon, PlusIcon } from '../icons';\n\n// List layout for the Task Board. Same per-column grouping as the kanban,\n// but rendered as collapsible sections of rows. Each row carries the same\n// info as a board card: tags above the title, priority chip pinned, date,\n// comment count, and creator avatar.\n\nexport interface ListLayoutProps {\n tasks: Record<string, Task[]>;\n columnTotals: Record<string, number>;\n filterTagIds: string[];\n tagsById: Map<string, Tag>;\n onTaskClick: (task: Task) => void;\n onAddTag: (e: React.MouseEvent<HTMLButtonElement>, taskId: string) => void;\n onAddTaskToColumn: (statusKey: string) => void;\n}\n\nexport function ListLayout({\n tasks,\n columnTotals,\n filterTagIds,\n tagsById,\n onTaskClick,\n onAddTag,\n onAddTaskToColumn,\n}: ListLayoutProps) {\n const { columns } = useTaskBoardContext();\n return (\n <div className=\"flex-1 min-h-0 overflow-y-auto pb-4\">\n <div className=\"flex flex-col gap-4\">\n {columns.map((col) => {\n const all = tasks[col.key] || [];\n const filtered =\n filterTagIds.length > 0\n ? all.filter((t) =>\n filterTagIds.some((id) => (t.applied_tag_ids || []).includes(id))\n )\n : all;\n return (\n <ListSection\n key={col.key}\n col={col}\n tasks={filtered}\n total={columnTotals[col.key] ?? all.length}\n tagsById={tagsById}\n onTaskClick={onTaskClick}\n onAddTag={onAddTag}\n onAddTaskToColumn={onAddTaskToColumn}\n />\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction ListSection({\n col,\n tasks,\n total,\n tagsById,\n onTaskClick,\n onAddTag,\n onAddTaskToColumn,\n}: {\n col: ColumnConfig;\n tasks: Task[];\n total: number;\n tagsById: Map<string, Tag>;\n onTaskClick: (task: Task) => void;\n onAddTag: (e: React.MouseEvent<HTMLButtonElement>, taskId: string) => void;\n onAddTaskToColumn: (statusKey: string) => void;\n}) {\n const [open, setOpen] = useState(true);\n\n return (\n <section className=\"border border-neutral-200 rounded-xl bg-white overflow-hidden\">\n <div className=\"flex items-center gap-2 px-4 py-3 border-b border-neutral-100\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"flex items-center gap-2 flex-1 text-left\"\n aria-expanded={open}\n >\n <span className={`w-2 h-2 rounded-full ${col.color}`} />\n <h3 className=\"text-xs font-semibold tracking-wide text-neutral-700 uppercase\">\n {col.label}\n </h3>\n <span className=\"inline-flex items-center justify-center min-w-[20px] h-5 px-1.5 rounded text-[10px] font-semibold bg-neutral-100 text-neutral-600\">\n {total}\n </span>\n <span className=\"text-[11px] text-neutral-400 ml-2\">{col.description}</span>\n <ChevronDownIcon\n size={14}\n strokeWidth={1.5}\n className={`ml-auto text-neutral-400 transition-transform ${\n open ? '' : '-rotate-90'\n }`}\n />\n </button>\n <button\n type=\"button\"\n onClick={() => onAddTaskToColumn(col.key)}\n className=\"ml-2 w-7 h-7 flex items-center justify-center rounded-md text-neutral-400 hover:text-[#FF5E00] hover:bg-[#FF5E00]/10 transition-colors\"\n aria-label={`Add task to ${col.label}`}\n >\n <PlusIcon size={14} />\n </button>\n </div>\n\n {open && (\n <div>\n {tasks.length === 0 ? (\n <div className=\"px-4 py-6 text-center text-[12px] text-neutral-400\">No tasks</div>\n ) : (\n tasks.map((t, i) => (\n <ListRow\n key={t.id}\n task={t}\n tagsById={tagsById}\n onClick={() => onTaskClick(t)}\n onAddTag={onAddTag}\n hasDivider={i > 0}\n />\n ))\n )}\n </div>\n )}\n </section>\n );\n}\n\nfunction ListRow({\n task,\n tagsById,\n onClick,\n onAddTag,\n hasDivider,\n}: {\n task: Task;\n tagsById: Map<string, Tag>;\n onClick: () => void;\n onAddTag: (e: React.MouseEvent<HTMLButtonElement>, taskId: string) => void;\n hasDivider: boolean;\n}) {\n const priority = getPriorityStyle(task.priority);\n // Resolve applied tag IDs through the pool. Fall back to the legacy\n // string-based `tags` field for tasks that haven't been migrated yet.\n const appliedFromPool: Tag[] = (task.applied_tag_ids || [])\n .map((id) => tagsById.get(id))\n .filter((t): t is Tag => Boolean(t));\n const legacyTags = task.applied_tag_ids?.length ? [] : task.tags || [];\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick();\n }\n }}\n className={`grid items-center gap-4 px-4 py-3 hover:bg-neutral-50 cursor-pointer transition-colors ${\n hasDivider ? 'border-t border-neutral-100' : ''\n }`}\n style={{ gridTemplateColumns: 'minmax(0, 1fr) auto auto auto' }}\n >\n <div className=\"min-w-0\">\n <div className=\"flex items-center flex-wrap gap-1.5 mb-1\">\n {appliedFromPool.map((tag) => (\n <span\n key={tag.id}\n className={`inline-flex items-center px-1.5 py-px text-[9px] font-medium rounded whitespace-nowrap ${tag.color}`}\n >\n {tag.name}\n </span>\n ))}\n {legacyTags.map((slug) => {\n const style = getTagStyle(slug);\n return (\n <span\n key={slug}\n className={`inline-flex items-center px-1.5 py-px text-[9px] font-medium rounded border whitespace-nowrap ${style.className}`}\n >\n {style.label}\n </span>\n );\n })}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onAddTag(e, task.id);\n }}\n aria-label=\"Add tag\"\n title=\"Manage tags\"\n className=\"inline-flex items-center justify-center w-4 h-4 rounded border border-dashed border-neutral-300 text-neutral-400 hover:text-neutral-700 hover:border-neutral-400 transition-colors\"\n >\n <PlusIcon size={9} strokeWidth={2.5} />\n </button>\n </div>\n <h4 className=\"text-[13px] font-semibold text-neutral-900 truncate\">{task.title}</h4>\n {hasDescription(task.description) && (\n <p className=\"text-[11px] text-neutral-500 line-clamp-1 mt-0.5\">\n {getDescriptionPreview(task.description)}\n </p>\n )}\n </div>\n <span\n className={`shrink-0 inline-flex items-center px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide rounded border ${priority.className}`}\n >\n {priority.label}\n </span>\n <div className=\"flex items-center gap-3 text-[11px] text-neutral-400 shrink-0\">\n <span>{formatDate(task.created_at)}</span>\n {task.comment_count > 0 && (\n <span className=\"flex items-center gap-0.5\">\n <MessageSquareIcon size={11} />\n {task.comment_count}\n </span>\n )}\n </div>\n {task.created_by_name ? (\n <div\n className=\"w-5 h-5 rounded-full bg-[#FF5E00] flex items-center justify-center shrink-0\"\n title={task.created_by_name}\n >\n <span className=\"text-[8px] font-semibold text-white leading-none\">\n {getInitials(task.created_by_name)}\n </span>\n </div>\n ) : (\n <span className=\"w-5 h-5 shrink-0\" />\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 ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n MoreVerticalIcon,\n PlusIcon,\n Share2Icon,\n TrashIcon,\n XIcon,\n CheckIcon,\n} from '../icons';\nimport { useTaskBoardContext } from '../context/TaskBoardProvider';\nimport { DESCRIPTION_SECTIONS, EMPTY_DESCRIPTION } from '../utils/constants';\nimport { formatDate, formatTaskId, getInitials, getPriorityStyle } 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 { MarkdownEditor } from './MarkdownEditor';\nimport { MarkdownView } from './MarkdownView';\nimport { TagManagerPopover } from './TagManagerPopover';\nimport { useTaskQuestions } from '../hooks/useTaskQuestions';\nimport { useTaskAttachments } from '../hooks/useTaskAttachments';\nimport { useHighlightAnchor } from '../hooks/useHighlightAnchor';\nimport { useTagPool } from '../hooks/useTagPool';\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, user } = useTaskBoardContext();\n const tagPool = useTagPool();\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 [appliedTagIds, setAppliedTagIds] = useState<string[]>([]);\n\n // Top-level Overview / Technical Details tabs.\n const [activeTab, setActiveTab] = useState<'overview' | 'technical'>('overview');\n const [techEditing, setTechEditing] = useState(false);\n\n // Header dropdowns\n const [statusOpen, setStatusOpen] = useState(false);\n const [priorityOpen, setPriorityOpen] = useState(false);\n const [moreOpen, setMoreOpen] = useState(false);\n const [tagPopoverAnchor, setTagPopoverAnchor] = useState<DOMRect | null>(null);\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\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 setAppliedTagIds(data.applied_tag_ids || []);\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 };\n document.addEventListener('mousedown', onClick);\n return () => document.removeEventListener('mousedown', onClick);\n }, [statusOpen, priorityOpen, moreOpen]);\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 // Apply tag IDs from the workspace pool — used by the shared popover.\n const applyTagIdsNow = useCallback(\n (next: string[]) => {\n setAppliedTagIds(next);\n persist({ applied_tag_ids: next });\n },\n [persist]\n );\n\n const renamePoolTag = useCallback(\n async (id: string, newName: string) => {\n await tagPool.update(id, { name: newName.trim() });\n },\n [tagPool]\n );\n\n const handleTechnicalDetailsChange = (val: string) => {\n const next = { ...description, technical_details: val };\n setDescription(next);\n persist({ description: next });\n };\n\n // Draft-only actions. Accept promotes the draft to backlog (enters the\n // normal workflow); Delete tears the task down entirely.\n const handleDraftAccept = async () => {\n setTaskStatus('backlog');\n await persist({ status: 'backlog' });\n setTimeout(() => fetchTask(), 500);\n };\n\n const handleDraftDelete = async () => {\n if (!task) return;\n if (!confirm('Delete this draft? This cannot be undone.')) return;\n try {\n await service.deleteTask(taskId);\n onDeleted?.(task);\n } catch {\n setError('Failed to delete draft.');\n }\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 // Edit a single comment (thread root or reply). Author-only on the backend.\n const handleEditMessage = async (messageId: string, content: string) => {\n try {\n await service.editComment(taskId, messageId, { content });\n await fetchTask();\n } catch {\n // silent\n }\n };\n\n // Delete a single reply. The backend keeps the parent thread intact.\n const handleDeleteMessage = async (messageId: string) => {\n try {\n await service.deleteComment(taskId, messageId);\n await fetchTask();\n } catch {\n // silent\n }\n };\n\n // Delete a whole thread (root + replies). Backend cascades; close the detail\n // view first so we don't try to render a thread that's gone.\n const handleDeleteThread = async (threadId: string) => {\n try {\n await service.deleteComment(taskId, threadId);\n setOpenThreadId(null);\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 // Group anchors by section for the inline <mark> highlights.\n const anchorsBySection = useMemo(() => {\n const map: Record<string, Array<{ snippet: string; threadId: string }>> = {};\n for (const t of threads) {\n if (!t.anchor) continue;\n const key = t.anchor.section;\n if (!map[key]) map[key] = [];\n map[key].push({ snippet: t.anchor.snippet, threadId: t.id });\n }\n return map;\n }, [threads]);\n\n // Open a thread in the right panel — used both when a description-section\n // <mark> is clicked and when an anchor pill is clicked elsewhere.\n const openThreadFromAnchor = useCallback(\n (threadId: string) => {\n setOpenThreadId(threadId);\n if (!panelOpen) {\n setPanelOpen(true);\n try {\n window.localStorage.setItem(PANEL_OPEN_KEY, 'true');\n } catch {\n // ignore\n }\n }\n },\n [panelOpen]\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\">\n <span>Tags</span>\n {appliedTagIds.map((id) => {\n const tag = tagPool.byId.get(id);\n if (!tag) return null;\n return (\n <span\n key={id}\n className={`inline-flex items-center px-1.5 py-px text-[10px] font-medium rounded ${tag.color}`}\n >\n {tag.name}\n </span>\n );\n })}\n <button\n type=\"button\"\n onClick={(e) => {\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n setTagPopoverAnchor(rect);\n }}\n aria-label=\"Manage tags\"\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 </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 — swap for Accept/Delete on draft tasks */}\n {taskStatus === 'draft' ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleDraftAccept}\n className=\"inline-flex items-center gap-2 h-10 px-4 rounded-xl bg-[#FF5E00] hover:bg-[#E05200] text-white text-[12px] font-medium transition-colors\"\n >\n <CheckIcon size={14} strokeWidth={2} />\n Accept\n </button>\n <button\n type=\"button\"\n onClick={handleDraftDelete}\n className=\"inline-flex items-center gap-2 h-10 px-3 rounded-xl border border-neutral-200 bg-white text-neutral-700 hover:border-red-200 hover:bg-red-50 hover:text-red-600 text-[12px] font-medium transition-colors\"\n >\n <TrashIcon size={14} strokeWidth={1.5} />\n Delete\n </button>\n </div>\n ) : (\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\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 {/* Top-level tabs: Overview / Technical Details */}\n <div\n className=\"flex items-center gap-1 border-b border-neutral-200 mt-8 mb-6\"\n role=\"tablist\"\n aria-label=\"Task content\"\n >\n {(['overview', 'technical'] as const).map((key) => {\n const active = activeTab === key;\n return (\n <button\n key={key}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => setActiveTab(key)}\n className={`relative h-10 px-4 text-[13px] font-medium transition-colors ${\n active ? 'text-[#FF5E00]' : 'text-neutral-500 hover:text-neutral-900'\n }`}\n >\n {key === 'overview' ? 'Overview' : 'Technical Details'}\n {active && (\n <span className=\"absolute left-0 right-0 -bottom-px h-0.5 bg-[#FF5E00] rounded-full\" />\n )}\n </button>\n );\n })}\n </div>\n\n {/* Overview tab */}\n {activeTab === 'overview' && (\n <div className=\"flex flex-col gap-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 anchors={anchorsBySection[section.key]}\n onAnchorClick={openThreadFromAnchor}\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 )}\n\n {/* Technical Details tab — single large markdown area */}\n {activeTab === 'technical' && (\n <section data-section=\"technical-details\">\n <div className=\"flex items-center justify-between gap-3 mb-3\">\n <h2 className=\"text-[15px] font-semibold text-neutral-900 tracking-tight\">\n Technical Details\n </h2>\n {saving && <span className=\"text-[11px] text-neutral-400\">Saving...</span>}\n </div>\n {techEditing ? (\n <MarkdownEditor\n value={description.technical_details || ''}\n onCommit={(md) => {\n if (md !== (description.technical_details || '')) {\n handleTechnicalDetailsChange(md);\n }\n setTechEditing(false);\n }}\n onCancel={() => setTechEditing(false)}\n placeholder=\"Add technical details in markdown — architecture, data model, API contracts, edge cases…\"\n saving={saving}\n />\n ) : (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => setTechEditing(true)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setTechEditing(true);\n }\n }}\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 min-h-[420px] focus:outline-none focus-visible:ring-2 focus-visible:ring-[#FF5E00]/20\"\n >\n {description.technical_details?.trim() ? (\n <MarkdownView content={description.technical_details} className=\"text-[13px]\" />\n ) : (\n <p className=\"text-[13px] text-neutral-400 italic\">\n Add technical details in markdown — architecture, data model, API contracts,\n edge cases…\n </p>\n )}\n </div>\n )}\n </section>\n )}\n </div>\n\n <ThreadsPanel\n threads={threads}\n activity={activity}\n attachments={attachments.attachments}\n currentUsername={user.username}\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 onEditMessage={handleEditMessage}\n onDeleteMessage={handleDeleteMessage}\n onDeleteThread={handleDeleteThread}\n onUploadAttachment={attachments.uploadFile}\n onAddLinkAttachment={(url, name) => attachments.addLink({ url, name })}\n />\n\n {tagPopoverAnchor && (\n <TagManagerPopover\n anchor={tagPopoverAnchor}\n appliedTagIds={appliedTagIds}\n pool={tagPool.tags}\n onApplyTagIds={applyTagIdsNow}\n onCreateTag={tagPool.create}\n onRenameTag={renamePoolTag}\n onClose={() => setTagPopoverAnchor(null)}\n />\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';\nimport { stripMentionMarkup } from './mentions';\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 /** Whether the thread root has been edited at least once. */\n edited?: boolean;\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 edited?: 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 = stripMentionMarkup(c.content);\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 edited: !!r.edited,\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 edited: !!c.edited,\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, { useEffect, useRef, 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 /** Threads anchored to this section — drives the inline `<mark>` highlights. */\n anchors?: Array<{ snippet: string; threadId: string }>;\n /** Click handler when the user clicks on a highlighted snippet. */\n onAnchorClick?: (threadId: string) => void;\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 * - inline `<mark class=\"eb-tb-annot\">` wrapping each anchor's snippet\n * (clicking the mark opens that thread in the right panel)\n */\nexport function DescriptionSection({\n sectionKey,\n label,\n placeholder,\n value,\n onChange,\n status,\n onStatusChange,\n saving,\n anchors,\n onAnchorClick,\n}: DescriptionSectionProps) {\n const [editing, setEditing] = useState(false);\n const [openHelp, setOpenHelp] = useState<null | SectionStatus>(null);\n const readRef = useRef<HTMLDivElement>(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 // Walk the rendered MarkdownView output and wrap each anchor's snippet in\n // <mark class=\"eb-tb-annot\"> so the source text shows where threads attach.\n // Done as a post-render DOM pass so MarkdownView itself stays untouched.\n useEffect(() => {\n if (editing) return;\n const root = readRef.current;\n if (!root) return;\n\n // Clear marks from a previous pass before re-applying.\n root.querySelectorAll('mark.eb-tb-annot').forEach((m) => {\n const text = m.textContent || '';\n m.replaceWith(document.createTextNode(text));\n });\n root.normalize();\n\n if (!anchors || anchors.length === 0) return;\n\n for (const anchor of anchors) {\n const snippet = anchor.snippet?.trim();\n if (!snippet) continue;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n let node = walker.nextNode();\n while (node) {\n const txt = node.textContent || '';\n const idx = txt.indexOf(snippet);\n if (idx !== -1) {\n const range = document.createRange();\n try {\n range.setStart(node, idx);\n range.setEnd(node, idx + snippet.length);\n const mark = document.createElement('mark');\n mark.className = 'eb-tb-annot';\n mark.dataset.threadId = anchor.threadId;\n range.surroundContents(mark);\n } catch {\n // surroundContents throws if the range straddles element boundaries;\n // we just skip that anchor rather than crash.\n }\n break;\n }\n node = walker.nextNode();\n }\n }\n }, [anchors, value, editing]);\n\n // Click on a marked span opens its thread; click anywhere else starts edit.\n const handleReadClick = (e: React.MouseEvent) => {\n const target = e.target as HTMLElement | null;\n const mark = target?.closest('mark.eb-tb-annot') as HTMLElement | null;\n if (mark && mark.dataset.threadId && onAnchorClick) {\n e.preventDefault();\n e.stopPropagation();\n onAnchorClick(mark.dataset.threadId);\n return;\n }\n startEdit();\n };\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 <div\n ref={readRef}\n role=\"button\"\n tabIndex={0}\n onClick={handleReadClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n startEdit();\n }\n }}\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 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#FF5E00]/20\"\n >\n {hasContent ? (\n <MarkdownView content={value} className=\"text-[13px]\" />\n ) : (\n <p className=\"text-[13px] text-neutral-400 italic\">{placeholder}</p>\n )}\n </div>\n )}\n </section>\n );\n}\n","import React from 'react';\nimport { splitOnMentions } from '../utils/mentions';\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 // Hand-written O(n) parser instead of a regex split — adversarial input\n // like \"@[@[@[…\" would otherwise scan quadratically (CodeQL\n // js/polynomial-redos).\n const segments = splitOnMentions(text);\n let k = 0;\n for (const seg of segments) {\n if (seg.kind === 'mention') {\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={`@${seg.username}`}\n >\n @{seg.name}\n </span>\n );\n continue;\n }\n const inlineParts = seg.value.split(/(\\*\\*.*?\\*\\*|`[^`]+`)/g);\n for (const part of inlineParts) {\n if (!part) continue;\n const bold = part.match(/^\\*\\*(.+?)\\*\\*$/);\n const code = part.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++}`}>{part}</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\nimport { splitOnMentions } from './mentions';\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\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. The split is done by a hand-written\n // O(n) parser to keep adversarial input from triggering quadratic regex\n // backtracking (CodeQL js/polynomial-redos).\n const segments = splitOnMentions(text);\n return segments\n .map((seg) => {\n if (seg.kind === 'mention') {\n return `<span class=\"mention-pill\" data-mention-username=\"${escapeHtml(seg.username)}\">@${escapeHtml(seg.name)}</span>`;\n }\n let s = escapeHtml(seg.value);\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 &amp; 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 /** Username of the logged-in user — used by the detail view to flag own messages. */\n currentUsername: string;\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 /** Edit a single comment (thread root or reply). Author-only on the backend. */\n onEditMessage: (messageId: string, content: string) => Promise<void>;\n /** Delete a single reply. Backend keeps the parent thread intact. */\n onDeleteMessage: (messageId: string) => Promise<void>;\n /** Delete the whole thread (root + replies). Backend cascades. */\n onDeleteThread: (threadId: string) => 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 currentUsername,\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 onEditMessage,\n onDeleteMessage,\n onDeleteThread,\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 currentUsername={currentUsername}\n onBack={() => onOpenThread(null)}\n onReply={(content, isInternal) => onCreateReply(openThread.id, content, isInternal)}\n onUpdateThread={(body) => onUpdateThread(openThread.id, body)}\n onEditMessage={onEditMessage}\n onDeleteMessage={onDeleteMessage}\n onDeleteThread={onDeleteThread}\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\">&ldquo;{pendingAnchor.snippet}&rdquo;</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 autoFocus\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 MoreVerticalIcon,\n PencilIcon,\n RotateCcwIcon,\n TrashIcon,\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 /** Username of the logged-in user, for own-message detection. */\n currentUsername: string;\n onBack: () => void;\n onReply: (content: string, isInternal: boolean) => Promise<void>;\n onUpdateThread: (body: { title?: string; thread_status?: ThreadStatus }) => Promise<void>;\n /** Edit a single message (thread root or reply). Author-only on the backend. */\n onEditMessage: (messageId: string, content: string) => Promise<void>;\n /** Delete a single reply. Backend keeps the parent thread intact. */\n onDeleteMessage: (messageId: string) => Promise<void>;\n /** Delete the whole thread (root + replies). Backend cascades. */\n onDeleteThread: (threadId: string) => 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 currentUsername,\n onBack,\n onReply,\n onUpdateThread,\n onEditMessage,\n onDeleteMessage,\n onDeleteThread,\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 [editingMessageId, setEditingMessageId] = useState<string | null>(null);\n const [editDraft, setEditDraft] = useState('');\n const [savingEdit, setSavingEdit] = useState(false);\n const [headerMenuOpen, setHeaderMenuOpen] = useState(false);\n const headerMenuRef = useRef<HTMLDivElement>(null);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n setTitleDraft(thread.title);\n }, [thread.title]);\n\n // Reset inline-edit state when switching threads.\n useEffect(() => {\n setEditingMessageId(null);\n setEditDraft('');\n }, [thread.id]);\n\n // Outside-click closes the header kebab.\n useEffect(() => {\n if (!headerMenuOpen) return;\n const onClick = (e: MouseEvent) => {\n if (headerMenuRef.current && !headerMenuRef.current.contains(e.target as Node)) {\n setHeaderMenuOpen(false);\n }\n };\n document.addEventListener('mousedown', onClick);\n return () => document.removeEventListener('mousedown', onClick);\n }, [headerMenuOpen]);\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 startEditMessage = (id: string, content: string) => {\n setEditingMessageId(id);\n setEditDraft(content);\n };\n\n const cancelEditMessage = () => {\n setEditingMessageId(null);\n setEditDraft('');\n };\n\n const commitEditMessage = async () => {\n const id = editingMessageId;\n const next = editDraft.trim();\n if (!id || !next) {\n cancelEditMessage();\n return;\n }\n setSavingEdit(true);\n try {\n await onEditMessage(id, next);\n cancelEditMessage();\n } finally {\n setSavingEdit(false);\n }\n };\n\n const handleDeleteMessage = async (id: string, isThreadRoot: boolean) => {\n const msg = isThreadRoot\n ? 'Delete this thread and all of its replies? This cannot be undone.'\n : 'Delete this message? This cannot be undone.';\n if (!confirm(msg)) return;\n if (isThreadRoot) {\n await onDeleteThread(id);\n } else {\n await onDeleteMessage(id);\n }\n };\n\n const isComplete = thread.status === 'complete';\n const isThreadAuthor = thread.author_id === currentUsername;\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 <div className=\"flex items-center gap-1.5 shrink-0\">\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 ref={headerMenuRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setHeaderMenuOpen((v) => !v)}\n aria-label=\"Thread actions\"\n className=\"w-8 h-8 flex items-center justify-center rounded-xl border border-neutral-200 bg-white text-neutral-500 hover:text-neutral-900 hover:border-neutral-300 transition-colors\"\n >\n <MoreVerticalIcon size={14} strokeWidth={1.5} />\n </button>\n {headerMenuOpen && (\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 {isThreadAuthor && (\n <button\n type=\"button\"\n onClick={() => {\n setHeaderMenuOpen(false);\n setEditingTitle(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 <PencilIcon size={14} strokeWidth={1.5} />\n Edit title\n </button>\n )}\n <button\n type=\"button\"\n onClick={async () => {\n setHeaderMenuOpen(false);\n if (\n !confirm(\n 'Delete this thread and all of its replies? This cannot be undone.'\n )\n )\n return;\n await onDeleteThread(thread.id);\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 thread\n </button>\n </div>\n )}\n </div>\n </div>\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 {/* Original message */}\n {editingMessageId === thread.id ? (\n <ThreadMessageEditor\n authorName={thread.author_name}\n isInternal={thread.is_internal}\n value={editDraft}\n onChange={setEditDraft}\n onCommit={commitEditMessage}\n onCancel={cancelEditMessage}\n saving={savingEdit}\n />\n ) : (\n <ThreadMessage\n authorName={thread.author_name}\n createdAt={thread.created_at}\n content={thread.rawContent}\n isInternal={thread.is_internal}\n edited={thread.edited}\n isOwn={isThreadAuthor}\n internalLabel={internalLabel}\n onEdit={() => startEditMessage(thread.id, thread.rawContent)}\n onDelete={() => handleDeleteMessage(thread.id, true)}\n />\n )}\n\n {thread.replies.map((r) =>\n editingMessageId === r.id ? (\n <ThreadMessageEditor\n key={r.id}\n authorName={r.author_name}\n isInternal={r.is_internal}\n value={editDraft}\n onChange={setEditDraft}\n onCommit={commitEditMessage}\n onCancel={cancelEditMessage}\n saving={savingEdit}\n />\n ) : (\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 edited={r.edited}\n isOwn={r.author_id === currentUsername}\n internalLabel={internalLabel}\n onEdit={() => startEditMessage(r.id, r.content)}\n onDelete={() => handleDeleteMessage(r.id, false)}\n />\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\n/**\n * Read-mode rendering of a single thread message (root or reply). When `isOwn`\n * + handlers are passed, a hover kebab exposes Edit / Delete.\n */\nfunction ThreadMessage({\n authorName,\n createdAt,\n content,\n isInternal,\n edited = false,\n isOwn = false,\n internalLabel,\n onEdit,\n onDelete,\n}: {\n authorName: string;\n createdAt: string;\n content: string;\n isInternal: boolean;\n edited?: boolean;\n isOwn?: boolean;\n internalLabel: string;\n onEdit?: () => void;\n onDelete?: () => void;\n}) {\n const initials = getInitials(authorName || '?');\n const [menuOpen, setMenuOpen] = useState(false);\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 showActions = isOwn && (onEdit || onDelete);\n\n return (\n <div className=\"group 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 {edited && <span className=\"text-[10px] text-neutral-400 italic\">(edited)</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 {showActions && (\n <div\n ref={menuRef}\n className=\"ml-auto relative opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity\"\n >\n <button\n type=\"button\"\n onClick={() => setMenuOpen((v) => !v)}\n aria-label=\"Message actions\"\n className=\"w-6 h-6 flex items-center justify-center rounded text-neutral-400 hover:text-neutral-700 hover:bg-neutral-100\"\n >\n <MoreVerticalIcon size={12} strokeWidth={1.5} />\n </button>\n {menuOpen && (\n <div className=\"absolute right-0 top-full mt-1 w-36 bg-white border border-neutral-200 rounded-xl shadow-lg py-1 z-30\">\n {onEdit && (\n <button\n type=\"button\"\n onClick={() => {\n setMenuOpen(false);\n onEdit();\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\"\n >\n <PencilIcon size={12} strokeWidth={1.5} />\n Edit\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={() => {\n setMenuOpen(false);\n onDelete();\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\"\n >\n <TrashIcon size={12} strokeWidth={1.5} />\n Delete\n </button>\n )}\n </div>\n )}\n </div>\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\n/**\n * Inline editor for a thread message. Mirrors the read-mode `ThreadMessage`\n * avatar/header layout but swaps the body for a MentionTextarea + Save/Cancel\n * buttons. Cmd/Ctrl+Enter submits, Escape cancels.\n */\nfunction ThreadMessageEditor({\n authorName,\n isInternal,\n value,\n onChange,\n onCommit,\n onCancel,\n saving,\n}: {\n authorName: string;\n isInternal: boolean;\n value: string;\n onChange: (v: string) => void;\n onCommit: () => void;\n onCancel: () => void;\n saving?: boolean;\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 flex flex-col gap-2\">\n <MentionTextarea\n value={value}\n onChange={onChange}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault();\n onCommit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n onCancel();\n }\n }}\n rows={3}\n placeholder=\"Edit message…\"\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 autoFocus\n />\n <div className=\"flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\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 type=\"button\"\n onClick={onCommit}\n disabled={saving || !value.trim()}\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 {saving ? 'Saving...' : 'Save'}\n </button>\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 sectionEl = document.querySelector(`[data-section=\"${anchor.section}\"]`);\n if (!sectionEl) return;\n sectionEl.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // If <DescriptionSection>'s post-render pass wrapped this snippet in a\n // <mark>, pulse just the mark for a tighter visual cue. Otherwise fall\n // back to ringing the whole section so something still flashes.\n const markEl =\n Array.from(sectionEl.querySelectorAll<HTMLElement>('mark.eb-tb-annot')).find((m) =>\n (m.textContent || '').includes(anchor.snippet)\n ) || (sectionEl.querySelector('mark.eb-tb-annot') as HTMLElement | null);\n if (markEl) {\n markEl.classList.add('eb-tb-annot-pulse');\n setTimeout(() => markEl.classList.remove('eb-tb-annot-pulse'), 1500);\n } else {\n sectionEl.classList.add('ring-2', 'ring-amber-300', 'rounded-lg', 'transition-all');\n setTimeout(() => {\n sectionEl.classList.remove('ring-2', 'ring-amber-300', 'rounded-lg');\n }, 1500);\n }\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_react","import_jsx_runtime","import_react","import_dnd","import_react","stripMentionMarkup","stripMentionMarkup","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_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","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"]}