127 lines
4.1 KiB
TypeScript
127 lines
4.1 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Check, Trash2, Clock, X } from 'lucide-react';
|
|
import { Button } from '../../ui/Button';
|
|
import AlertSnoozeMenu from './AlertSnoozeMenu';
|
|
|
|
export interface AlertBulkActionsProps {
|
|
selectedCount: number;
|
|
onMarkAsRead: () => void;
|
|
onRemove: () => void;
|
|
onSnooze: (duration: '15min' | '1hr' | '4hr' | 'tomorrow' | number) => void;
|
|
onDeselectAll: () => void;
|
|
onSelectAll: () => void;
|
|
totalCount: number;
|
|
}
|
|
|
|
const AlertBulkActions: React.FC<AlertBulkActionsProps> = ({
|
|
selectedCount,
|
|
onMarkAsRead,
|
|
onRemove,
|
|
onSnooze,
|
|
onDeselectAll,
|
|
onSelectAll,
|
|
totalCount,
|
|
}) => {
|
|
const [showSnoozeMenu, setShowSnoozeMenu] = useState(false);
|
|
|
|
if (selectedCount === 0) {
|
|
return null;
|
|
}
|
|
|
|
const handleSnooze = (duration: '15min' | '1hr' | '4hr' | 'tomorrow' | number) => {
|
|
onSnooze(duration);
|
|
setShowSnoozeMenu(false);
|
|
};
|
|
|
|
const allSelected = selectedCount === totalCount;
|
|
|
|
return (
|
|
<div className="sticky top-0 z-20 bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-primary-dark)] text-white px-4 py-3 rounded-xl shadow-xl flex items-center justify-between gap-3 animate-in slide-in-from-top-2 duration-300">
|
|
<div className="flex items-center gap-3 flex-1 min-w-0">
|
|
<div className="flex items-center gap-2 px-3 py-1.5 bg-white/20 backdrop-blur-sm rounded-lg">
|
|
<span className="text-sm font-bold">{selectedCount}</span>
|
|
<span className="text-xs font-medium opacity-90">
|
|
{selectedCount === 1 ? 'seleccionado' : 'seleccionados'}
|
|
</span>
|
|
</div>
|
|
|
|
{!allSelected && totalCount > selectedCount && (
|
|
<button
|
|
onClick={onSelectAll}
|
|
className="text-sm font-medium hover:underline opacity-90 hover:opacity-100 transition-opacity whitespace-nowrap"
|
|
aria-label={`Select all ${totalCount} alerts`}
|
|
>
|
|
Seleccionar todos ({totalCount})
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2 relative flex-shrink-0">
|
|
{/* Quick Actions */}
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={onMarkAsRead}
|
|
className="bg-white/15 text-white border-white/30 hover:bg-white/25 backdrop-blur-sm h-9 px-3"
|
|
aria-label="Mark all selected as read"
|
|
>
|
|
<Check className="w-4 h-4 sm:mr-2" />
|
|
<span className="hidden sm:inline">Marcar leídos</span>
|
|
</Button>
|
|
|
|
<div className="relative">
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={() => setShowSnoozeMenu(!showSnoozeMenu)}
|
|
className="bg-white/15 text-white border-white/30 hover:bg-white/25 backdrop-blur-sm h-9 px-3"
|
|
aria-label="Snooze selected alerts"
|
|
>
|
|
<Clock className="w-4 h-4 sm:mr-2" />
|
|
<span className="hidden sm:inline">Posponer</span>
|
|
</Button>
|
|
|
|
{showSnoozeMenu && (
|
|
<>
|
|
<div
|
|
className="fixed inset-0 z-20"
|
|
onClick={() => setShowSnoozeMenu(false)}
|
|
aria-hidden="true"
|
|
/>
|
|
<div className="absolute right-0 top-full mt-2 z-30">
|
|
<AlertSnoozeMenu
|
|
onSnooze={handleSnooze}
|
|
onCancel={() => setShowSnoozeMenu(false)}
|
|
/>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={onRemove}
|
|
className="bg-red-500/25 text-white border-red-300/40 hover:bg-red-500/40 backdrop-blur-sm h-9 px-3"
|
|
aria-label="Delete selected alerts"
|
|
>
|
|
<Trash2 className="w-4 h-4 sm:mr-2" />
|
|
<span className="hidden sm:inline">Eliminar</span>
|
|
</Button>
|
|
|
|
{/* Close button */}
|
|
<button
|
|
onClick={onDeselectAll}
|
|
className="ml-1 p-2 hover:bg-white/15 rounded-lg transition-colors"
|
|
aria-label="Deselect all"
|
|
title="Cerrar selección"
|
|
>
|
|
<X className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AlertBulkActions;
|