// frontend/src/components/TablaTitulares.tsx import { useState } from 'react'; import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Chip, IconButton, Typography, Link, TextField } from '@mui/material'; import DeleteIcon from '@mui/icons-material/Delete'; import DragHandleIcon from '@mui/icons-material/DragHandle'; import EditIcon from '@mui/icons-material/Edit'; import { DndContext, closestCenter, PointerSensor, useSensor, useSensors, type DragEndEvent } from '@dnd-kit/core'; import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import type { Titular } from '../types'; import type { ActualizarTitularPayload } from '../services/apiService'; interface SortableRowProps { titular: Titular; onDelete: (id: number) => void; onSave: (id: number, payload: ActualizarTitularPayload) => void; onEdit: (titular: Titular) => void; } const SortableRow = ({ titular, onDelete, onSave, onEdit }: SortableRowProps) => { const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: titular.id }); const [isEditing, setIsEditing] = useState(false); const [editText, setEditText] = useState(titular.texto); const style = { transform: CSS.Transform.toString(transform), transition }; const handleSave = () => { if (editText.trim() && editText.trim() !== titular.texto) { onSave(titular.id, { texto: editText.trim(), viñeta: titular.viñeta }); } setIsEditing(false); }; const getChipColor = (tipo: Titular['tipo']): "success" | "warning" | "info" => { if (tipo === 'Edited') return 'warning'; if (tipo === 'Manual') return 'info'; return 'success'; }; const formatFuente = (fuente: string | null) => { if (!fuente) return 'N/A'; try { const url = new URL(fuente); return url.hostname.replace('www.', ''); } catch { return fuente; } } return ( setIsEditing(true)}> {isEditing ? ( setEditText(e.target.value)} onBlur={handleSave} onKeyDown={(e) => { if (e.key === 'Enter') handleSave(); }} onClick={(e) => e.stopPropagation()} /> ) : ( {titular.texto} )} {titular.urlFuente ? ( {formatFuente(titular.fuente)} ) : ( formatFuente(titular.fuente) )} { e.stopPropagation(); onEdit(titular); }}> { e.stopPropagation(); onDelete(titular.id); }} sx={{ color: '#ef4444' }}> ); }; interface TablaTitularesProps { titulares: Titular[]; onReorder: (titulares: Titular[]) => void; onDelete: (id: number) => void; onEdit: (titular: Titular) => void; onSave: (id: number, payload: ActualizarTitularPayload) => void; } const TablaTitulares = ({ titulares, onReorder, onDelete, onEdit, onSave }: TablaTitularesProps) => { const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 8 } })); const handleDragEnd = (event: DragEndEvent) => { const { active, over } = event; if (over && active.id !== over.id) { const oldIndex = titulares.findIndex((item) => item.id === active.id); const newIndex = titulares.findIndex((item) => item.id === over.id); onReorder(arrayMove(titulares, oldIndex, newIndex)); } }; if (titulares.length === 0) { return ( No hay titulares para mostrar. ); } return ( t.id)} strategy={verticalListSortingStrategy}> Texto del Titular Tipo Fuente Acciones {titulares.map((titular) => ( ))}
); }; export default TablaTitulares;