Improve the frontend 2
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Plus, Settings, ClipboardCheck, Target, Cog } from 'lucide-react';
|
||||
import { AddModal } from '../../ui/AddModal/AddModal';
|
||||
import { Select } from '../../ui/Select';
|
||||
import {
|
||||
QualityCheckType,
|
||||
ProcessStage,
|
||||
type QualityCheckTemplateCreate
|
||||
} from '../../../api/types/qualityTemplates';
|
||||
import { useCurrentTenant } from '../../../stores/tenant.store';
|
||||
import { useAuthUser } from '../../../stores/auth.store';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { recipesService } from '../../../api/services/recipes';
|
||||
import type { RecipeResponse } from '../../../api/types/recipes';
|
||||
@@ -33,7 +35,8 @@ const QUALITY_CHECK_TYPE_OPTIONS = [
|
||||
{ value: QualityCheckType.TEMPERATURE, label: 'Temperatura - Control térmico' },
|
||||
{ value: QualityCheckType.WEIGHT, label: 'Peso - Control de peso' },
|
||||
{ value: QualityCheckType.BOOLEAN, label: 'Sí/No - Verificación binaria' },
|
||||
{ value: QualityCheckType.TIMING, label: 'Tiempo - Control temporal' }
|
||||
{ value: QualityCheckType.TIMING, label: 'Tiempo - Control temporal' },
|
||||
{ value: QualityCheckType.CHECKLIST, label: 'Checklist - Lista de verificación' }
|
||||
];
|
||||
|
||||
const PROCESS_STAGE_OPTIONS = [
|
||||
@@ -72,17 +75,19 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
isLoading: externalLoading = false,
|
||||
initialRecipe
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useTranslation(['production', 'common']);
|
||||
const currentTenant = useCurrentTenant();
|
||||
const user = useAuthUser();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [selectedStages, setSelectedStages] = useState<ProcessStage[]>([]);
|
||||
const [selectedCheckType, setSelectedCheckType] = useState<QualityCheckType | null>(null);
|
||||
|
||||
// Helper function to get translated category label
|
||||
const getCategoryLabel = (category: string | null | undefined): string => {
|
||||
if (!category) return 'Sin categoría';
|
||||
const translationKey = `production.quality.categories.${category}`;
|
||||
const translated = t(translationKey);
|
||||
return translated === translationKey ? category : translated;
|
||||
if (!category) return t('production:quality.categories.no_category', 'Sin categoría');
|
||||
const translationKey = `quality.categories.${category}`;
|
||||
const translated = t(`production:${translationKey}`);
|
||||
return translated === `production:${translationKey}` ? category : translated;
|
||||
};
|
||||
|
||||
// Build category options with translations
|
||||
@@ -109,6 +114,22 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
// Type-specific validation
|
||||
if (formData.check_type === QualityCheckType.VISUAL) {
|
||||
const hasAnyScoring = formData.scoring_excellent_min || formData.scoring_excellent_max ||
|
||||
formData.scoring_good_min || formData.scoring_good_max ||
|
||||
formData.scoring_acceptable_min || formData.scoring_acceptable_max;
|
||||
if (!hasAnyScoring) {
|
||||
throw new Error('Los criterios de puntuación son requeridos para controles visuales');
|
||||
}
|
||||
}
|
||||
|
||||
if ([QualityCheckType.MEASUREMENT, QualityCheckType.TEMPERATURE, QualityCheckType.WEIGHT].includes(formData.check_type)) {
|
||||
if (!formData.unit?.trim()) {
|
||||
throw new Error('La unidad es requerida para controles de medición, temperatura y peso');
|
||||
}
|
||||
}
|
||||
|
||||
// Process applicable stages - convert string back to array
|
||||
const applicableStages = formData.applicable_stages
|
||||
? (typeof formData.applicable_stages === 'string'
|
||||
@@ -116,6 +137,29 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
: formData.applicable_stages)
|
||||
: [];
|
||||
|
||||
// Build scoring criteria for visual checks
|
||||
let scoringCriteria: Record<string, any> | undefined;
|
||||
if (formData.check_type === QualityCheckType.VISUAL) {
|
||||
scoringCriteria = {
|
||||
excellent: {
|
||||
min: formData.scoring_excellent_min ? Number(formData.scoring_excellent_min) : undefined,
|
||||
max: formData.scoring_excellent_max ? Number(formData.scoring_excellent_max) : undefined
|
||||
},
|
||||
good: {
|
||||
min: formData.scoring_good_min ? Number(formData.scoring_good_min) : undefined,
|
||||
max: formData.scoring_good_max ? Number(formData.scoring_good_max) : undefined
|
||||
},
|
||||
acceptable: {
|
||||
min: formData.scoring_acceptable_min ? Number(formData.scoring_acceptable_min) : undefined,
|
||||
max: formData.scoring_acceptable_max ? Number(formData.scoring_acceptable_max) : undefined
|
||||
},
|
||||
fail: {
|
||||
below: formData.scoring_fail_below ? Number(formData.scoring_fail_below) : undefined,
|
||||
above: formData.scoring_fail_above ? Number(formData.scoring_fail_above) : undefined
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const templateData: QualityCheckTemplateCreate = {
|
||||
name: formData.name,
|
||||
template_code: formData.template_code || '',
|
||||
@@ -128,13 +172,15 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
is_critical: formData.is_critical || false,
|
||||
weight: Number(formData.weight) || 1.0,
|
||||
applicable_stages: applicableStages.length > 0 ? applicableStages as ProcessStage[] : undefined,
|
||||
created_by: currentTenant?.id || '',
|
||||
created_by: user?.id || '',
|
||||
// Measurement fields
|
||||
min_value: formData.min_value ? Number(formData.min_value) : undefined,
|
||||
max_value: formData.max_value ? Number(formData.max_value) : undefined,
|
||||
target_value: formData.target_value ? Number(formData.target_value) : undefined,
|
||||
unit: formData.unit || undefined,
|
||||
tolerance_percentage: formData.tolerance_percentage ? Number(formData.tolerance_percentage) : undefined
|
||||
unit: formData.unit && formData.unit.trim() ? formData.unit.trim() : undefined,
|
||||
tolerance_percentage: formData.tolerance_percentage ? Number(formData.tolerance_percentage) : undefined,
|
||||
// Scoring criteria (for visual checks)
|
||||
scoring_criteria: scoringCriteria
|
||||
};
|
||||
|
||||
// Handle recipe associations if provided
|
||||
@@ -170,15 +216,16 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
isHighlight: true
|
||||
};
|
||||
|
||||
// Determine if measurement fields should be shown based on check type
|
||||
const showMeasurementFields = (checkType: string) => [
|
||||
QualityCheckType.MEASUREMENT,
|
||||
QualityCheckType.TEMPERATURE,
|
||||
QualityCheckType.WEIGHT
|
||||
].includes(checkType as QualityCheckType);
|
||||
// Handler for field changes to track check_type selection
|
||||
const handleFieldChange = (fieldName: string, value: any) => {
|
||||
if (fieldName === 'check_type') {
|
||||
setSelectedCheckType(value as QualityCheckType);
|
||||
}
|
||||
};
|
||||
|
||||
const sections = [
|
||||
{
|
||||
// Function to build sections dynamically based on selected check type
|
||||
const getSections = () => {
|
||||
const basicInfoSection = {
|
||||
title: 'Información Básica',
|
||||
icon: ClipboardCheck,
|
||||
fields: [
|
||||
@@ -204,8 +251,9 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
name: 'check_type',
|
||||
type: 'select' as const,
|
||||
required: true,
|
||||
defaultValue: QualityCheckType.VISUAL,
|
||||
options: QUALITY_CHECK_TYPE_OPTIONS
|
||||
placeholder: 'Selecciona un tipo de control...',
|
||||
options: QUALITY_CHECK_TYPE_OPTIONS,
|
||||
helpText: 'Los campos de configuración cambiarán según el tipo seleccionado'
|
||||
},
|
||||
{
|
||||
label: 'Categoría',
|
||||
@@ -230,8 +278,9 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
helpText: 'Pasos específicos que debe seguir el operario'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
};
|
||||
|
||||
const measurementSection = {
|
||||
title: 'Configuración de Medición',
|
||||
icon: Target,
|
||||
fields: [
|
||||
@@ -257,11 +306,12 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
helpText: 'Valor ideal que se busca alcanzar'
|
||||
},
|
||||
{
|
||||
label: 'Unidad',
|
||||
label: 'Unidad *',
|
||||
name: 'unit',
|
||||
type: 'text' as const,
|
||||
required: true,
|
||||
placeholder: '°C / g / cm',
|
||||
helpText: 'Unidad de medida (ej: °C para temperatura)'
|
||||
helpText: 'REQUERIDO para este tipo de control (ej: °C, g, cm)'
|
||||
},
|
||||
{
|
||||
label: 'Tolerancia (%)',
|
||||
@@ -271,22 +321,93 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
helpText: 'Porcentaje de tolerancia permitido'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
};
|
||||
|
||||
const scoringSection = {
|
||||
title: 'Criterios de Puntuación (Controles Visuales)',
|
||||
icon: Target,
|
||||
fields: [
|
||||
{
|
||||
label: 'Excelente - Mínimo',
|
||||
name: 'scoring_excellent_min',
|
||||
type: 'number' as const,
|
||||
placeholder: '9.0',
|
||||
helpText: 'Puntuación mínima para nivel excelente'
|
||||
},
|
||||
{
|
||||
label: 'Excelente - Máximo',
|
||||
name: 'scoring_excellent_max',
|
||||
type: 'number' as const,
|
||||
placeholder: '10.0',
|
||||
helpText: 'Puntuación máxima para nivel excelente'
|
||||
},
|
||||
{
|
||||
label: 'Bueno - Mínimo',
|
||||
name: 'scoring_good_min',
|
||||
type: 'number' as const,
|
||||
placeholder: '7.0',
|
||||
helpText: 'Puntuación mínima para nivel bueno'
|
||||
},
|
||||
{
|
||||
label: 'Bueno - Máximo',
|
||||
name: 'scoring_good_max',
|
||||
type: 'number' as const,
|
||||
placeholder: '8.9',
|
||||
helpText: 'Puntuación máxima para nivel bueno'
|
||||
},
|
||||
{
|
||||
label: 'Aceptable - Mínimo',
|
||||
name: 'scoring_acceptable_min',
|
||||
type: 'number' as const,
|
||||
placeholder: '5.0',
|
||||
helpText: 'Puntuación mínima para nivel aceptable'
|
||||
},
|
||||
{
|
||||
label: 'Aceptable - Máximo',
|
||||
name: 'scoring_acceptable_max',
|
||||
type: 'number' as const,
|
||||
placeholder: '6.9',
|
||||
helpText: 'Puntuación máxima para nivel aceptable'
|
||||
},
|
||||
{
|
||||
label: 'Fallo - Por Debajo',
|
||||
name: 'scoring_fail_below',
|
||||
type: 'number' as const,
|
||||
placeholder: '5.0',
|
||||
helpText: 'Valor por debajo del cual se considera fallo'
|
||||
},
|
||||
{
|
||||
label: 'Fallo - Por Encima',
|
||||
name: 'scoring_fail_above',
|
||||
type: 'number' as const,
|
||||
placeholder: '10.0',
|
||||
helpText: 'Valor por encima del cual se considera fallo (opcional)'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const stagesSection = {
|
||||
title: 'Etapas del Proceso',
|
||||
icon: Settings,
|
||||
fields: [
|
||||
{
|
||||
label: 'Etapas Aplicables',
|
||||
name: 'applicable_stages',
|
||||
type: 'text' as const,
|
||||
placeholder: 'Se seleccionarán las etapas donde aplicar',
|
||||
helpText: 'Las etapas se configuran mediante la selección múltiple',
|
||||
type: 'component' as const,
|
||||
component: Select,
|
||||
componentProps: {
|
||||
options: PROCESS_STAGE_OPTIONS,
|
||||
multiple: true,
|
||||
placeholder: 'Seleccionar etapas del proceso',
|
||||
searchable: true
|
||||
},
|
||||
helpText: 'Selecciona las etapas donde se aplicará este control de calidad',
|
||||
span: 2 as const
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
};
|
||||
|
||||
const recipesSection = {
|
||||
title: 'Asociación con Recetas',
|
||||
icon: Plus,
|
||||
fields: [
|
||||
@@ -300,8 +421,9 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
span: 2 as const
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
};
|
||||
|
||||
const advancedSection = {
|
||||
title: 'Configuración Avanzada',
|
||||
icon: Cog,
|
||||
fields: [
|
||||
@@ -350,8 +472,28 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
helpText: 'Si es crítico, bloquea la producción si falla'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Build sections array based on selected check type
|
||||
const sections = [basicInfoSection];
|
||||
|
||||
// Add type-specific configuration sections
|
||||
if (selectedCheckType === QualityCheckType.VISUAL) {
|
||||
sections.push(scoringSection);
|
||||
} else if ([QualityCheckType.MEASUREMENT, QualityCheckType.TEMPERATURE, QualityCheckType.WEIGHT].includes(selectedCheckType as QualityCheckType)) {
|
||||
sections.push(measurementSection);
|
||||
}
|
||||
];
|
||||
// For BOOLEAN, TIMING, CHECKLIST - no special configuration sections yet
|
||||
|
||||
// Always add these sections
|
||||
sections.push(stagesSection);
|
||||
sections.push(recipesSection);
|
||||
sections.push(advancedSection);
|
||||
|
||||
return sections;
|
||||
};
|
||||
|
||||
const sections = getSections();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -365,15 +507,8 @@ export const CreateQualityTemplateModal: React.FC<CreateQualityTemplateModalProp
|
||||
size="xl"
|
||||
loading={loading || externalLoading}
|
||||
onSave={handleSave}
|
||||
onFieldChange={handleFieldChange}
|
||||
/>
|
||||
|
||||
{/* TODO: Stage selection would need a custom component or enhanced AddModal field types */}
|
||||
{isOpen && (
|
||||
<div style={{ display: 'none' }}>
|
||||
<p>Nota: La selección de etapas del proceso requiere un componente personalizado no implementado en esta versión simplificada.</p>
|
||||
<p>Las etapas actualmente se manejan mediante un campo de texto que debería ser reemplazado por un selector múltiple.</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import React from 'react';
|
||||
import { BaseDeleteModal } from '../../ui';
|
||||
import { QualityCheckTemplate } from '../../../api/types/qualityTemplates';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface DeleteQualityTemplateModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
template: QualityCheckTemplate | null;
|
||||
onSoftDelete: (templateId: string) => Promise<void>;
|
||||
onHardDelete: (templateId: string) => Promise<void>;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal for quality template deletion with soft/hard delete options
|
||||
* - Soft delete: Mark as inactive (reversible)
|
||||
* - Hard delete: Permanent deletion with dependency checking
|
||||
*/
|
||||
export const DeleteQualityTemplateModal: React.FC<DeleteQualityTemplateModalProps> = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
template,
|
||||
onSoftDelete,
|
||||
onHardDelete,
|
||||
isLoading = false,
|
||||
}) => {
|
||||
const { t } = useTranslation(['production', 'common']);
|
||||
|
||||
if (!template) return null;
|
||||
|
||||
return (
|
||||
<BaseDeleteModal<QualityCheckTemplate>
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
entity={template}
|
||||
onSoftDelete={onSoftDelete}
|
||||
onHardDelete={onHardDelete}
|
||||
isLoading={isLoading}
|
||||
title={t('production:quality.delete.title', 'Eliminar Plantilla de Calidad')}
|
||||
getEntityId={(temp) => temp.id}
|
||||
getEntityDisplay={(temp) => ({
|
||||
primaryText: temp.name,
|
||||
secondaryText: `${t('production:quality.delete.template_code', 'Código')}: ${temp.template_code || 'N/A'} • ${t('production:quality.delete.check_type', 'Tipo')}: ${temp.check_type}`,
|
||||
})}
|
||||
softDeleteOption={{
|
||||
title: t('production:quality.delete.soft_delete', 'Desactivar (Recomendado)'),
|
||||
description: t('production:quality.delete.soft_explanation', 'La plantilla se marca como inactiva pero conserva todo su historial. Ideal para plantillas temporalmente fuera de uso.'),
|
||||
benefits: t('production:quality.delete.soft_benefits', '✓ Reversible • ✓ Conserva historial • ✓ Conserva datos'),
|
||||
}}
|
||||
hardDeleteOption={{
|
||||
title: t('production:quality.delete.hard_delete', 'Eliminar Permanentemente'),
|
||||
description: t('production:quality.delete.hard_explanation', 'Elimina completamente la plantilla y todos sus datos asociados. Use solo para datos erróneos o pruebas.'),
|
||||
benefits: t('production:quality.delete.hard_risks', '⚠️ No reversible • ⚠️ Elimina historial • ⚠️ Elimina todos los datos'),
|
||||
enabled: true,
|
||||
}}
|
||||
softDeleteWarning={{
|
||||
title: t('production:quality.delete.soft_info_title', 'ℹ️ Esta acción desactivará la plantilla:'),
|
||||
items: [
|
||||
t('production:quality.delete.soft_info_1', 'La plantilla se marcará como inactiva'),
|
||||
t('production:quality.delete.soft_info_2', 'No aparecerá en listas activas'),
|
||||
t('production:quality.delete.soft_info_3', 'Se conserva todo el historial y datos'),
|
||||
t('production:quality.delete.soft_info_4', 'Se puede reactivar posteriormente'),
|
||||
],
|
||||
}}
|
||||
hardDeleteWarning={{
|
||||
title: t('production:quality.delete.hard_warning_title', '⚠️ Esta acción eliminará permanentemente:'),
|
||||
items: [
|
||||
t('production:quality.delete.hard_warning_1', 'La plantilla y toda su información'),
|
||||
t('production:quality.delete.hard_warning_2', 'Todas las configuraciones de calidad asociadas'),
|
||||
t('production:quality.delete.hard_warning_3', 'Todo el historial de controles de calidad'),
|
||||
t('production:quality.delete.hard_warning_4', 'Las alertas y métricas relacionadas'),
|
||||
],
|
||||
footer: t('production:quality.delete.irreversible', 'Esta acción NO se puede deshacer'),
|
||||
}}
|
||||
requireConfirmText={true}
|
||||
confirmText="ELIMINAR"
|
||||
showSuccessScreen={true}
|
||||
successTitle={t('production:quality.delete.success_soft_title', 'Plantilla Desactivada')}
|
||||
getSuccessMessage={(temp, mode) =>
|
||||
mode === 'hard'
|
||||
? t('production:quality.delete.template_deleted', { name: temp.name })
|
||||
: t('production:quality.delete.template_deactivated', { name: temp.name })
|
||||
}
|
||||
autoCloseDelay={1500}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteQualityTemplateModal;
|
||||
@@ -3,8 +3,6 @@ import {
|
||||
Plus,
|
||||
Search,
|
||||
Filter,
|
||||
Edit,
|
||||
Copy,
|
||||
Trash2,
|
||||
Eye,
|
||||
CheckCircle,
|
||||
@@ -32,8 +30,7 @@ import {
|
||||
useQualityTemplates,
|
||||
useCreateQualityTemplate,
|
||||
useUpdateQualityTemplate,
|
||||
useDeleteQualityTemplate,
|
||||
useDuplicateQualityTemplate
|
||||
useDeleteQualityTemplate
|
||||
} from '../../../api/hooks/qualityTemplates';
|
||||
import {
|
||||
QualityCheckType,
|
||||
@@ -45,6 +42,7 @@ import {
|
||||
import { CreateQualityTemplateModal } from './CreateQualityTemplateModal';
|
||||
import { EditQualityTemplateModal } from './EditQualityTemplateModal';
|
||||
import { ViewQualityTemplateModal } from './ViewQualityTemplateModal';
|
||||
import { DeleteQualityTemplateModal } from './DeleteQualityTemplateModal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface QualityTemplateManagerProps {
|
||||
@@ -114,10 +112,12 @@ export const QualityTemplateManager: React.FC<QualityTemplateManagerProps> = ({
|
||||
const [selectedCheckType, setSelectedCheckType] = useState<QualityCheckType | ''>('');
|
||||
const [selectedStage, setSelectedStage] = useState<ProcessStage | ''>('');
|
||||
const [showActiveOnly, setShowActiveOnly] = useState(true);
|
||||
const [showCreateModal, setShowCreateModal] = useState(false);
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
const [showViewModal, setShowViewModal] = useState(false);
|
||||
const [showCreateModal, setShowCreateModal] = useState<boolean>(false);
|
||||
const [showEditModal, setShowEditModal] = useState<boolean>(false);
|
||||
const [showViewModal, setShowViewModal] = useState<boolean>(false);
|
||||
const [showDeleteModal, setShowDeleteModal] = useState<boolean>(false);
|
||||
const [selectedTemplate, setSelectedTemplate] = useState<QualityCheckTemplate | null>(null);
|
||||
const [templateToDelete, setTemplateToDelete] = useState<QualityCheckTemplate | null>(null);
|
||||
|
||||
const currentTenant = useCurrentTenant();
|
||||
const tenantId = currentTenant?.id || '';
|
||||
@@ -146,7 +146,6 @@ export const QualityTemplateManager: React.FC<QualityTemplateManagerProps> = ({
|
||||
const createTemplateMutation = useCreateQualityTemplate(tenantId);
|
||||
const updateTemplateMutation = useUpdateQualityTemplate(tenantId);
|
||||
const deleteTemplateMutation = useDeleteQualityTemplate(tenantId);
|
||||
const duplicateTemplateMutation = useDuplicateQualityTemplate(tenantId);
|
||||
|
||||
// Filtered templates
|
||||
const filteredTemplates = useMemo(() => {
|
||||
@@ -214,25 +213,25 @@ export const QualityTemplateManager: React.FC<QualityTemplateManagerProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteTemplate = async (templateId: string) => {
|
||||
if (!confirm('¿Estás seguro de que quieres eliminar esta plantilla?')) return;
|
||||
|
||||
const handleSoftDelete = async (templateId: string) => {
|
||||
try {
|
||||
await deleteTemplateMutation.mutateAsync(templateId);
|
||||
} catch (error) {
|
||||
console.error('Error deleting template:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDuplicateTemplate = async (templateId: string) => {
|
||||
const handleHardDelete = async (templateId: string) => {
|
||||
try {
|
||||
await duplicateTemplateMutation.mutateAsync(templateId);
|
||||
await deleteTemplateMutation.mutateAsync(templateId);
|
||||
} catch (error) {
|
||||
console.error('Error duplicating template:', error);
|
||||
console.error('Error deleting template:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const getTemplateStatusConfig = (template: QualityCheckTemplate) => {
|
||||
const getTemplateStatusConfig = (template: QualityCheckTemplate) => {
|
||||
const typeConfigs = QUALITY_CHECK_TYPE_CONFIG(t);
|
||||
const typeConfig = typeConfigs[template.check_type];
|
||||
|
||||
@@ -241,7 +240,7 @@ export const QualityTemplateManager: React.FC<QualityTemplateManagerProps> = ({
|
||||
text: typeConfig.label,
|
||||
icon: typeConfig.icon
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
@@ -406,27 +405,15 @@ export const QualityTemplateManager: React.FC<QualityTemplateManagerProps> = ({
|
||||
setShowViewModal(true);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Editar',
|
||||
icon: Edit,
|
||||
priority: 'secondary',
|
||||
onClick: () => {
|
||||
setSelectedTemplate(template);
|
||||
setShowEditModal(true);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Duplicar',
|
||||
icon: Copy,
|
||||
priority: 'secondary',
|
||||
onClick: () => handleDuplicateTemplate(template.id)
|
||||
},
|
||||
{
|
||||
label: 'Eliminar',
|
||||
icon: Trash2,
|
||||
destructive: true,
|
||||
priority: 'secondary',
|
||||
onClick: () => handleDeleteTemplate(template.id)
|
||||
onClick: () => {
|
||||
setTemplateToDelete(template);
|
||||
setShowDeleteModal(true);
|
||||
}
|
||||
}
|
||||
]}
|
||||
/>
|
||||
@@ -491,6 +478,21 @@ export const QualityTemplateManager: React.FC<QualityTemplateManagerProps> = ({
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Delete Template Modal */}
|
||||
{templateToDelete && (
|
||||
<DeleteQualityTemplateModal
|
||||
isOpen={showDeleteModal}
|
||||
onClose={() => {
|
||||
setShowDeleteModal(false);
|
||||
setTemplateToDelete(null);
|
||||
}}
|
||||
template={templateToDelete}
|
||||
onSoftDelete={handleSoftDelete}
|
||||
onHardDelete={handleHardDelete}
|
||||
isLoading={deleteTemplateMutation.isPending}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user