Imporve onboarding UI

This commit is contained in:
Urtzi Alfaro
2025-12-19 13:10:24 +01:00
parent 71ee2976a2
commit bfa5ff0637
39 changed files with 1016 additions and 483 deletions

View File

@@ -1,13 +1,12 @@
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import type { SetupStepProps } from '../SetupWizard';
import { SetupStepProps } from '../types';
import { useQualityTemplates, useCreateQualityTemplate } from '../../../../api/hooks/qualityTemplates';
import { useCurrentTenant } from '../../../../stores/tenant.store';
import { useAuthUser } from '../../../../stores/auth.store';
import { QualityCheckType, ProcessStage } from '../../../../api/types/qualityTemplates';
import type { QualityCheckTemplateCreate } from '../../../../api/types/qualityTemplates';
import { QualityCheckType, ProcessStage, QualityCheckTemplate, QualityCheckTemplateCreate } from '../../../../api/types/qualityTemplates';
export const QualitySetupStep: React.FC<SetupStepProps> = ({ onUpdate, onComplete, canContinue }) => {
export const QualitySetupStep: React.FC<SetupStepProps> = ({ onUpdate, onComplete, onPrevious, canContinue }) => {
const { t } = useTranslation();
// Get tenant ID and user
@@ -75,14 +74,14 @@ export const QualitySetupStep: React.FC<SetupStepProps> = ({ onUpdate, onComplet
try {
const templateData: QualityCheckTemplateCreate = {
name: formData.name,
check_type: formData.check_type,
check_type: (formData.check_type as QualityCheckType) || QualityCheckType.VISUAL,
description: formData.description || undefined,
applicable_stages: formData.applicable_stages,
is_required: formData.is_required,
is_critical: formData.is_critical,
is_active: true,
weight: formData.is_critical ? 10 : 5,
created_by: userId,
created_by: userId || '',
};
await createTemplateMutation.mutateAsync(templateData);
@@ -165,7 +164,7 @@ export const QualitySetupStep: React.FC<SetupStepProps> = ({ onUpdate, onComplet
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span className="text-sm font-medium text-[var(--text-primary)]">
{t('setup_wizard:quality.added_count', { count: templates.length, defaultValue: '{{count}} quality check added' })}
{t('setup_wizard:quality.added_count', { count: templates.length, defaultValue: '{count} quality check added' })}
</span>
</div>
{templates.length >= 2 ? (
@@ -252,7 +251,7 @@ export const QualitySetupStep: React.FC<SetupStepProps> = ({ onUpdate, onComplet
type="text"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className={`w-full px-3 py-2 bg-[var(--bg-primary)] border ${errors.name ? 'border-[var(--color-error)]' : 'border-[var(--border-secondary)]'} rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] text-[var(--text-primary)]`}
className={`w - full px - 3 py - 2 bg - [var(--bg - primary)] border ${errors.name ? 'border-[var(--color-error)]' : 'border-[var(--border-secondary)]'} rounded - lg focus: outline - none focus: ring - 2 focus: ring - [var(--color - primary)]text - [var(--text - primary)]`}
placeholder={t('setup_wizard:quality.placeholders.name', 'e.g., Crust color check, Dough temperature')}
/>
{errors.name && <p className="mt-1 text-xs text-[var(--color-error)]">{errors.name}</p>}
@@ -274,11 +273,10 @@ export const QualitySetupStep: React.FC<SetupStepProps> = ({ onUpdate, onComplet
console.log('Check type clicked:', option.value, 'current:', formData.check_type);
setFormData(prev => ({ ...prev, check_type: option.value }));
}}
className={`p-3 text-left border-2 rounded-lg transition-all cursor-pointer ${
formData.check_type === option.value
? 'border-[var(--color-primary)] bg-[var(--color-primary)]/20 shadow-lg ring-2 ring-[var(--color-primary)]/30'
: 'border-[var(--border-secondary)] hover:border-[var(--color-primary)]/50 hover:bg-[var(--bg-secondary)]'
}`}
className={`p - 3 text - left border - 2 rounded - lg transition - all cursor - pointer ${formData.check_type === option.value
? 'border-[var(--color-primary)] bg-[var(--color-primary)]/20 shadow-lg ring-2 ring-[var(--color-primary)]/30'
: 'border-[var(--border-secondary)] hover:border-[var(--color-primary)]/50 hover:bg-[var(--bg-secondary)]'
} `}
>
<div className="text-lg mb-1">{option.icon}</div>
<div className="text-xs font-medium text-[var(--text-primary)]">{option.label}</div>
@@ -325,11 +323,10 @@ export const QualitySetupStep: React.FC<SetupStepProps> = ({ onUpdate, onComplet
: [...prev.applicable_stages, option.value]
}));
}}
className={`p-2 text-sm text-left border-2 rounded-lg transition-all cursor-pointer ${
formData.applicable_stages.includes(option.value)
? 'border-[var(--color-primary)] bg-[var(--color-primary)]/20 text-[var(--color-primary)] font-semibold shadow-md ring-1 ring-[var(--color-primary)]/30'
: 'border-[var(--border-secondary)] text-[var(--text-secondary)] hover:border-[var(--color-primary)]/50 hover:bg-[var(--bg-secondary)]'
}`}
className={`p - 2 text - sm text - left border - 2 rounded - lg transition - all cursor - pointer ${formData.applicable_stages.includes(option.value)
? 'border-[var(--color-primary)] bg-[var(--color-primary)]/20 text-[var(--color-primary)] font-semibold shadow-md ring-1 ring-[var(--color-primary)]/30'
: 'border-[var(--border-secondary)] text-[var(--text-secondary)] hover:border-[var(--color-primary)]/50 hover:bg-[var(--bg-secondary)]'
} `}
>
{option.label}
</button>
@@ -429,16 +426,29 @@ export const QualitySetupStep: React.FC<SetupStepProps> = ({ onUpdate, onComplet
</div>
)}
{/* Continue button - only shown when used in onboarding context */}
{onComplete && (
<div className="flex justify-end mt-6 pt-6 border-t border-[var(--border-secondary)]">
<button
onClick={() => onComplete()}
disabled={canContinue === false}
className="px-6 py-3 bg-[var(--color-primary)] text-white rounded-lg hover:bg-[var(--color-primary-dark)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors font-medium"
>
{t('setup_wizard:navigation.continue', 'Continue →')}
</button>
{/* Navigation buttons */}
{!isAdding && onComplete && (
<div className="flex items-center justify-between gap-4 pt-6 mt-6 border-t border-[var(--border-secondary)]">
<div className="flex gap-2">
<button
type="button"
onClick={onPrevious}
className="px-4 py-2 text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-secondary)] rounded-lg transition-colors font-medium"
>
{t('common:previous', 'Anterior')}
</button>
</div>
<div className="flex items-center gap-3">
<button
type="button"
onClick={() => onComplete()}
disabled={canContinue === false}
className="px-6 py-2.5 bg-[var(--color-primary)] text-white rounded-lg hover:bg-[var(--color-primary-dark)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors font-medium flex items-center gap-2"
>
{t('common:next', 'Continuar →')}
</button>
</div>
</div>
)}
</div>