{"version":3,"sources":["../src/components/Forum/Forum.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\nimport {\n  CaretLeftIcon,\n  ChatCircleTextIcon,\n  CheckIcon,\n  DotsThreeVerticalIcon,\n  ImageIcon,\n  PencilSimpleIcon,\n  TrashIcon,\n} from '@phosphor-icons/react';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport Input from '../Input/Input';\nimport TextArea from '../TextArea/TextArea';\nimport Modal from '../Modal/Modal';\nimport Radio from '../Radio/Radio';\nimport DropdownMenu, {\n  DropdownMenuTrigger,\n  DropdownMenuContent,\n  DropdownMenuItem,\n} from '../DropdownMenu/DropdownMenu';\nimport { RichEditor } from '../RichEditor/RichEditor';\nimport ImageUpload from '../ImageUpload/ImageUpload';\nimport { SkeletonList, SkeletonCard } from '../Skeleton/Skeleton';\nimport { stripHtml, sanitizeHtmlForDisplay } from '../HtmlMathRenderer';\nimport { cn } from '../../utils/utils';\nimport type { ForumApiClient, ForumTopic, ForumReply } from '../../types/forum';\nimport { PROFILE_ROLES } from '../../types/chat';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst MONTHS_PT = [\n  'Janeiro',\n  'Fevereiro',\n  'Março',\n  'Abril',\n  'Maio',\n  'Junho',\n  'Julho',\n  'Agosto',\n  'Setembro',\n  'Outubro',\n  'Novembro',\n  'Dezembro',\n];\n\nfunction formatForumDate(isoDate: string): string {\n  const d = new Date(isoDate);\n  const day = d.getDate();\n  const month = MONTHS_PT[d.getMonth()];\n  const year = d.getFullYear();\n  const hours = d.getHours();\n  const minutes = d.getMinutes().toString().padStart(2, '0');\n  return `${day} ${month} ${year} • ${hours}:${minutes}`;\n}\n\nfunction getInitials(name: string): string {\n  return name\n    .split(' ')\n    .slice(0, 2)\n    .map((word) => word[0] ?? '')\n    .join('')\n    .toUpperCase();\n}\n\nfunction formatReplyCount(count: number): string {\n  if (count === 1) return '1 resposta';\n  return `${count} respostas`;\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\ninterface AuthorAvatarProps {\n  readonly name: string;\n  readonly photoUrl: string | null;\n}\n\nfunction AuthorAvatar({ name, photoUrl }: AuthorAvatarProps) {\n  if (photoUrl) {\n    return (\n      <img\n        src={photoUrl}\n        alt={name}\n        className=\"w-8 h-8 rounded-full object-cover shrink-0\"\n      />\n    );\n  }\n  return (\n    <div className=\"w-8 h-8 rounded-full bg-primary-600 flex items-center justify-center shrink-0\">\n      <Text size=\"xs\" weight=\"semibold\" color=\"text-white\">\n        {getInitials(name)}\n      </Text>\n    </div>\n  );\n}\n\ninterface AuthorMetaProps {\n  readonly authorName: string;\n  readonly authorPhoto: string | null;\n  readonly createdAt: string;\n}\n\nfunction AuthorMeta({ authorName, authorPhoto, createdAt }: AuthorMetaProps) {\n  return (\n    <div className=\"flex items-center gap-2\">\n      <AuthorAvatar name={authorName} photoUrl={authorPhoto} />\n      <div className=\"flex items-center gap-1\">\n        <Text size=\"xs\" weight=\"semibold\" color=\"text-primary-700\">\n          Postado por {authorName}\n        </Text>\n        <Text size=\"xs\" color=\"text-text-600\">\n          • {formatForumDate(createdAt)}\n        </Text>\n      </div>\n    </div>\n  );\n}\n\ninterface PostActionsMenuProps {\n  readonly onEdit: () => void;\n  readonly onDelete: () => void;\n}\n\nfunction PostActionsMenu({ onEdit, onDelete }: PostActionsMenuProps) {\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger\n        aria-label=\"Abrir ações do post\"\n        className=\"p-1 rounded hover:bg-background-100 transition-colors shrink-0\"\n      >\n        <DotsThreeVerticalIcon size={20} className=\"text-text-600\" />\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align=\"end\">\n        <DropdownMenuItem\n          iconLeft={<PencilSimpleIcon size={16} />}\n          onClick={onEdit}\n        >\n          Editar\n        </DropdownMenuItem>\n        <DropdownMenuItem iconLeft={<TrashIcon size={16} />} onClick={onDelete}>\n          Deletar\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n\ninterface PostContentModalProps {\n  readonly isOpen: boolean;\n  readonly title: string;\n  readonly submitLabel: string;\n  readonly content: string;\n  readonly imageUrl: string | undefined;\n  readonly isSubmitting: boolean;\n  readonly onContentChange: (value: string) => void;\n  readonly onClose: () => void;\n  readonly onSubmit: () => void;\n  readonly onUploadImage?: (file: File) => Promise<string>;\n  readonly onImageUploaded: (url: string) => void;\n  readonly maxLength: number;\n  /** Use RichEditor with toolbar instead of plain TextArea */\n  readonly richText?: boolean;\n  /** Show \"Este fórum vale nota no boletim?\" question (professor only) */\n  readonly showGradeQuestion?: boolean;\n  readonly countsForGrade?: boolean;\n  readonly onCountsForGradeChange?: (value: boolean) => void;\n}\n\nfunction PostContentModal({\n  isOpen,\n  title,\n  submitLabel,\n  content,\n  imageUrl,\n  isSubmitting,\n  onContentChange,\n  onClose,\n  onSubmit,\n  onUploadImage,\n  onImageUploaded,\n  maxLength,\n  richText = false,\n  showGradeQuestion = false,\n  countsForGrade,\n  onCountsForGradeChange,\n}: PostContentModalProps) {\n  const handleImageSelect = useCallback(\n    async (file: File) => {\n      if (!onUploadImage) return;\n      try {\n        const url = await onUploadImage(file);\n        onImageUploaded(url);\n      } catch {\n        // silently fail — consuming app should handle upload errors\n      }\n    },\n    [onUploadImage, onImageUploaded]\n  );\n\n  // Determine if content is effectively empty or exceeds the limit\n  const plainTextContent = richText ? stripHtml(content) : content;\n  const isContentEmpty = !plainTextContent.trim();\n  const exceedsMaxLength = plainTextContent.trim().length > maxLength;\n\n  return (\n    <Modal\n      isOpen={isOpen}\n      onClose={onClose}\n      title={title}\n      size=\"md\"\n      footer={\n        <div className=\"flex justify-end gap-2\">\n          <Button\n            variant=\"outline\"\n            action=\"secondary\"\n            size=\"medium\"\n            onClick={onClose}\n          >\n            Cancelar\n          </Button>\n          <Button\n            variant=\"solid\"\n            action=\"primary\"\n            size=\"medium\"\n            disabled={isContentEmpty || exceedsMaxLength || isSubmitting}\n            onClick={onSubmit}\n          >\n            {submitLabel}\n          </Button>\n        </div>\n      }\n    >\n      <div className=\"flex flex-col gap-3\">\n        {richText ? (\n          // key forces remount (and thus reset) whenever the modal opens/closes\n          <RichEditor\n            key={String(isOpen)}\n            content={content}\n            onChange={(data) => onContentChange(data.html)}\n            placeholder=\"Escreva o conteúdo do seu post aqui.\"\n          />\n        ) : (\n          <TextArea\n            placeholder=\"Escreva o conteúdo do seu post aqui.\"\n            value={content}\n            onChange={(e) => onContentChange(e.target.value)}\n            autoResize\n            minHeight={120}\n            maxLength={maxLength}\n          />\n        )}\n\n        <ImageUpload\n          variant=\"compact\"\n          onFileSelect={handleImageSelect}\n          onRemoveFile={() => onImageUploaded('')}\n          buttonIcon={<ImageIcon size={16} />}\n        />\n        {imageUrl && (\n          <img\n            src={imageUrl}\n            alt=\"Preview da imagem\"\n            className=\"max-h-40 rounded-lg object-contain\"\n          />\n        )}\n\n        {showGradeQuestion && (\n          <div className=\"flex flex-col gap-2\">\n            <Text size=\"sm\" weight=\"medium\">\n              Este fórum vale nota no boletim?\n            </Text>\n            <div className=\"flex items-center gap-4\">\n              <Radio\n                name=\"countsForGrade\"\n                value=\"yes\"\n                label=\"Sim\"\n                size=\"small\"\n                checked={countsForGrade === true}\n                onChange={() => onCountsForGradeChange?.(true)}\n              />\n              <Radio\n                name=\"countsForGrade\"\n                value=\"no\"\n                label=\"Não\"\n                size=\"small\"\n                checked={countsForGrade === false}\n                onChange={() => onCountsForGradeChange?.(false)}\n              />\n            </div>\n          </div>\n        )}\n      </div>\n    </Modal>\n  );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton\n// ---------------------------------------------------------------------------\n\nfunction TopicListSkeleton() {\n  return (\n    <SkeletonList items={3} showAvatar showTitle showDescription lines={2} />\n  );\n}\n\nfunction TopicDetailSkeleton() {\n  return (\n    <SkeletonCard\n      showAvatar\n      showTitle\n      showDescription\n      showActions={false}\n      lines={2}\n    />\n  );\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nexport type ForumProps = {\n  /** API client with forum CRUD methods */\n  readonly apiClient: ForumApiClient;\n  /** Current user's userInstitutionId — used to identify own posts */\n  readonly currentUserId: string;\n  /** User role — enables professor-specific features (e.g. grade question on create) */\n  readonly userRole?: PROFILE_ROLES.STUDENT | PROFILE_ROLES.TEACHER;\n  /** Forum page title */\n  readonly title?: string;\n  /** Forum page subtitle */\n  readonly subtitle?: string;\n  /** Callback to upload an image file and return its hosted URL */\n  readonly onUploadImage?: (file: File) => Promise<string>;\n  /**\n   * Callback to evaluate a reply (teacher only).\n   * If provided, an \"Avaliar\" button appears on each reply when the topic counts for grade.\n   */\n  readonly onEvaluateReply?: (replyId: string, grade: number) => Promise<void>;\n  /** Additional CSS classes */\n  readonly className?: string;\n};\n\nexport function Forum({\n  apiClient,\n  currentUserId,\n  userRole = PROFILE_ROLES.STUDENT,\n  title = 'Fórum',\n  subtitle = 'Espaço para troca de conhecimento',\n  onUploadImage,\n  onEvaluateReply,\n  className,\n}: ForumProps) {\n  const isTeacher = userRole === PROFILE_ROLES.TEACHER;\n  const [view, setView] = useState<'list' | 'detail'>('list');\n  const [topics, setTopics] = useState<ForumTopic[]>([]);\n  const [isLoadingTopics, setIsLoadingTopics] = useState(false);\n  const [selectedTopic, setSelectedTopic] = useState<ForumTopic | null>(null);\n  const [replies, setReplies] = useState<ForumReply[]>([]);\n  const [isLoadingTopic, setIsLoadingTopic] = useState(false);\n  const [isSubmitting, setIsSubmitting] = useState(false);\n\n  // Create post modal state\n  const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);\n  const [createContent, setCreateContent] = useState('');\n  const [createImageUrl, setCreateImageUrl] = useState<string | undefined>();\n  const [createCountsForGrade, setCreateCountsForGrade] = useState<\n    boolean | undefined\n  >();\n\n  // Reply modal state\n  const [isReplyModalOpen, setIsReplyModalOpen] = useState(false);\n  const [replyContent, setReplyContent] = useState('');\n  const [replyImageUrl, setReplyImageUrl] = useState<string | undefined>();\n\n  // Edit topic modal state\n  const [editingTopic, setEditingTopic] = useState<ForumTopic | null>(null);\n  const [editTopicContent, setEditTopicContent] = useState('');\n  const [editTopicImageUrl, setEditTopicImageUrl] = useState<\n    string | undefined\n  >();\n\n  // Edit reply modal state\n  const [editingReply, setEditingReply] = useState<ForumReply | null>(null);\n  const [editReplyContent, setEditReplyContent] = useState('');\n  const [editReplyImageUrl, setEditReplyImageUrl] = useState<\n    string | undefined\n  >();\n\n  // Evaluate reply modal state (teacher only)\n  const [evaluatingReplyId, setEvaluatingReplyId] = useState<string | null>(\n    null\n  );\n  const [gradeValue, setGradeValue] = useState<number | null>(null);\n  const [isEditingGrade, setIsEditingGrade] = useState(false);\n\n  // Delete confirmation state\n  const [pendingDelete, setPendingDelete] = useState<\n    { type: 'topic'; id: string } | { type: 'reply'; id: string } | null\n  >(null);\n\n  const fetchTopics = useCallback(async () => {\n    setIsLoadingTopics(true);\n    try {\n      const response = await apiClient.getTopics({ limit: 50 });\n      setTopics(response.topics);\n    } finally {\n      setIsLoadingTopics(false);\n    }\n  }, [apiClient]);\n\n  const fetchTopic = useCallback(\n    async (topicId: string) => {\n      setIsLoadingTopic(true);\n      try {\n        const response = await apiClient.getTopic(topicId);\n        setSelectedTopic(response.topic);\n        setReplies(response.replies);\n      } finally {\n        setIsLoadingTopic(false);\n      }\n    },\n    [apiClient]\n  );\n\n  useEffect(() => {\n    fetchTopics();\n  }, [fetchTopics]);\n\n  const handleTopicClick = useCallback(\n    (topic: ForumTopic) => {\n      setSelectedTopic(topic);\n      setView('detail');\n      fetchTopic(topic.id);\n    },\n    [fetchTopic]\n  );\n\n  const handleBack = useCallback(() => {\n    setView('list');\n    setSelectedTopic(null);\n    setReplies([]);\n    fetchTopics();\n  }, [fetchTopics]);\n\n  // Create topic\n  const handleCloseCreateModal = useCallback(() => {\n    setIsCreateModalOpen(false);\n    setCreateContent('');\n    setCreateImageUrl(undefined);\n    setCreateCountsForGrade(undefined);\n  }, []);\n\n  const handleCreateTopic = useCallback(async () => {\n    if (!createContent.trim()) return;\n    setIsSubmitting(true);\n    try {\n      await apiClient.createTopic({\n        content: createContent.trim(),\n        ...(createImageUrl && { imageUrl: createImageUrl }),\n        ...(isTeacher &&\n          createCountsForGrade !== undefined && {\n            countsForGrade: createCountsForGrade,\n          }),\n      });\n      handleCloseCreateModal();\n      await fetchTopics();\n    } finally {\n      setIsSubmitting(false);\n    }\n  }, [\n    apiClient,\n    createContent,\n    createImageUrl,\n    createCountsForGrade,\n    isTeacher,\n    handleCloseCreateModal,\n    fetchTopics,\n  ]);\n\n  // Edit topic\n  const handleOpenEditTopic = useCallback((topic: ForumTopic) => {\n    setEditingTopic(topic);\n    setEditTopicContent(topic.content);\n    setEditTopicImageUrl(topic.imageUrl ?? undefined);\n  }, []);\n\n  const handleCloseEditTopic = useCallback(() => {\n    setEditingTopic(null);\n    setEditTopicContent('');\n    setEditTopicImageUrl(undefined);\n  }, []);\n\n  const handleEditTopic = useCallback(async () => {\n    if (!editingTopic || !editTopicContent.trim()) return;\n    setIsSubmitting(true);\n    try {\n      await apiClient.updateTopic(editingTopic.id, {\n        content: editTopicContent.trim(),\n        imageUrl: editTopicImageUrl ?? null,\n      });\n      handleCloseEditTopic();\n      if (view === 'list') {\n        await fetchTopics();\n      } else {\n        await fetchTopic(editingTopic.id);\n      }\n    } finally {\n      setIsSubmitting(false);\n    }\n  }, [\n    apiClient,\n    editingTopic,\n    editTopicContent,\n    editTopicImageUrl,\n    handleCloseEditTopic,\n    view,\n    fetchTopics,\n    fetchTopic,\n  ]);\n\n  const handleDeleteTopic = useCallback(\n    async (topicId: string) => {\n      setIsSubmitting(true);\n      try {\n        await apiClient.deleteTopic(topicId);\n        if (view === 'detail') {\n          handleBack();\n        } else {\n          await fetchTopics();\n        }\n      } finally {\n        setIsSubmitting(false);\n        setPendingDelete(null);\n      }\n    },\n    [apiClient, view, handleBack, fetchTopics]\n  );\n\n  // Reply\n  const handleCloseReplyModal = useCallback(() => {\n    setIsReplyModalOpen(false);\n    setReplyContent('');\n    setReplyImageUrl(undefined);\n  }, []);\n\n  const handleCreateReply = useCallback(async () => {\n    if (!selectedTopic || !replyContent.trim()) return;\n    setIsSubmitting(true);\n    try {\n      await apiClient.createReply(selectedTopic.id, {\n        content: replyContent.trim(),\n        ...(replyImageUrl && { imageUrl: replyImageUrl }),\n      });\n      handleCloseReplyModal();\n      await fetchTopic(selectedTopic.id);\n    } finally {\n      setIsSubmitting(false);\n    }\n  }, [\n    apiClient,\n    selectedTopic,\n    replyContent,\n    replyImageUrl,\n    handleCloseReplyModal,\n    fetchTopic,\n  ]);\n\n  // Edit reply\n  const handleOpenEditReply = useCallback((reply: ForumReply) => {\n    setEditingReply(reply);\n    setEditReplyContent(reply.content);\n    setEditReplyImageUrl(reply.imageUrl ?? undefined);\n  }, []);\n\n  const handleCloseEditReply = useCallback(() => {\n    setEditingReply(null);\n    setEditReplyContent('');\n    setEditReplyImageUrl(undefined);\n  }, []);\n\n  const handleEditReply = useCallback(async () => {\n    if (!editingReply || !editReplyContent.trim() || !selectedTopic) return;\n    setIsSubmitting(true);\n    try {\n      await apiClient.updateReply(editingReply.id, {\n        content: editReplyContent.trim(),\n        imageUrl: editReplyImageUrl ?? null,\n      });\n      handleCloseEditReply();\n      await fetchTopic(selectedTopic.id);\n    } finally {\n      setIsSubmitting(false);\n    }\n  }, [\n    apiClient,\n    editingReply,\n    editReplyContent,\n    editReplyImageUrl,\n    handleCloseEditReply,\n    selectedTopic,\n    fetchTopic,\n  ]);\n\n  const handleDeleteReply = useCallback(\n    async (replyId: string) => {\n      if (!selectedTopic) return;\n      setIsSubmitting(true);\n      try {\n        await apiClient.deleteReply(replyId);\n        await fetchTopic(selectedTopic.id);\n      } finally {\n        setIsSubmitting(false);\n        setPendingDelete(null);\n      }\n    },\n    [apiClient, selectedTopic, fetchTopic]\n  );\n\n  const handleCloseEvaluateModal = useCallback(() => {\n    setEvaluatingReplyId(null);\n    setGradeValue(null);\n    setIsEditingGrade(false);\n  }, []);\n\n  const handleOpenEvaluate = useCallback((reply: ForumReply) => {\n    setEvaluatingReplyId(reply.id);\n    setGradeValue(null);\n    setIsEditingGrade(false);\n  }, []);\n\n  const handleOpenEditGrade = useCallback((reply: ForumReply) => {\n    setEvaluatingReplyId(reply.id);\n    setGradeValue(reply.grade ?? null);\n    setIsEditingGrade(true);\n  }, []);\n\n  const isValidGrade =\n    gradeValue !== null &&\n    Number.isInteger(gradeValue) &&\n    gradeValue >= 0 &&\n    gradeValue <= 10;\n\n  const handleSubmitEvaluation = useCallback(async () => {\n    if (!evaluatingReplyId || !isValidGrade || !onEvaluateReply) return;\n    setIsSubmitting(true);\n    try {\n      await onEvaluateReply(evaluatingReplyId, gradeValue);\n      // Optimistically update grade in local state\n      setReplies((prev) =>\n        prev.map((r) =>\n          r.id === evaluatingReplyId ? { ...r, grade: gradeValue } : r\n        )\n      );\n      handleCloseEvaluateModal();\n    } finally {\n      setIsSubmitting(false);\n    }\n  }, [\n    evaluatingReplyId,\n    gradeValue,\n    isValidGrade,\n    onEvaluateReply,\n    handleCloseEvaluateModal,\n  ]);\n\n  const handleConfirmDelete = useCallback(async () => {\n    if (!pendingDelete) return;\n    if (pendingDelete.type === 'topic') {\n      await handleDeleteTopic(pendingDelete.id);\n    } else {\n      await handleDeleteReply(pendingDelete.id);\n    }\n  }, [pendingDelete, handleDeleteTopic, handleDeleteReply]);\n\n  /* ---- Extracted render blocks (avoids nested ternaries — SonarQube) ---- */\n\n  const topicListContent = (() => {\n    if (isLoadingTopics) return <TopicListSkeleton />;\n\n    if (topics.length === 0) {\n      return (\n        <div className=\"flex items-center justify-center py-16 border border-border-200 rounded-lg\">\n          <Text size=\"md\" color=\"text-text-500\">\n            Nenhum tópico ainda. Seja o primeiro a criar um post!\n          </Text>\n        </div>\n      );\n    }\n\n    return (\n      <div className=\"flex flex-col gap-4\">\n        {topics.map((topic) => (\n          <div\n            key={topic.id}\n            className=\"flex items-start bg-white border border-border-100 rounded-lg pt-4 pr-2 pb-4 pl-2 shadow-sm\"\n          >\n            {/* Clickable content area */}\n            <button\n              type=\"button\"\n              className=\"flex flex-col gap-3 flex-1 min-w-0 text-left hover:opacity-90 transition-opacity\"\n              onClick={() => handleTopicClick(topic)}\n            >\n              <AuthorMeta\n                authorName={topic.authorName}\n                authorPhoto={topic.authorPhoto}\n                createdAt={topic.createdAt}\n              />\n              <Text size=\"sm\" className=\"leading-normal line-clamp-3 ml-10\">\n                {stripHtml(topic.content)}\n              </Text>\n              <div className=\"flex items-center gap-1 text-text-600 ml-10\">\n                <ChatCircleTextIcon size={16} />\n                <Text size=\"xs\">{formatReplyCount(topic.replyCount)}</Text>\n              </div>\n            </button>\n\n            {/* Actions menu — only for own posts */}\n            {topic.userInstitutionId === currentUserId && (\n              <PostActionsMenu\n                onEdit={() => handleOpenEditTopic(topic)}\n                onDelete={() =>\n                  setPendingDelete({ type: 'topic', id: topic.id })\n                }\n              />\n            )}\n          </div>\n        ))}\n      </div>\n    );\n  })();\n\n  const topicDetailContent = (() => {\n    if (isLoadingTopic) return <TopicDetailSkeleton />;\n\n    if (!selectedTopic) return null;\n\n    return (\n      <>\n        {/* Original post */}\n        <div className=\"flex items-start gap-2\">\n          <div className=\"flex flex-col gap-3 flex-1 min-w-0\">\n            <AuthorMeta\n              authorName={selectedTopic.authorName}\n              authorPhoto={selectedTopic.authorPhoto}\n              createdAt={selectedTopic.createdAt}\n            />\n            <div\n              className=\"text-sm text-text-950 leading-normal ml-10 prose prose-sm max-w-none\"\n              dangerouslySetInnerHTML={{\n                __html: sanitizeHtmlForDisplay(selectedTopic.content),\n              }}\n            />\n            {selectedTopic.imageUrl && (\n              <img\n                src={selectedTopic.imageUrl}\n                alt=\"Imagem do post\"\n                className=\"ml-10 max-w-lg rounded-lg\"\n              />\n            )}\n          </div>\n          {selectedTopic.userInstitutionId === currentUserId && (\n            <PostActionsMenu\n              onEdit={() => handleOpenEditTopic(selectedTopic)}\n              onDelete={() =>\n                setPendingDelete({ type: 'topic', id: selectedTopic.id })\n              }\n            />\n          )}\n        </div>\n\n        {/* Replies header */}\n        <div className=\"flex items-center justify-between\">\n          <Text size=\"sm\" color=\"text-text-600\">\n            {formatReplyCount(selectedTopic.replyCount)}\n          </Text>\n          <Button\n            variant=\"solid\"\n            action=\"primary\"\n            size=\"medium\"\n            onClick={() => setIsReplyModalOpen(true)}\n          >\n            Responder\n          </Button>\n        </div>\n\n        {/* Replies list */}\n        {replies.length > 0 && (\n          <div className=\"flex flex-col divide-y divide-border-200\">\n            {replies.map((reply) => (\n              <div key={reply.id} className=\"flex items-start gap-2 py-4\">\n                <div className=\"flex flex-col gap-3 flex-1 min-w-0\">\n                  <AuthorMeta\n                    authorName={reply.authorName}\n                    authorPhoto={reply.authorPhoto}\n                    createdAt={reply.createdAt}\n                  />\n                  <div\n                    className=\"text-sm text-text-950 leading-normal ml-10 prose prose-sm max-w-none\"\n                    dangerouslySetInnerHTML={{\n                      __html: sanitizeHtmlForDisplay(reply.content),\n                    }}\n                  />\n                  {reply.imageUrl && (\n                    <img\n                      src={reply.imageUrl}\n                      alt=\"Imagem da resposta\"\n                      className=\"ml-10 max-w-lg rounded-lg\"\n                    />\n                  )}\n                  {isTeacher &&\n                    selectedTopic?.countsForGrade &&\n                    onEvaluateReply &&\n                    (reply.grade == null ? (\n                      /* Not yet graded — show Avaliar button */\n                      <button\n                        type=\"button\"\n                        className=\"flex items-center gap-1.5 text-text-600 text-sm hover:text-text-950 transition-colors w-fit ml-10\"\n                        onClick={() => handleOpenEvaluate(reply)}\n                      >\n                        <CheckIcon size={16} />\n                        Avaliar\n                      </button>\n                    ) : (\n                      /* Grade already set — teacher sees it with edit pencil */\n                      <div className=\"flex items-center gap-1.5 ml-10\">\n                        <Text size=\"sm\" color=\"text-text-600\">\n                          Nota {reply.grade}\n                        </Text>\n                        <button\n                          type=\"button\"\n                          className=\"text-text-600 hover:text-text-950 transition-colors\"\n                          onClick={() => handleOpenEditGrade(reply)}\n                        >\n                          <PencilSimpleIcon size={14} />\n                        </button>\n                      </div>\n                    ))}\n                  {!isTeacher &&\n                    reply.grade != null &&\n                    reply.userInstitutionId === currentUserId &&\n                    selectedTopic?.countsForGrade && (\n                      <Text size=\"sm\" color=\"text-text-600\" className=\"ml-10\">\n                        Nota {reply.grade}\n                      </Text>\n                    )}\n                </div>\n                {reply.userInstitutionId === currentUserId && (\n                  <PostActionsMenu\n                    onEdit={() => handleOpenEditReply(reply)}\n                    onDelete={() =>\n                      setPendingDelete({ type: 'reply', id: reply.id })\n                    }\n                  />\n                )}\n              </div>\n            ))}\n          </div>\n        )}\n      </>\n    );\n  })();\n\n  return (\n    <div className={cn('flex flex-col gap-4', className)}>\n      {view === 'list' ? (\n        <>\n          {/* Header */}\n          <div className=\"flex items-center justify-between\">\n            <Text as=\"h1\" size=\"2xl\" weight=\"bold\" color=\"text-text-950\">\n              {title}\n            </Text>\n            <Button\n              variant=\"solid\"\n              action=\"primary\"\n              size=\"medium\"\n              onClick={() => setIsCreateModalOpen(true)}\n            >\n              Criar post\n            </Button>\n          </div>\n\n          {/* Subtitle + topic list */}\n          <div className=\"flex flex-col gap-3\">\n            <Text as=\"h2\" size=\"lg\" weight=\"semibold\" color=\"text-text-950\">\n              {subtitle}\n            </Text>\n\n            {topicListContent}\n          </div>\n        </>\n      ) : (\n        /* Detail view */\n        <>\n          <button\n            type=\"button\"\n            className=\"flex items-center gap-2 hover:opacity-80 transition-opacity w-fit\"\n            onClick={handleBack}\n          >\n            <CaretLeftIcon size={24} className=\"text-text-950\" />\n            <Text size=\"2xl\" weight=\"bold\">\n              Voltar\n            </Text>\n          </button>\n\n          {topicDetailContent}\n        </>\n      )}\n\n      {/* Create post modal */}\n      <PostContentModal\n        isOpen={isCreateModalOpen}\n        title=\"Criar post\"\n        submitLabel=\"Criar post\"\n        content={createContent}\n        imageUrl={createImageUrl}\n        isSubmitting={isSubmitting}\n        onContentChange={setCreateContent}\n        onClose={handleCloseCreateModal}\n        onSubmit={handleCreateTopic}\n        onUploadImage={onUploadImage}\n        onImageUploaded={setCreateImageUrl}\n        maxLength={10000}\n        richText\n        showGradeQuestion={isTeacher}\n        countsForGrade={createCountsForGrade}\n        onCountsForGradeChange={setCreateCountsForGrade}\n      />\n\n      {/* Reply modal */}\n      <PostContentModal\n        isOpen={isReplyModalOpen}\n        title=\"Responder\"\n        submitLabel=\"Responder\"\n        content={replyContent}\n        imageUrl={replyImageUrl}\n        isSubmitting={isSubmitting}\n        onContentChange={setReplyContent}\n        onClose={handleCloseReplyModal}\n        onSubmit={handleCreateReply}\n        onUploadImage={onUploadImage}\n        onImageUploaded={setReplyImageUrl}\n        maxLength={5000}\n        richText\n      />\n\n      {/* Edit topic modal */}\n      <PostContentModal\n        isOpen={!!editingTopic}\n        title=\"Editar\"\n        submitLabel=\"Salvar\"\n        content={editTopicContent}\n        imageUrl={editTopicImageUrl}\n        isSubmitting={isSubmitting}\n        onContentChange={setEditTopicContent}\n        onClose={handleCloseEditTopic}\n        onSubmit={handleEditTopic}\n        onUploadImage={onUploadImage}\n        onImageUploaded={setEditTopicImageUrl}\n        maxLength={10000}\n        richText\n      />\n\n      {/* Edit reply modal */}\n      <PostContentModal\n        isOpen={!!editingReply}\n        title=\"Editar\"\n        submitLabel=\"Salvar\"\n        content={editReplyContent}\n        imageUrl={editReplyImageUrl}\n        isSubmitting={isSubmitting}\n        onContentChange={setEditReplyContent}\n        onClose={handleCloseEditReply}\n        onSubmit={handleEditReply}\n        onUploadImage={onUploadImage}\n        onImageUploaded={setEditReplyImageUrl}\n        maxLength={5000}\n        richText\n      />\n\n      {/* Evaluate / edit grade modal (teacher only) */}\n      <Modal\n        isOpen={!!evaluatingReplyId}\n        onClose={handleCloseEvaluateModal}\n        title={\n          isEditingGrade\n            ? 'Edite a nota da atividade'\n            : 'Defina a nota da atividade'\n        }\n        size=\"md\"\n        footer={\n          <div className=\"flex justify-end gap-2\">\n            <Button\n              variant=\"outline\"\n              action=\"secondary\"\n              size=\"medium\"\n              onClick={handleCloseEvaluateModal}\n            >\n              Cancelar\n            </Button>\n            <Button\n              variant=\"solid\"\n              action=\"primary\"\n              size=\"medium\"\n              disabled={!isValidGrade || isSubmitting}\n              onClick={handleSubmitEvaluation}\n            >\n              {isEditingGrade ? 'Salvar' : 'Avaliar'}\n            </Button>\n          </div>\n        }\n      >\n        <Input\n          type=\"number\"\n          min={0}\n          max={10}\n          step={1}\n          placeholder=\"Nota (0-10)\"\n          value={gradeValue ?? ''}\n          onChange={(e) => {\n            const val = e.target.value;\n            const parsed = Number(val);\n            setGradeValue(val === '' || Number.isNaN(parsed) ? null : parsed);\n          }}\n        />\n      </Modal>\n\n      {/* Delete confirmation modal */}\n      <Modal\n        isOpen={!!pendingDelete}\n        onClose={() => setPendingDelete(null)}\n        title=\"Deseja deletar post?\"\n        size=\"sm\"\n        footer={\n          <div className=\"flex justify-end gap-2\">\n            <Button\n              variant=\"outline\"\n              action=\"secondary\"\n              size=\"medium\"\n              onClick={() => setPendingDelete(null)}\n            >\n              Cancelar\n            </Button>\n            <Button\n              variant=\"solid\"\n              action=\"negative\"\n              size=\"medium\"\n              disabled={isSubmitting}\n              onClick={handleConfirmDelete}\n            >\n              Deletar\n            </Button>\n          </div>\n        }\n      >\n        <Text size=\"md\" color=\"text-text-600\">\n          Essa ação é permanente e não poderá ser desfeita.\n        </Text>\n      </Modal>\n    </div>\n  );\n}\n\nexport default Forum;\n"],"mappings":"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","names":[]}