feat: actualizar terminología de categoría a clasificación en toda la aplicación
This commit is contained in:
parent
fe79f843f6
commit
b7154af381
@ -71,7 +71,7 @@ const handleAddToCart = () => {
|
|||||||
<div class="flex items-center gap-1 mb-3">
|
<div class="flex items-center gap-1 mb-3">
|
||||||
<GoogleIcon name="category" class="text-sm text-gray-400" />
|
<GoogleIcon name="category" class="text-sm text-gray-400" />
|
||||||
<span class="text-xs text-gray-500 dark:text-gray-400">
|
<span class="text-xs text-gray-500 dark:text-gray-400">
|
||||||
{{ product.category?.name || 'Sin categoría' }}
|
{{ product.category?.name || 'Sin clasificación' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -502,7 +502,7 @@ export default {
|
|||||||
},
|
},
|
||||||
sku: 'SKU / Código',
|
sku: 'SKU / Código',
|
||||||
product: 'Producto',
|
product: 'Producto',
|
||||||
category: 'Categoría',
|
category: 'Clasificación',
|
||||||
stock: 'Stock',
|
stock: 'Stock',
|
||||||
state: 'Estado',
|
state: 'Estado',
|
||||||
cost: 'Costo',
|
cost: 'Costo',
|
||||||
|
|||||||
@ -24,12 +24,12 @@ const form = useForm({
|
|||||||
const createCategory = () => {
|
const createCategory = () => {
|
||||||
form.post(apiURL('categorias'), {
|
form.post(apiURL('categorias'), {
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
Notify.success('Categoría creada exitosamente');
|
Notify.success('Clasificación creada exitosamente');
|
||||||
emit('created', data?.model);
|
emit('created', data?.model);
|
||||||
closeModal();
|
closeModal();
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Notify.error('Error al crear la categoría');
|
Notify.error('Error al crear la clasificación');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -46,7 +46,7 @@ const closeModal = () => {
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex items-center justify-between mb-6">
|
<div class="flex items-center justify-between mb-6">
|
||||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
||||||
Crear Categoría
|
Crear Clasificación
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button
|
||||||
@click="closeModal"
|
@click="closeModal"
|
||||||
@ -68,7 +68,7 @@ const closeModal = () => {
|
|||||||
<FormInput
|
<FormInput
|
||||||
v-model="form.name"
|
v-model="form.name"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Nombre de la categoría"
|
placeholder="Nombre de la clasificación"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<FormError :message="form.errors?.name" />
|
<FormError :message="form.errors?.name" />
|
||||||
@ -83,7 +83,7 @@ const closeModal = () => {
|
|||||||
v-model="form.description"
|
v-model="form.description"
|
||||||
rows="3"
|
rows="3"
|
||||||
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
||||||
placeholder="Descripción de la categoría"
|
placeholder="Descripción de la clasificación"
|
||||||
></textarea>
|
></textarea>
|
||||||
<FormError :message="form.errors?.description" />
|
<FormError :message="form.errors?.description" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -37,7 +37,7 @@ const handleClose = () => {
|
|||||||
<GoogleIcon name="delete_forever" class="text-2xl text-red-600 dark:text-red-400" />
|
<GoogleIcon name="delete_forever" class="text-2xl text-red-600 dark:text-red-400" />
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
||||||
Eliminar Categoría
|
Eliminar Clasificación
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@ -53,7 +53,7 @@ const handleClose = () => {
|
|||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<div class="space-y-5">
|
<div class="space-y-5">
|
||||||
<p class="text-gray-700 dark:text-gray-300 text-base">
|
<p class="text-gray-700 dark:text-gray-300 text-base">
|
||||||
¿Estás seguro de que deseas eliminar esta categoría?
|
¿Estás seguro de que deseas eliminar esta clasificación?
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div v-if="category" class="bg-linear-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl p-5 space-y-2">
|
<div v-if="category" class="bg-linear-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl p-5 space-y-2">
|
||||||
@ -89,7 +89,7 @@ const handleClose = () => {
|
|||||||
<div class="flex items-start gap-2 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
|
<div class="flex items-start gap-2 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
|
||||||
<GoogleIcon name="info" class="text-red-600 dark:text-red-400 text-xl shrink-0 mt-0.5" />
|
<GoogleIcon name="info" class="text-red-600 dark:text-red-400 text-xl shrink-0 mt-0.5" />
|
||||||
<p class="text-sm text-red-800 dark:text-red-300 font-medium">
|
<p class="text-sm text-red-800 dark:text-red-300 font-medium">
|
||||||
Esta acción es permanente y no se puede deshacer. Los productos asociados a esta categoría perderán su categorización.
|
Esta acción es permanente y no se puede deshacer. Los productos asociados a esta clasificación perderán su clasificación.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -109,7 +109,7 @@ const handleClose = () => {
|
|||||||
class="flex items-center gap-2 px-5 py-2.5 bg-red-600 hover:bg-red-700 text-white text-sm font-semibold rounded-lg focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-600 shadow-lg shadow-red-600/30 transition-all"
|
class="flex items-center gap-2 px-5 py-2.5 bg-red-600 hover:bg-red-700 text-white text-sm font-semibold rounded-lg focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-600 shadow-lg shadow-red-600/30 transition-all"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="delete" class="text-xl" />
|
<GoogleIcon name="delete" class="text-xl" />
|
||||||
Eliminar Categoría
|
Eliminar Clasificación
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -26,12 +26,12 @@ const form = useForm({
|
|||||||
const updateCategory = () => {
|
const updateCategory = () => {
|
||||||
form.put(apiURL(`categorias/${props.category.id}`), {
|
form.put(apiURL(`categorias/${props.category.id}`), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
Notify.success('Categoría actualizada exitosamente');
|
Notify.success('Clasificación actualizada exitosamente');
|
||||||
emit('updated');
|
emit('updated');
|
||||||
closeModal();
|
closeModal();
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Notify.error('Error al actualizar la categoría');
|
Notify.error('Error al actualizar la clasificación');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -57,7 +57,7 @@ watch(() => props.category, (newCategory) => {
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex items-center justify-between mb-6">
|
<div class="flex items-center justify-between mb-6">
|
||||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
||||||
Editar Categoría
|
Editar Clasificación
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button
|
||||||
@click="closeModal"
|
@click="closeModal"
|
||||||
@ -79,7 +79,7 @@ watch(() => props.category, (newCategory) => {
|
|||||||
<FormInput
|
<FormInput
|
||||||
v-model="form.name"
|
v-model="form.name"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Nombre de la categoría"
|
placeholder="Nombre de la clasificación"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<FormError :message="form.errors?.name" />
|
<FormError :message="form.errors?.name" />
|
||||||
@ -94,7 +94,7 @@ watch(() => props.category, (newCategory) => {
|
|||||||
v-model="form.description"
|
v-model="form.description"
|
||||||
rows="3"
|
rows="3"
|
||||||
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
||||||
placeholder="Descripción de la categoría"
|
placeholder="Descripción de la clasificación"
|
||||||
></textarea>
|
></textarea>
|
||||||
<FormError :message="form.errors?.description" />
|
<FormError :message="form.errors?.description" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -72,15 +72,15 @@ const confirmDelete = async (id) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
Notify.success('Categoría eliminada exitosamente');
|
Notify.success('Clasificación eliminada exitosamente');
|
||||||
closeDeleteModal();
|
closeDeleteModal();
|
||||||
searcher.search();
|
searcher.search();
|
||||||
} else {
|
} else {
|
||||||
Notify.error('Error al eliminar la categoría');
|
Notify.error('Error al eliminar la clasificación');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
Notify.error('Error al eliminar la categoría');
|
Notify.error('Error al eliminar la clasificación');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ onMounted(() => {
|
|||||||
@click="openCreateModal"
|
@click="openCreateModal"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="add" class="text-xl" />
|
<GoogleIcon name="add" class="text-xl" />
|
||||||
Nueva Categoría
|
Nueva Clasificación
|
||||||
</button>
|
</button>
|
||||||
</SearcherHead>
|
</SearcherHead>
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ onMounted(() => {
|
|||||||
<button
|
<button
|
||||||
@click="router.push({ name: 'pos.category.subcategories', params: { id: model.id } })"
|
@click="router.push({ name: 'pos.category.subcategories', params: { id: model.id } })"
|
||||||
class="text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
|
class="text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
|
||||||
title="Gestionar subcategorías"
|
title="Gestionar subclasificaciones"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="account_tree" class="text-xl" />
|
<GoogleIcon name="account_tree" class="text-xl" />
|
||||||
</button>
|
</button>
|
||||||
@ -182,7 +182,7 @@ onMounted(() => {
|
|||||||
<button
|
<button
|
||||||
@click="openDeleteModal(model)"
|
@click="openDeleteModal(model)"
|
||||||
class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300 transition-colors"
|
class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300 transition-colors"
|
||||||
title="Eliminar categoría"
|
title="Eliminar clasificación"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="delete" class="text-xl" />
|
<GoogleIcon name="delete" class="text-xl" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -43,14 +43,14 @@ const createSubcategory = () => {
|
|||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
Notify.success(
|
Notify.success(
|
||||||
entries.value.length === 1
|
entries.value.length === 1
|
||||||
? 'Subcategoría creada exitosamente'
|
? 'Subclasificación creada exitosamente'
|
||||||
: 'Subcategorías creadas exitosamente'
|
: 'Subclasificaciones creadas exitosamente'
|
||||||
);
|
);
|
||||||
emit('created', data?.models ?? data?.model);
|
emit('created', data?.models ?? data?.model);
|
||||||
closeModal();
|
closeModal();
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Notify.error('Error al crear la subcategoría');
|
Notify.error('Error al crear la subclasificación');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -68,7 +68,7 @@ const closeModal = () => {
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex items-center justify-between mb-6">
|
<div class="flex items-center justify-between mb-6">
|
||||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
||||||
Crear Subcategoría
|
Crear Subclasificación
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button
|
||||||
@click="closeModal"
|
@click="closeModal"
|
||||||
@ -92,7 +92,7 @@ const closeModal = () => {
|
|||||||
>
|
>
|
||||||
<div v-if="entries.length > 1" class="flex items-center justify-between">
|
<div v-if="entries.length > 1" class="flex items-center justify-between">
|
||||||
<span class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase">
|
<span class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase">
|
||||||
Subcategoría {{ index + 1 }}
|
Subclasificación {{ index + 1 }}
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -114,7 +114,7 @@ const closeModal = () => {
|
|||||||
<FormInput
|
<FormInput
|
||||||
v-model="entry.name"
|
v-model="entry.name"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Nombre de la subcategoría"
|
placeholder="Nombre de la subclasificación"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<FormError :message="form.errors?.[`${index}.name`] ?? form.errors?.name" />
|
<FormError :message="form.errors?.[`${index}.name`] ?? form.errors?.name" />
|
||||||
@ -129,7 +129,7 @@ const closeModal = () => {
|
|||||||
v-model="entry.description"
|
v-model="entry.description"
|
||||||
rows="2"
|
rows="2"
|
||||||
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
||||||
placeholder="Descripción de la subcategoría"
|
placeholder="Descripción de la subclasificación"
|
||||||
></textarea>
|
></textarea>
|
||||||
<FormError :message="form.errors?.[`${index}.description`] ?? form.errors?.description" />
|
<FormError :message="form.errors?.[`${index}.description`] ?? form.errors?.description" />
|
||||||
</div>
|
</div>
|
||||||
@ -159,7 +159,7 @@ const closeModal = () => {
|
|||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
|
||||||
</svg>
|
</svg>
|
||||||
Agregar otra subcategoría
|
Agregar otra subclasificación
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Botones -->
|
<!-- Botones -->
|
||||||
|
|||||||
@ -28,13 +28,13 @@ const form = useForm({
|
|||||||
const createSubcategory = () => {
|
const createSubcategory = () => {
|
||||||
form.post(apiURL(`categorias/${props.categoryId}/subcategorias`), {
|
form.post(apiURL(`categorias/${props.categoryId}/subcategorias`), {
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
Notify.success('Subcategoría creada exitosamente');
|
Notify.success('Subclasificación creada exitosamente');
|
||||||
const created = data?.model ?? (data?.models ? data.models[0] : []);
|
const created = data?.model ?? (data?.models ? data.models[0] : []);
|
||||||
emit('created', created);
|
emit('created', created);
|
||||||
closeModal();
|
closeModal();
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Notify.error('Error al crear la subcategoría');
|
Notify.error('Error al crear la subclasificación');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -51,7 +51,7 @@ const closeModal = () => {
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex items-center justify-between mb-6">
|
<div class="flex items-center justify-between mb-6">
|
||||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
||||||
Crear Subcategoría
|
Crear Subclasificación
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button
|
||||||
@click="closeModal"
|
@click="closeModal"
|
||||||
@ -73,7 +73,7 @@ const closeModal = () => {
|
|||||||
<FormInput
|
<FormInput
|
||||||
v-model="form.name"
|
v-model="form.name"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Nombre de la subcategoría"
|
placeholder="Nombre de la subclasificación"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<FormError :message="form.errors?.name" />
|
<FormError :message="form.errors?.name" />
|
||||||
@ -88,7 +88,7 @@ const closeModal = () => {
|
|||||||
v-model="form.description"
|
v-model="form.description"
|
||||||
rows="3"
|
rows="3"
|
||||||
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
||||||
placeholder="Descripción de la subcategoría"
|
placeholder="Descripción de la subclasificación"
|
||||||
></textarea>
|
></textarea>
|
||||||
<FormError :message="form.errors?.description" />
|
<FormError :message="form.errors?.description" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -37,7 +37,7 @@ const handleClose = () => {
|
|||||||
<GoogleIcon name="delete_forever" class="text-2xl text-red-600 dark:text-red-400" />
|
<GoogleIcon name="delete_forever" class="text-2xl text-red-600 dark:text-red-400" />
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
||||||
Eliminar Subcategoría
|
Eliminar Subclasificación
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@ -53,7 +53,7 @@ const handleClose = () => {
|
|||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<div class="space-y-5">
|
<div class="space-y-5">
|
||||||
<p class="text-gray-700 dark:text-gray-300 text-base">
|
<p class="text-gray-700 dark:text-gray-300 text-base">
|
||||||
¿Estás seguro de que deseas eliminar esta subcategoría?
|
¿Estás seguro de que deseas eliminar esta subclasificación?
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div v-if="subcategory" class="bg-linear-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl p-5 space-y-2">
|
<div v-if="subcategory" class="bg-linear-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl p-5 space-y-2">
|
||||||
@ -89,7 +89,7 @@ const handleClose = () => {
|
|||||||
<div class="flex items-start gap-2 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
|
<div class="flex items-start gap-2 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
|
||||||
<GoogleIcon name="info" class="text-red-600 dark:text-red-400 text-xl shrink-0 mt-0.5" />
|
<GoogleIcon name="info" class="text-red-600 dark:text-red-400 text-xl shrink-0 mt-0.5" />
|
||||||
<p class="text-sm text-red-800 dark:text-red-300 font-medium">
|
<p class="text-sm text-red-800 dark:text-red-300 font-medium">
|
||||||
Los productos que tenían asignada esta subcategoría quedarán sin subcategoría automáticamente.
|
Los productos que tenían asignada esta subclasificación quedarán sin subclasificación automáticamente.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -109,7 +109,7 @@ const handleClose = () => {
|
|||||||
class="flex items-center gap-2 px-5 py-2.5 bg-red-600 hover:bg-red-700 text-white text-sm font-semibold rounded-lg focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-600 shadow-lg shadow-red-600/30 transition-all"
|
class="flex items-center gap-2 px-5 py-2.5 bg-red-600 hover:bg-red-700 text-white text-sm font-semibold rounded-lg focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-600 shadow-lg shadow-red-600/30 transition-all"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="delete" class="text-xl" />
|
<GoogleIcon name="delete" class="text-xl" />
|
||||||
Eliminar Subcategoría
|
Eliminar Subclasificación
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -30,12 +30,12 @@ const form = useForm({
|
|||||||
const updateSubcategory = () => {
|
const updateSubcategory = () => {
|
||||||
form.put(apiURL(`categorias/${props.categoryId}/subcategorias/${props.subcategory.id}`), {
|
form.put(apiURL(`categorias/${props.categoryId}/subcategorias/${props.subcategory.id}`), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
Notify.success('Subcategoría actualizada exitosamente');
|
Notify.success('Subclasificación actualizada exitosamente');
|
||||||
emit('updated');
|
emit('updated');
|
||||||
closeModal();
|
closeModal();
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Notify.error('Error al actualizar la subcategoría');
|
Notify.error('Error al actualizar la subclasificación');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -61,7 +61,7 @@ watch(() => props.subcategory, (newSubcategory) => {
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex items-center justify-between mb-6">
|
<div class="flex items-center justify-between mb-6">
|
||||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100">
|
||||||
Editar Subcategoría
|
Editar Subclasificación
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button
|
||||||
@click="closeModal"
|
@click="closeModal"
|
||||||
@ -83,7 +83,7 @@ watch(() => props.subcategory, (newSubcategory) => {
|
|||||||
<FormInput
|
<FormInput
|
||||||
v-model="form.name"
|
v-model="form.name"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Nombre de la subcategoría"
|
placeholder="Nombre de la subclasificación"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<FormError :message="form.errors?.name" />
|
<FormError :message="form.errors?.name" />
|
||||||
@ -98,7 +98,7 @@ watch(() => props.subcategory, (newSubcategory) => {
|
|||||||
v-model="form.description"
|
v-model="form.description"
|
||||||
rows="3"
|
rows="3"
|
||||||
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100"
|
||||||
placeholder="Descripción de la subcategoría"
|
placeholder="Descripción de la subclasificación"
|
||||||
></textarea>
|
></textarea>
|
||||||
<FormError :message="form.errors?.description" />
|
<FormError :message="form.errors?.description" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -93,15 +93,15 @@ const confirmDelete = async (id) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
Notify.success('Subcategoría eliminada exitosamente');
|
Notify.success('Subclasificación eliminada exitosamente');
|
||||||
closeDeleteModal();
|
closeDeleteModal();
|
||||||
searcher.search();
|
searcher.search();
|
||||||
} else {
|
} else {
|
||||||
Notify.error('Error al eliminar la subcategoría');
|
Notify.error('Error al eliminar la subclasificación');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
Notify.error('Error al eliminar la subcategoría');
|
Notify.error('Error al eliminar la subclasificación');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,14 +120,14 @@ onMounted(() => {
|
|||||||
<button
|
<button
|
||||||
@click="router.push({ name: 'pos.category.index' })"
|
@click="router.push({ name: 'pos.category.index' })"
|
||||||
class="flex items-center justify-center w-8 h-8 rounded-lg text-gray-500 hover:text-gray-700 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-200 dark:hover:bg-gray-800 transition-colors"
|
class="flex items-center justify-center w-8 h-8 rounded-lg text-gray-500 hover:text-gray-700 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-200 dark:hover:bg-gray-800 transition-colors"
|
||||||
title="Volver a categorías"
|
title="Volver a clasificaciones"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="arrow_back" class="text-xl" />
|
<GoogleIcon name="arrow_back" class="text-xl" />
|
||||||
</button>
|
</button>
|
||||||
<div>
|
<div>
|
||||||
<p class="text-xs text-gray-500 dark:text-gray-400">Categoría</p>
|
<p class="text-xs text-gray-500 dark:text-gray-400">Clasificación</p>
|
||||||
<h1 class="text-xl font-bold text-gray-900 dark:text-gray-100">
|
<h1 class="text-xl font-bold text-gray-900 dark:text-gray-100">
|
||||||
{{ categoryName || 'Subcategorías' }}
|
{{ categoryName || 'Subclasificaciones' }}
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -136,7 +136,7 @@ onMounted(() => {
|
|||||||
@click="openCreateModal"
|
@click="openCreateModal"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="add" class="text-xl" />
|
<GoogleIcon name="add" class="text-xl" />
|
||||||
Nueva Subcategoría
|
Nueva Subclasificación
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -204,14 +204,14 @@ onMounted(() => {
|
|||||||
<button
|
<button
|
||||||
@click="openEditModal(model)"
|
@click="openEditModal(model)"
|
||||||
class="text-indigo-600 hover:text-indigo-900 transition-colors"
|
class="text-indigo-600 hover:text-indigo-900 transition-colors"
|
||||||
title="Editar subcategoría"
|
title="Editar subclasificación"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="edit" class="text-xl" />
|
<GoogleIcon name="edit" class="text-xl" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="openDeleteModal(model)"
|
@click="openDeleteModal(model)"
|
||||||
class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300 transition-colors"
|
class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300 transition-colors"
|
||||||
title="Eliminar subcategoría"
|
title="Eliminar subclasificación"
|
||||||
>
|
>
|
||||||
<GoogleIcon name="delete" class="text-xl" />
|
<GoogleIcon name="delete" class="text-xl" />
|
||||||
</button>
|
</button>
|
||||||
@ -226,7 +226,7 @@ onMounted(() => {
|
|||||||
name="category"
|
name="category"
|
||||||
class="text-6xl mb-2 opacity-50"
|
class="text-6xl mb-2 opacity-50"
|
||||||
/>
|
/>
|
||||||
<p class="font-semibold">No hay subcategorías registradas</p>
|
<p class="font-semibold">No hay subclasificaciones registradas</p>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -157,10 +157,12 @@ const sendInvoiceByWhatsapp = async () => {
|
|||||||
sendingWhatsapp.value = true;
|
sendingWhatsapp.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await whatsappService.sendInvoice({
|
const ticket = request.sale?.invoice_number || `SOL-${request.id}`;
|
||||||
|
await whatsappService.sendDocument({
|
||||||
phone_number: request.client.phone,
|
phone_number: request.client.phone,
|
||||||
invoice_number: request.sale?.invoice_number || `SOL-${request.id}`,
|
document_url: request.invoice_pdf_url,
|
||||||
pdf_url: request.invoice_pdf_url,
|
filename: `${ticket}.pdf`,
|
||||||
|
ticket,
|
||||||
customer_name: request.client.name
|
customer_name: request.client.name
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -419,7 +421,7 @@ const sendInvoiceByWhatsapp = async () => {
|
|||||||
{{ item.product_name }}
|
{{ item.product_name }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs text-green-700 dark:text-green-300">
|
<p class="text-xs text-green-700 dark:text-green-300">
|
||||||
SKU: {{ item.inventory?.sku || 'N/A' }} • {{ item.inventory?.category?.name || 'Sin categoría' }}
|
SKU: {{ item.inventory?.sku || 'N/A' }} • {{ item.inventory?.category?.name || 'Sin clasificación' }}
|
||||||
</p>
|
</p>
|
||||||
<div v-if="item.serials && item.serials.length > 0" class="mt-1">
|
<div v-if="item.serials && item.serials.length > 0" class="mt-1">
|
||||||
<p class="text-xs text-green-600 dark:text-green-400">
|
<p class="text-xs text-green-600 dark:text-green-400">
|
||||||
|
|||||||
@ -65,7 +65,7 @@ const handleClose = () => {
|
|||||||
<div class="flex items-center gap-3 text-sm text-gray-600 dark:text-gray-400">
|
<div class="flex items-center gap-3 text-sm text-gray-600 dark:text-gray-400">
|
||||||
<span class="font-mono font-medium">SKU: {{ product.sku }}</span>
|
<span class="font-mono font-medium">SKU: {{ product.sku }}</span>
|
||||||
<span class="text-gray-400">•</span>
|
<span class="text-gray-400">•</span>
|
||||||
<span>{{ product.category?.name || 'Sin categoría' }}</span>
|
<span>{{ product.category?.name || 'Sin clasificación' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
|
|||||||
@ -58,7 +58,7 @@ const loadCategories = async () => {
|
|||||||
categories.value = result.data.categories.data;
|
categories.value = result.data.categories.data;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error al cargar categorías:', error);
|
console.error('Error al cargar clasificaciones:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ const loadSubcategories = async () => {
|
|||||||
categories.value = result.data.subcategories.data;
|
categories.value = result.data.subcategories.data;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error al cargar subcategorías:', error);
|
console.error('Error al cargar subclasificaciones:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -266,13 +266,13 @@ onMounted(() => {
|
|||||||
<div class="pt-4 pb-2">
|
<div class="pt-4 pb-2">
|
||||||
<div class="flex items-end gap-4">
|
<div class="flex items-end gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">Filtrar por categoría:</label>
|
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">Filtrar por clasificación:</label>
|
||||||
<select
|
<select
|
||||||
v-model="selectedCategory"
|
v-model="selectedCategory"
|
||||||
@change="handleCategoryChange"
|
@change="handleCategoryChange"
|
||||||
class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
||||||
>
|
>
|
||||||
<option value="">Todas las categorías</option>
|
<option value="">Todas las clasificaciones</option>
|
||||||
<option v-for="category in categories" :key="category.id" :value="category.id">
|
<option v-for="category in categories" :key="category.id" :value="category.id">
|
||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
@ -103,7 +103,7 @@ onMounted(() => {
|
|||||||
<p class="text-sm text-gray-500 dark:text-gray-400">
|
<p class="text-sm text-gray-500 dark:text-gray-400">
|
||||||
SKU: {{ inventory.sku }}
|
SKU: {{ inventory.sku }}
|
||||||
<span v-if="inventory.category">
|
<span v-if="inventory.category">
|
||||||
| Categoría: {{ inventory.category.name }}
|
| Clasificación: {{ inventory.category.name }}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -64,7 +64,7 @@ const loadCategories = async () => {
|
|||||||
categories.value = result.data.categories.data;
|
categories.value = result.data.categories.data;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error al cargar categorías:', error);
|
console.error('Error al cargar clasificaciones:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -175,13 +175,13 @@ onMounted(async () => {
|
|||||||
<div class="pt-4 pb-2">
|
<div class="pt-4 pb-2">
|
||||||
<div class="flex items-end gap-4">
|
<div class="flex items-end gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">Filtrar por categoría:</label>
|
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">Filtrar por clasificación:</label>
|
||||||
<select
|
<select
|
||||||
v-model="selectedCategory"
|
v-model="selectedCategory"
|
||||||
@change="handleCategoryChange"
|
@change="handleCategoryChange"
|
||||||
class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
||||||
>
|
>
|
||||||
<option value="">Todas las categorías</option>
|
<option value="">Todas las clasificaciones</option>
|
||||||
<option v-for="category in categories" :key="category.id" :value="category.id">
|
<option v-for="category in categories" :key="category.id" :value="category.id">
|
||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
</option>
|
</option>
|
||||||
@ -207,7 +207,7 @@ onMounted(async () => {
|
|||||||
<template #head>
|
<template #head>
|
||||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">SKU / CÓDIGO</th>
|
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">SKU / CÓDIGO</th>
|
||||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">PRODUCTO</th>
|
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">PRODUCTO</th>
|
||||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">CATEGORÍA</th>
|
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">CLASIFICACIÓN</th>
|
||||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">PRECIO</th>
|
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">PRECIO</th>
|
||||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">STOCK</th>
|
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">STOCK</th>
|
||||||
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">TOTAL</th>
|
<th class="px-6 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">TOTAL</th>
|
||||||
|
|||||||
@ -6,19 +6,19 @@ import axios from 'axios';
|
|||||||
*/
|
*/
|
||||||
const whatsappService = {
|
const whatsappService = {
|
||||||
/**
|
/**
|
||||||
* Enviar factura por WhatsApp
|
* Enviar documento por WhatsApp
|
||||||
* @param {Object} data - Datos de la factura
|
* @param {Object} data - Datos del documento
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
async sendInvoice({ phone_number, invoice_number, pdf_url, xml_url = null, customer_name }) {
|
async sendDocument({ phone_number, document_url, filename, ticket, customer_name }) {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.post(
|
const { data } = await axios.post(
|
||||||
apiURL('whatsapp/send-invoice'),
|
apiURL('whatsapp/send-document'),
|
||||||
{
|
{
|
||||||
phone_number,
|
phone_number,
|
||||||
invoice_number,
|
document_url,
|
||||||
pdf_url,
|
filename,
|
||||||
xml_url,
|
ticket,
|
||||||
customer_name
|
customer_name
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user