diff options
Diffstat (limited to 'web/src/components/tickets/TicketCard.tsx')
| -rw-r--r-- | web/src/components/tickets/TicketCard.tsx | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/web/src/components/tickets/TicketCard.tsx b/web/src/components/tickets/TicketCard.tsx new file mode 100644 index 0000000..3b3926b --- /dev/null +++ b/web/src/components/tickets/TicketCard.tsx @@ -0,0 +1,66 @@ +/** + * TicketCard.tsx + * Card de ticket para uso na lista do dashboard. + */ + +import { useNavigate } from 'react-router-dom'; +import type { Ticket } from '@/lib/api'; +import { StatusBadge } from './StatusBadge'; +import { PriorityBadge } from './PriorityBadge'; +import styles from './TicketCard.module.css'; + +interface TicketCardProps { + ticket: Ticket; +} + +function formatDate(iso: string): string { + return new Intl.DateTimeFormat('pt-BR', { + day: '2-digit', + month: 'short', + hour: '2-digit', + minute: '2-digit', + }).format(new Date(iso)); +} + +export function TicketCard({ ticket }: TicketCardProps) { + const navigate = useNavigate(); + + return ( + <article + className={`${styles.card} ${styles[`priority_${ticket.priority}`]}`} + onClick={() => navigate(`/tickets/${ticket.id}`)} + role="button" + tabIndex={0} + onKeyDown={(e) => e.key === 'Enter' && navigate(`/tickets/${ticket.id}`)} + aria-label={`Ticket #${ticket.id}: ${ticket.title}`} + > + <div className={styles.top}> + <div className={styles.badges}> + <StatusBadge status={ticket.status} /> + <PriorityBadge priority={ticket.priority} /> + </div> + <span className={styles.id}>#{ticket.id}</span> + </div> + + <h3 className={styles.title}>{ticket.title}</h3> + + <p className={styles.description}>{ticket.description}</p> + + <div className={styles.footer}> + <span className={styles.meta}> + Aberto em {formatDate(ticket.createdAt)} + </span> + {ticket.assigneeId ? ( + <span className={styles.assigned}> + <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"> + <circle cx="12" cy="8" r="4" /><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7" /> + </svg> + Agente #{ticket.assigneeId} + </span> + ) : ( + <span className={styles.unassigned}>Sem agente</span> + )} + </div> + </article> + ); +} |