Corrección 1 — Delete de proceso restaurado + Corrección 2 — Patrón userId en repos

This commit is contained in:
2026-05-28 01:13:28 -03:00
parent 1bc80e190f
commit 0a3c60cd09
26 changed files with 1650 additions and 25844 deletions

View File

@@ -10,6 +10,7 @@ import { ScrollArea } from '@/components/ui/scroll-area'
import { Switch } from '@/components/ui/switch'
import { Separator } from '@/components/ui/separator'
import { useProcessStore } from '@/store/process-store'
import { useAuth } from '@/auth/AuthContext'
import { formatCurrency } from '@/lib/format'
import type { Activity } from '@/domain/types'
@@ -19,6 +20,7 @@ interface ActivityPanelProps {
export function ActivityPanel({ selectedElementId }: ActivityPanelProps) {
const { activities, resources, updateActivity, currentProcess } = useProcessStore()
const { user } = useAuth()
const [localActivity, setLocalActivity] = useState<Activity | null>(null)
const [isDirty, setIsDirty] = useState(false)
@@ -42,7 +44,7 @@ export function ActivityPanel({ selectedElementId }: ActivityPanelProps) {
async function handleSave() {
if (!localActivity) return
await updateActivity(localActivity)
await updateActivity(localActivity, user!.id)
setIsDirty(false)
}

View File

@@ -110,12 +110,17 @@ export function BpmnCanvas({
if (!viewer || !xml) return
isImportedRef.current = false
viewer.importXML(xml).then(({ warnings }) => {
// Si el viewer fue destruido y reemplazado (p.ej. React Strict Mode), ignorar
if (viewerRef.current !== viewer) return
if (warnings.length) console.warn('bpmn-js warnings:', warnings)
const canvas = viewer.get('canvas') as any
canvas.zoom('fit-viewport', 'auto')
isImportedRef.current = true
syncAutomationOverlays()
}).catch((err: Error) => console.error('Error cargando BPMN:', err))
}).catch((err: Error) => {
if (viewerRef.current !== viewer) return
console.error('Error cargando BPMN:', err)
})
}, [xml, syncAutomationOverlays])
// ─── Re-sincronizar overlays cuando cambia la lista de automatizables ─────

View File

@@ -6,6 +6,7 @@ import { Slider } from '@/components/ui/slider'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { ScrollArea } from '@/components/ui/scroll-area'
import { useProcessStore } from '@/store/process-store'
import { useAuth } from '@/auth/AuthContext'
import { parseBpmnXml } from '@/domain/bpmn-parser'
import { formatPercent } from '@/lib/format'
import type { GatewayConfig } from '@/domain/types'
@@ -28,6 +29,7 @@ export function isXorSumValid(gw: GatewayConfig): boolean {
export function GatewayPanel({ selectedElementId }: GatewayPanelProps) {
const { gateways, currentProcess, updateGateway, activities } = useProcessStore()
const { user } = useAuth()
const [localGw, setLocalGw] = useState<GatewayConfig | null>(null)
const [isDirty, setIsDirty] = useState(false)
@@ -82,7 +84,7 @@ export function GatewayPanel({ selectedElementId }: GatewayPanelProps) {
async function handleSave() {
if (!localGw) return
await updateGateway(localGw)
await updateGateway(localGw, user!.id)
setIsDirty(false)
}

View File

@@ -9,6 +9,7 @@ import { ScrollArea } from '@/components/ui/scroll-area'
import { Separator } from '@/components/ui/separator'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { useProcessStore } from '@/store/process-store'
import { useAuth } from '@/auth/AuthContext'
import { formatPercent } from '@/lib/format'
const CURRENCIES = [
@@ -24,6 +25,7 @@ const CURRENCIES = [
export function GlobalSettingsPanel() {
const { currentProcess, updateProcess } = useProcessStore()
const { user } = useAuth()
const [localName, setLocalName] = useState('')
const [localClient, setLocalClient] = useState('')
const [localCurrency, setLocalCurrency] = useState('USD')
@@ -57,7 +59,7 @@ export function GlobalSettingsPanel() {
annualFrequency: Math.max(1, localFrequency),
analysisHorizonYears: clampedHorizon,
automationInvestment: Math.max(0, localInvestment),
})
}, user!.id)
setLocalHorizon(clampedHorizon)
setIsDirty(false)
}

View File

@@ -7,6 +7,7 @@ import { Button } from '@/components/ui/button'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { ScrollArea } from '@/components/ui/scroll-area'
import { useProcessStore } from '@/store/process-store'
import { useAuth } from '@/auth/AuthContext'
import { formatCurrency } from '@/lib/format'
import type { Resource, ResourceType } from '@/domain/types'
@@ -36,6 +37,7 @@ const EMPTY_FORM: ResourceFormState = { name: '', type: 'role', costPerHour: ''
export function ResourcesPanel() {
const { currentProcess, resources, addResource, updateResource, deleteResource } = useProcessStore()
const { user } = useAuth()
const [showForm, setShowForm] = useState(false)
const [editingId, setEditingId] = useState<string | null>(null)
const [form, setForm] = useState<ResourceFormState>(EMPTY_FORM)
@@ -65,7 +67,7 @@ export function ResourcesPanel() {
if (editingId) {
const existing = resources.find((r) => r.id === editingId)
if (!existing) return
await updateResource({ ...existing, name: form.name.trim(), type: form.type, costPerHour })
await updateResource({ ...existing, name: form.name.trim(), type: form.type, costPerHour }, user!.id)
} else {
const newResource: Resource = {
id: uuidv4(),
@@ -74,7 +76,7 @@ export function ResourcesPanel() {
type: form.type,
costPerHour,
}
await addResource(newResource)
await addResource(newResource, user!.id)
}
cancelForm()
}
@@ -186,7 +188,7 @@ export function ResourcesPanel() {
variant="ghost"
size="icon"
className="h-6 w-6 text-slate-400 hover:text-destructive"
onClick={() => deleteResource(resource.id)}
onClick={() => deleteResource(resource.id, user!.id)}
>
<Trash2 className="h-3 w-3" />
</Button>

View File

@@ -19,6 +19,7 @@ import { useProcessStore } from '@/store/process-store'
import { useSimulationStore } from '@/store/simulation-store'
import { useSimulate } from '../simulation/useSimulate'
import { useLibraryStore } from '@/store/library-store'
import { useAuth } from '@/auth/AuthContext'
import { AppHeader } from '@/components/AppHeader'
type SelectedCategory = 'activity' | 'gateway' | null
@@ -30,6 +31,7 @@ export function WorkspacePage() {
const { isRunning, resultActual, error: simError, selectActivity, loadLatestForProcess, lastPersistedExecutedAt } = useSimulationStore()
const { simulate } = useSimulate()
const { toast } = useToast()
const { user } = useAuth()
const [sidebarOpen, setSidebarOpen] = useState(true)
const [selectedElementId, setSelectedElementId] = useState<string | null>(null)
@@ -122,12 +124,12 @@ export function WorkspacePage() {
if (field === 'name') {
const trimmed = editValue.trim()
if (trimmed && trimmed !== currentProcess?.name) {
await updateProcess({ name: trimmed })
await updateProcess({ name: trimmed }, user!.id)
}
} else {
const trimmed = editValue.trim()
if (trimmed !== (currentProcess?.clientName ?? '')) {
await updateProcess({ clientName: trimmed })
await updateProcess({ clientName: trimmed }, user!.id)
}
}
setEditingField(null)
@@ -141,14 +143,14 @@ export function WorkspacePage() {
if (!normalized) return
const current = currentProcess?.tags ?? []
if (current.some((t) => t === normalized)) return
updateProcess({ tags: [...current, normalized] })
updateProcess({ tags: [...current, normalized] }, user!.id)
setTagInput('')
setShowTagSuggestions(false)
}
function removeTag(tag: string) {
const current = currentProcess?.tags ?? []
updateProcess({ tags: current.filter((t) => t !== tag) })
updateProcess({ tags: current.filter((t) => t !== tag) }, user!.id)
}
function handleTagKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {