Corrección 1 — Delete de proceso restaurado + Corrección 2 — Patrón userId en repos
This commit is contained in:
@@ -3,8 +3,10 @@ import { useNavigate } from '@tanstack/react-router'
|
||||
import {
|
||||
Upload, Search, Plus, Building2, FolderX, GitBranch,
|
||||
Clock, TrendingUp, BarChart2, FileX2, X, Settings,
|
||||
MoreVertical, Trash2,
|
||||
} from 'lucide-react'
|
||||
import { useLibraryStore } from '@/store/library-store'
|
||||
import { useAuth } from '@/auth/AuthContext'
|
||||
import { formatCurrency } from '@/lib/format'
|
||||
import type { Process, ProcessGroup, Simulation } from '@/domain/types'
|
||||
import { AppHeader } from '@/components/AppHeader'
|
||||
@@ -78,18 +80,31 @@ function KpiBadge({ process, simulation }: { process: Process; simulation: Simul
|
||||
|
||||
// ─── Process Card ─────────────────────────────────────────────────────────────
|
||||
|
||||
function ProcessCard({ process, simulation, showGroupChip, groupName }: {
|
||||
function ProcessCard({ process, simulation, showGroupChip, groupName, onDelete }: {
|
||||
process: Process
|
||||
simulation: Simulation | null | undefined
|
||||
showGroupChip?: boolean
|
||||
groupName?: string
|
||||
onDelete?: () => void
|
||||
}) {
|
||||
const navigate = useNavigate()
|
||||
const [menuState, setMenuState] = useState<null | 'menu' | 'confirm'>(null)
|
||||
|
||||
// Cierra el menú al hacer click fuera de él
|
||||
useEffect(() => {
|
||||
if (!menuState) return
|
||||
function handleDocClick() { setMenuState(null) }
|
||||
document.addEventListener('click', handleDocClick)
|
||||
return () => document.removeEventListener('click', handleDocClick)
|
||||
}, [menuState])
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex items-center gap-3 px-4 py-3 rounded-xl border border-border bg-card hover:border-border/80 hover:shadow-sm transition-all cursor-pointer"
|
||||
onClick={() => navigate({ to: '/workspace/$processId', params: { processId: process.id } })}
|
||||
className="flex items-center gap-3 px-4 py-3 rounded-xl border border-border bg-card hover:border-border/80 hover:shadow-sm transition-all cursor-pointer group"
|
||||
onClick={() => {
|
||||
if (menuState) { setMenuState(null); return }
|
||||
navigate({ to: '/workspace/$processId', params: { processId: process.id } })
|
||||
}}
|
||||
>
|
||||
{/* Ícono */}
|
||||
<div className="flex-shrink-0 w-9 h-9 rounded-lg flex items-center justify-center"
|
||||
@@ -125,6 +140,60 @@ function ProcessCard({ process, simulation, showGroupChip, groupName }: {
|
||||
<div className="flex-shrink-0 min-w-[90px]">
|
||||
<KpiBadge process={process} simulation={simulation} />
|
||||
</div>
|
||||
|
||||
{/* Menú de opciones (⋮) — en el flujo flex, a la derecha del KPI */}
|
||||
{onDelete && (
|
||||
<div
|
||||
className="relative flex-shrink-0"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<button
|
||||
className={`p-1 rounded hover:bg-secondary text-muted-foreground hover:text-foreground transition-all ${menuState === null ? 'opacity-0 group-hover:opacity-100' : 'opacity-100'}`}
|
||||
onClick={(e) => { e.stopPropagation(); setMenuState(menuState === 'menu' ? null : 'menu') }}
|
||||
title="Opciones"
|
||||
>
|
||||
<MoreVertical className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
{menuState === 'menu' && (
|
||||
<div
|
||||
className="absolute right-0 top-7 z-20 bg-card border border-border rounded-lg shadow-lg py-1 min-w-[130px]"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<button
|
||||
className="flex items-center gap-2 w-full px-3 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 transition-colors"
|
||||
onClick={(e) => { e.stopPropagation(); setMenuState('confirm') }}
|
||||
>
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
Eliminar
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{menuState === 'confirm' && (
|
||||
<div
|
||||
className="absolute right-0 top-6 z-20 bg-card border border-border rounded-lg shadow-lg p-3 min-w-[170px]"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<p className="text-[12px] font-medium mb-2 text-foreground">¿Eliminar proceso?</p>
|
||||
<p className="text-[11px] text-muted-foreground mb-3">Esta acción no se puede deshacer.</p>
|
||||
<div className="flex gap-1.5">
|
||||
<button
|
||||
className="flex-1 text-[11px] px-2 py-1 rounded font-medium text-white transition-opacity hover:opacity-90"
|
||||
style={{ background: '#ef4444' }}
|
||||
onClick={(e) => { e.stopPropagation(); onDelete(); setMenuState(null) }}
|
||||
>
|
||||
Eliminar
|
||||
</button>
|
||||
<button
|
||||
className="flex-1 text-[11px] px-2 py-1 rounded border border-border text-muted-foreground hover:bg-secondary transition-colors"
|
||||
onClick={(e) => { e.stopPropagation(); setMenuState(null) }}
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -244,6 +313,7 @@ function HomeView({
|
||||
onImport: (groupId?: string) => void
|
||||
}) {
|
||||
const { groups, processes, settings, createGroup } = useLibraryStore()
|
||||
const { user } = useAuth()
|
||||
const [search, setSearch] = useState('')
|
||||
const [activeTags, setActiveTags] = useState<string[]>([])
|
||||
|
||||
@@ -402,7 +472,7 @@ function HomeView({
|
||||
})}
|
||||
<NewGroupCard
|
||||
label={settings.groupLabel}
|
||||
onCreate={(name) => createGroup(name)}
|
||||
onCreate={(name) => createGroup(name, user!.id)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -437,7 +507,7 @@ function ProcessCardWithSim({ process, showGroupChip, groupName }: {
|
||||
showGroupChip?: boolean
|
||||
groupName?: string
|
||||
}) {
|
||||
const { getLatestSimulation } = useLibraryStore()
|
||||
const { getLatestSimulation, deleteProcess } = useLibraryStore()
|
||||
const [simulation, setSimulation] = useState<Simulation | null | undefined>(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -448,7 +518,15 @@ function ProcessCardWithSim({ process, showGroupChip, groupName }: {
|
||||
return () => { cancelled = true }
|
||||
}, [process.id, getLatestSimulation])
|
||||
|
||||
return <ProcessCard process={process} simulation={simulation} showGroupChip={showGroupChip} groupName={groupName} />
|
||||
return (
|
||||
<ProcessCard
|
||||
process={process}
|
||||
simulation={simulation}
|
||||
showGroupChip={showGroupChip}
|
||||
groupName={groupName}
|
||||
onDelete={() => deleteProcess(process.id)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
// ─── Group View ───────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user