fix: adiciona Card ao histórico de chat e lint no deploy

Histórico de chat:
- Adiciona Card branco igual à linha do tempo
- Corrige acentuações (Histórico, sessão, sessões)

CI/CD:
- Adiciona step de lint antes do build no workflow de deploy
- Se o lint falhar, o deploy é cancelado (fail fast)
- Evita que código com erros de lint seja deployado

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Seu Nome 2025-12-08 17:05:34 -03:00
parent 6147de138b
commit 8db7c3c810
2 changed files with 48 additions and 37 deletions

View file

@ -226,6 +226,15 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('pnpm-lock.yaml', 'bun.lock') }}- ${{ runner.os }}-nextjs-${{ hashFiles('pnpm-lock.yaml', 'bun.lock') }}-
- name: Lint check (fail fast before build)
run: |
cd "$EFFECTIVE_APP_DIR"
docker run --rm \
-v "$EFFECTIVE_APP_DIR":/app \
-w /app \
sistema_web:node22-bun \
bash -lc "set -euo pipefail; bun install --frozen-lockfile --filter '!appsdesktop'; bun run lint"
- name: Install and build (Next.js) - name: Install and build (Next.js)
env: env:
PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING: "1" PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING: "1"

View file

@ -8,6 +8,7 @@ import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel" import type { Id } from "@/convex/_generated/dataModel"
import { useAuth } from "@/lib/auth-client" import { useAuth } from "@/lib/auth-client"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Spinner } from "@/components/ui/spinner" import { Spinner } from "@/components/ui/spinner"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import { import {
@ -147,7 +148,7 @@ function ChatSessionCard({ session, isExpanded, onToggle }: { session: ChatSessi
return ( return (
<div className="rounded-xl border border-slate-200 bg-white overflow-hidden"> <div className="rounded-xl border border-slate-200 bg-white overflow-hidden">
{/* Header da sessao */} {/* Header da sessão */}
<button <button
onClick={onToggle} onClick={onToggle}
className="flex w-full items-center justify-between gap-3 px-4 py-3 text-left hover:bg-slate-50 transition-colors" className="flex w-full items-center justify-between gap-3 px-4 py-3 text-left hover:bg-slate-50 transition-colors"
@ -196,7 +197,7 @@ function ChatSessionCard({ session, isExpanded, onToggle }: { session: ChatSessi
<div className="border-t border-slate-100"> <div className="border-t border-slate-100">
{session.messages.length === 0 ? ( {session.messages.length === 0 ? (
<div className="flex items-center justify-center py-6 text-sm text-slate-400"> <div className="flex items-center justify-center py-6 text-sm text-slate-400">
Nenhuma mensagem nesta sessao Nenhuma mensagem nesta sessão
</div> </div>
) : ( ) : (
<> <>
@ -298,7 +299,7 @@ function DayGroupCard({
<Calendar className="size-4 text-slate-400" /> <Calendar className="size-4 text-slate-400" />
<span className="text-sm font-medium text-slate-700">{dayGroup.label}</span> <span className="text-sm font-medium text-slate-700">{dayGroup.label}</span>
<span className="text-xs text-slate-500"> <span className="text-xs text-slate-500">
({dayGroup.sessions.length} {dayGroup.sessions.length === 1 ? "sessao" : "sessoes"} - {dayGroup.totalMessages} mensagens) ({dayGroup.sessions.length} {dayGroup.sessions.length === 1 ? "sessão" : "sessões"} - {dayGroup.totalMessages} mensagens)
</span> </span>
</div> </div>
{isExpanded ? ( {isExpanded ? (
@ -308,7 +309,7 @@ function DayGroupCard({
)} )}
</button> </button>
{/* Sessoes do dia */} {/* Sessões do dia */}
{isExpanded && ( {isExpanded && (
<div className="space-y-2 pl-2"> <div className="space-y-2 pl-2">
{dayGroup.sessions.map((session) => ( {dayGroup.sessions.map((session) => (
@ -405,22 +406,22 @@ export function TicketChatHistory({ ticketId }: ChatHistoryProps) {
setVisibleDays((prev) => prev + DAYS_PER_PAGE) setVisibleDays((prev) => prev + DAYS_PER_PAGE)
} }
// Nao mostrar se nao ha historico // Não mostrar se não há histórico
if (!chatHistory || chatHistory.sessions.length === 0) { if (!chatHistory || chatHistory.sessions.length === 0) {
return null return null
} }
return ( return (
<div className="space-y-3"> <Card className="rounded-2xl border border-slate-200 bg-white shadow-sm">
<CardContent className="space-y-4 px-4 pb-6">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between"> <div className="flex flex-wrap items-center justify-between gap-3 border-b border-slate-200 pb-4">
<div className="flex items-center gap-2"> <div>
<MessageCircle className="size-4 text-slate-500" /> <h3 className="text-base font-semibold text-neutral-900">Histórico de chat</h3>
<h3 className="text-sm font-semibold text-slate-900">Historico de chat</h3> <p className="text-sm text-neutral-500">
{chatHistory.sessions.length} {chatHistory.sessions.length === 1 ? "sessão" : "sessões"} - {chatHistory.totalMessages} mensagens
</p>
</div> </div>
<span className="text-xs text-slate-500">
{chatHistory.sessions.length} {chatHistory.sessions.length === 1 ? "sessao" : "sessoes"} - {chatHistory.totalMessages} mensagens
</span>
</div> </div>
{/* Grupos por dia */} {/* Grupos por dia */}
@ -445,6 +446,7 @@ export function TicketChatHistory({ ticketId }: ChatHistoryProps) {
</Button> </Button>
</div> </div>
)} )}
</div> </CardContent>
</Card>
) )
} }