from pathlib import Path
import re
path = Path('web-v2/src/pages/InspectionVisitEditorF4Page.tsx')
text = path.read_text()
state_before = " const [success, setSuccess] = useState('');\n"
state_after = """ const [success, setSuccess] = useState('');
const [showCancelForm, setShowCancelForm] = useState(false);
const [cancelReason, setCancelReason] = useState('');
"""
if text.count(state_before) != 1:
raise SystemExit('Could not locate success state exactly once')
text = text.replace(state_before, state_after)
lifecycle_pattern = re.compile(
r" const lifecycleAction = async \(action: 'PLAN' \| 'UNPLAN' \| 'CANCEL'\) => \{.*?\n \};\n\n if \(loading\)",
re.S,
)
lifecycle_replacement = """ const lifecycleAction = async (action: 'PLAN' | 'UNPLAN') => {
if (!id) return;
setBusy(true); setError(''); setSuccess('');
try {
let updated: InspectionVisit;
if (action === 'PLAN') {
updated = await planInspectionVisit(id);
setSuccess('Inspección planificada. Ya puede iniciarse desde la APK.');
} else {
updated = await unplanInspectionVisit(id);
setSuccess('La Inspección volvió a borrador para corregir la planificación.');
}
applyVisit(updated);
} catch (requestError) { setError(errorMessage(requestError)); }
finally { setBusy(false); }
};
const cancelCurrentVisit = async (event: FormEvent) => {
event.preventDefault();
if (!id) return;
const reason = cancelReason.trim();
if (reason.length < 10) {
setError('El motivo de cancelación debe tener al menos 10 caracteres.');
return;
}
if (reason.length > 500) {
setError('El motivo de cancelación no puede superar los 500 caracteres.');
return;
}
setBusy(true); setError(''); setSuccess('');
try {
const updated = await cancelInspectionVisit(id, reason);
applyVisit(updated);
setCancelReason('');
setShowCancelForm(false);
setSuccess('Inspección cancelada. El motivo quedó registrado y auditado.');
} catch (requestError) { setError(errorMessage(requestError)); }
finally { setBusy(false); }
};
if (loading)"""
text, count = lifecycle_pattern.subn(lifecycle_replacement, text, count=1)
if count != 1:
raise SystemExit(f'Lifecycle block replacements: {count}')
actions_pattern = re.compile(
r" \{visit && La oficina planifica. El inicio y cierre operativo se realizan desde la APK. Una Inspección no puede cerrarse hasta que todas sus Actas estén selladas.