feat(front) react version start
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import { useState } from 'react'
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
Typography,
|
||||
Box,
|
||||
Chip,
|
||||
IconButton,
|
||||
Menu,
|
||||
MenuItem,
|
||||
} from '@mui/material'
|
||||
import MoreVertIcon from '@mui/icons-material/MoreVert'
|
||||
import { useDeleteSession, useUnblockSession } from './api'
|
||||
|
||||
function formatDate(d) {
|
||||
try {
|
||||
return new Date(d).toLocaleString()
|
||||
} catch {
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
export default function SessionCard({ session, onBlock }) {
|
||||
const [anchor, setAnchor] = useState(null)
|
||||
const deleteMutation = useDeleteSession()
|
||||
const unblockMutation = useUnblockSession()
|
||||
|
||||
const handleDelete = async () => {
|
||||
setAnchor(null)
|
||||
if (!window.confirm(`¿Eliminar la sesión de ${session.phone || 'desconocido'} y todo su historial de chat?`)) return
|
||||
deleteMutation.mutate({ id: session.id, phone: session.phone })
|
||||
}
|
||||
|
||||
const handleUnblock = async () => {
|
||||
setAnchor(null)
|
||||
if (!window.confirm(`Desbloquear sesión para ${session.phone}?`)) return
|
||||
unblockMutation.mutate({ phone: session.phone })
|
||||
}
|
||||
|
||||
const statusColor = session.finished ? 'success' : 'warning'
|
||||
const statusText = session.finished ? 'Finalizada' : 'Activa'
|
||||
|
||||
return (
|
||||
<Card sx={{ mb: 2 }}>
|
||||
<CardContent>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
||||
<Box sx={{ flex: 1, minWidth: 0 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: 600, overflowWrap: 'anywhere' }}>
|
||||
{session.name || `Teléfono: ${session.phone || 'desconocido'}`}
|
||||
{session.name && session.phone && (
|
||||
<Typography component="span" variant="caption" color="text.secondary" sx={{ ml: 1 }}>
|
||||
({session.phone})
|
||||
</Typography>
|
||||
)}
|
||||
</Typography>
|
||||
<Chip size="small" color={statusColor} label={statusText} />
|
||||
{session.block && (
|
||||
<Chip size="small" color="error" label="Bloqueada" />
|
||||
)}
|
||||
</Box>
|
||||
<Typography variant="caption" display="block" color="text.secondary" sx={{ mt: 0.5 }}>
|
||||
<strong>Resumen:</strong> {session.summary || 'Aún no hay resumen.'}
|
||||
</Typography>
|
||||
<Typography variant="caption" display="block" color="text.disabled" sx={{ mt: 1, overflowWrap: 'anywhere' }}>
|
||||
Campaña: {session.campaign_id?.split('-')[0] || 'N/A'}...
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', gap: 2, mt: 0.5, flexWrap: 'wrap' }}>
|
||||
<Typography variant="caption" color="text.disabled">
|
||||
Iniciada: {formatDate(session.created_at)}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.disabled">
|
||||
Última interacción: {session.last_interaction ? formatDate(session.last_interaction) : 'Ninguna'}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography variant="caption" display="block" color="text.disabled" sx={{ mt: 0.5, overflowWrap: 'anywhere' }}>
|
||||
ID de sesión: {session.id}
|
||||
</Typography>
|
||||
</Box>
|
||||
<IconButton onClick={(e) => setAnchor(e.currentTarget)}>
|
||||
<MoreVertIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</CardContent>
|
||||
<Menu anchorEl={anchor} open={Boolean(anchor)} onClose={() => setAnchor(null)}>
|
||||
{session.block ? (
|
||||
<MenuItem onClick={handleUnblock} sx={{ color: 'error.main' }}>
|
||||
Desbloquear
|
||||
</MenuItem>
|
||||
) : (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setAnchor(null)
|
||||
onBlock(session)
|
||||
}}
|
||||
sx={{ color: 'error.main' }}
|
||||
>
|
||||
Bloquear
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={handleDelete} sx={{ color: 'error.main' }}>
|
||||
Eliminar
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user