Improve the UI add button
This commit is contained in:
@@ -1,102 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Clock, X, FileText, Trash2 } from 'lucide-react';
|
||||
import { formatTimeAgo } from '../../../hooks/useWizardDraft';
|
||||
|
||||
interface DraftRecoveryPromptProps {
|
||||
isOpen: boolean;
|
||||
lastSaved: Date;
|
||||
onRestore: () => void;
|
||||
onDiscard: () => void;
|
||||
onClose: () => void;
|
||||
wizardName: string;
|
||||
}
|
||||
|
||||
export const DraftRecoveryPrompt: React.FC<DraftRecoveryPromptProps> = ({
|
||||
isOpen,
|
||||
lastSaved,
|
||||
onRestore,
|
||||
onDiscard,
|
||||
onClose,
|
||||
wizardName
|
||||
}) => {
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-[60] flex items-center justify-center">
|
||||
{/* Backdrop */}
|
||||
<div
|
||||
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
|
||||
onClick={onClose}
|
||||
/>
|
||||
|
||||
{/* Modal */}
|
||||
<div className="relative w-full max-w-md bg-[var(--bg-primary)] rounded-xl shadow-2xl overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="px-6 py-4 border-b border-[var(--border-secondary)] bg-gradient-to-r from-[var(--color-warning)]/10 to-[var(--color-warning)]/5">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full bg-[var(--color-warning)]/20 flex items-center justify-center">
|
||||
<FileText className="w-5 h-5 text-[var(--color-warning)]" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold text-[var(--text-primary)]">
|
||||
Borrador Detectado
|
||||
</h2>
|
||||
<p className="text-sm text-[var(--text-secondary)]">
|
||||
{wizardName}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="p-1.5 hover:bg-[var(--bg-secondary)] rounded-lg transition-colors"
|
||||
>
|
||||
<X className="w-4 h-4 text-[var(--text-secondary)]" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="p-6 space-y-4">
|
||||
{/* Info Card */}
|
||||
<div className="p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-secondary)]">
|
||||
<div className="flex items-start gap-3">
|
||||
<Clock className="w-5 h-5 text-[var(--text-tertiary)] mt-0.5 flex-shrink-0" />
|
||||
<div className="flex-1">
|
||||
<p className="text-sm text-[var(--text-primary)] font-medium mb-1">
|
||||
Progreso guardado automáticamente
|
||||
</p>
|
||||
<p className="text-sm text-[var(--text-secondary)]">
|
||||
Guardado {formatTimeAgo(lastSaved)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<p className="text-sm text-[var(--text-secondary)]">
|
||||
Encontramos un borrador de este formulario. ¿Deseas continuar desde donde lo dejaste o empezar de nuevo?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="px-6 py-4 border-t border-[var(--border-secondary)] bg-[var(--bg-secondary)] flex items-center gap-3">
|
||||
<button
|
||||
onClick={onDiscard}
|
||||
className="flex-1 px-4 py-2.5 bg-[var(--bg-primary)] border border-[var(--border-secondary)] text-[var(--text-primary)] rounded-lg hover:bg-[var(--bg-tertiary)] transition-colors flex items-center justify-center gap-2 text-sm font-medium"
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
Descartar y Empezar de Nuevo
|
||||
</button>
|
||||
<button
|
||||
onClick={onRestore}
|
||||
className="flex-1 px-4 py-2.5 bg-[var(--color-primary)] text-white rounded-lg hover:bg-[var(--color-primary-dark)] transition-colors flex items-center justify-center gap-2 text-sm font-medium"
|
||||
>
|
||||
<FileText className="w-4 h-4" />
|
||||
Restaurar Borrador
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export { DraftRecoveryPrompt } from './DraftRecoveryPrompt';
|
||||
@@ -19,6 +19,9 @@ export interface WizardStepProps {
|
||||
currentStepIndex: number;
|
||||
totalSteps: number;
|
||||
goToStep: (index: number) => void;
|
||||
// New architecture: dataRef and onDataChange passed from UnifiedAddWizard
|
||||
dataRef?: React.MutableRefObject<any>;
|
||||
onDataChange?: (data: any) => void;
|
||||
}
|
||||
|
||||
interface WizardModalProps {
|
||||
@@ -29,6 +32,9 @@ interface WizardModalProps {
|
||||
steps: WizardStep[];
|
||||
icon?: React.ReactNode;
|
||||
size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
||||
// New architecture: optional dataRef and onDataChange for wizards that use them
|
||||
dataRef?: React.MutableRefObject<any>;
|
||||
onDataChange?: (data: any) => void;
|
||||
}
|
||||
|
||||
export const WizardModal: React.FC<WizardModalProps> = ({
|
||||
@@ -38,7 +44,9 @@ export const WizardModal: React.FC<WizardModalProps> = ({
|
||||
title,
|
||||
steps,
|
||||
icon,
|
||||
size = 'xl'
|
||||
size = 'xl',
|
||||
dataRef,
|
||||
onDataChange
|
||||
}) => {
|
||||
const [currentStepIndex, setCurrentStepIndex] = useState(0);
|
||||
const [isValidating, setIsValidating] = useState(false);
|
||||
@@ -55,12 +63,36 @@ export const WizardModal: React.FC<WizardModalProps> = ({
|
||||
'2xl': 'max-w-7xl'
|
||||
};
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setCurrentStepIndex(0);
|
||||
onClose();
|
||||
}, [onClose]);
|
||||
|
||||
const handleComplete = useCallback(() => {
|
||||
onComplete();
|
||||
handleClose();
|
||||
}, [onComplete, handleClose]);
|
||||
|
||||
const goToStep = useCallback((index: number) => {
|
||||
if (index >= 0 && index < steps.length) {
|
||||
setCurrentStepIndex(index);
|
||||
}
|
||||
}, [steps.length]);
|
||||
|
||||
const handleBack = useCallback(() => {
|
||||
setCurrentStepIndex(prev => Math.max(prev - 1, 0));
|
||||
}, []);
|
||||
|
||||
const handleNext = useCallback(async () => {
|
||||
// Access current step inside callback to avoid re-creating function on every render
|
||||
const step = steps[currentStepIndex];
|
||||
const lastStep = currentStepIndex === steps.length - 1;
|
||||
|
||||
// Validate current step if validator exists
|
||||
if (currentStep.validate) {
|
||||
if (step.validate) {
|
||||
setIsValidating(true);
|
||||
try {
|
||||
const isValid = await currentStep.validate();
|
||||
const isValid = await step.validate();
|
||||
if (!isValid) {
|
||||
setIsValidating(false);
|
||||
return;
|
||||
@@ -73,32 +105,12 @@ export const WizardModal: React.FC<WizardModalProps> = ({
|
||||
setIsValidating(false);
|
||||
}
|
||||
|
||||
if (isLastStep) {
|
||||
if (lastStep) {
|
||||
handleComplete();
|
||||
} else {
|
||||
setCurrentStepIndex(prev => Math.min(prev + 1, steps.length - 1));
|
||||
}
|
||||
}, [currentStep, isLastStep, steps.length]);
|
||||
|
||||
const handleBack = useCallback(() => {
|
||||
setCurrentStepIndex(prev => Math.max(prev - 1, 0));
|
||||
}, []);
|
||||
|
||||
const handleComplete = useCallback(() => {
|
||||
onComplete();
|
||||
handleClose();
|
||||
}, [onComplete]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setCurrentStepIndex(0);
|
||||
onClose();
|
||||
}, [onClose]);
|
||||
|
||||
const goToStep = useCallback((index: number) => {
|
||||
if (index >= 0 && index < steps.length) {
|
||||
setCurrentStepIndex(index);
|
||||
}
|
||||
}, [steps.length]);
|
||||
}, [steps, currentStepIndex, handleComplete]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
@@ -184,6 +196,8 @@ export const WizardModal: React.FC<WizardModalProps> = ({
|
||||
currentStepIndex={currentStepIndex}
|
||||
totalSteps={steps.length}
|
||||
goToStep={goToStep}
|
||||
dataRef={dataRef}
|
||||
onDataChange={onDataChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user