FIX:Errores en creación de conceptos

This commit is contained in:
Rubi Almora 2026-03-06 11:44:15 -06:00
parent 76b1c6c02b
commit 104e2e327e
6 changed files with 203 additions and 151 deletions

View File

@ -17,6 +17,7 @@ const form = useForm({
legal_instrument: "",
article: "",
content: "",
motivation: "",
min_amount_uma: "",
max_amount_uma: "",
min_amount_peso: "",
@ -35,6 +36,7 @@ const resetForm = () => {
form.legal_instrument = "";
form.article = "";
form.content = "";
form.motivation = "";
form.min_amount_uma = "";
form.max_amount_uma = "";
form.min_amount_peso = "";
@ -91,6 +93,14 @@ const isFixedType = computed(() => {
);
});
const conceptTypeId = computed(() => {
return typeof form.concept_type === "object" && form.concept_type?.id
? form.concept_type.id
: form.concept_type;
});
const isFineConcept = computed(() => conceptTypeId.value === "fine");
/** Cargar cosas */
onMounted(async () => {
api.get(apiURL("directions"), {
@ -114,16 +124,23 @@ const handleSubmit = () => {
? form.direction_id.id
: Number(form.direction_id),
unit_id:
typeof form.unit_id === "object" ? form.unit_id.id : Number(form.unit_id),
form.unit_id != null
? typeof form.unit_id === "object"
? form.unit_id.id
: Number(form.unit_id)
: null,
concept_type:
typeof form.concept_type === "object"
? form.concept_type.id
: String(form.concept_type),
short_name: form.short_name,
name: form.name,
...(isFineConcept.value && {
legal_instrument: form.legal_instrument,
article: form.article,
content: form.content,
motivation: form.motivation,
}),
charge_type: chargeTypeId.value,
};
@ -218,6 +235,7 @@ const handleSubmit = () => {
required
/>
</div>
<template v-if="isFineConcept">
<div class="mb-5 grid grid-cols-2 gap-4 py-2">
<Input
v-model="form.legal_instrument"
@ -234,13 +252,22 @@ const handleSubmit = () => {
:onError="form.errors.article"
/>
</div>
<div class="mb-5 gap-4">
<Textarea
v-model="form.content"
class="col-span-2"
:id="$t('concept.description')"
:onError="form.errors.content"
required
/>
</div>
<div class="mb-5 gap-4 py-2">
<Input
v-model="form.motivation"
:id="$t('concept.motivation')"
type="text"
:onError="form.errors.motivation"
/>
</div>
</template>
<div class="">
<hr class="my-6 border-gray-300" />

View File

@ -0,0 +1,31 @@
<script setup>
import SingleFile from '@Holos/Form/SingleFile.vue';
import Error from '@Holos/Form/Elements/Error.vue';
defineProps({
modelValue: [Object, File, String],
required: Boolean,
title: { type: String, default: '' },
onError: [String, Array],
accept: { type: String, default: 'image/png, image/jpeg' },
});
const emit = defineEmits(['update:modelValue']);
</script>
<template>
<div class="flex flex-col">
<SingleFile
:model-value="modelValue"
:title="title"
:required="required"
:accept="accept"
@update:model-value="emit('update:modelValue', $event)"
>
<template #previous>
<slot name="previous" />
</template>
</SingleFile>
<Error :onError="onError" />
</div>
</template>

View File

@ -114,6 +114,7 @@ export default {
shortName: 'Nombre Corto',
name: 'Nombre',
legal: 'Instrumento Legal',
motivation: 'Motivación',
article: 'Articulado',
description: 'Contenido',
chargeType: 'Tipo de Cobro',
@ -153,6 +154,10 @@ export default {
},
membership: {
title: 'Membresías',
curp: 'CURP',
name: 'Nombre',
tutor: 'Tutor',
photo: 'Foto',
create: {
title: 'Crear membresía',
description: 'Permite crear nuevas membresías.',

View File

@ -89,13 +89,16 @@ const editIsFixedType = computed(() => {
const handleUpdate = async () => {
const transformedData = {
direction_id: typeof props.model.direction === 'object' ? props.model.direction.id : Number(props.model.direction_id),
unit_id: props.model.unit ? (typeof props.model.unit === 'object' ? props.model.unit.id : Number(props.model.unit)) : null,
unit_id: editIsFixedType.value && props.model.unit
? (typeof props.model.unit === 'object' ? props.model.unit.id : Number(props.model.unit))
: null,
short_name: props.model.short_name,
concept_type: props.model.concept_type,
name: props.model.name,
legal_instrument: props.model.legal_instrument,
article: props.model.article,
content: props.model.content,
motivation: props.model.motivation,
charge_type: editChargeTypeId.value,
// Campos UMA para tipos de rango
min_amount_uma: (editShowUmaFields.value && editIsRangeType.value && props.model.min_amount_uma) ? Number(props.model.min_amount_uma) : null,
@ -161,20 +164,20 @@ const handleUpdate = async () => {
v-model="model.legal_instrument"
:id="$t('concept.legal')"
type="text"
required
/>
<Input
v-model="model.article"
:id="$t('concept.article')"
type="text"
required
/>
<Textarea
v-model="model.content"
:id="$t('concept.description')"
required
/>
<Textarea
v-model="model.motivation"
:id="$t('concept.motivation')"
/>
<!-- Selector de tipo de cargo -->
<Selectable
v-model="chargeTypeObject"
@ -184,8 +187,10 @@ const handleUpdate = async () => {
required
/>
<div v-if="editShowUmaFields && editIsRangeType" class="grid grid-cols-2 gap-4">
<!-- Rango: solo monto mínimo y monto máximo (UMA o pesos) -->
<div v-if="editIsRangeType" class="grid grid-cols-2 gap-4">
<Input
v-if="editShowUmaFields"
v-model="model.min_amount_uma"
:id="$t('concept.minimumAmountUma')"
type="number"
@ -193,16 +198,15 @@ const handleUpdate = async () => {
required
/>
<Input
v-if="editShowUmaFields"
v-model="model.max_amount_uma"
:id="$t('concept.maximumAmountUma')"
type="number"
step="0.01"
required
/>
</div>
<div v-if="editShowPesoFields && editIsRangeType" class="grid grid-cols-2 gap-4">
<Input
v-if="editShowPesoFields"
v-model="model.min_amount_peso"
:id="$t('concept.minimumAmountPeso')"
type="number"
@ -210,6 +214,7 @@ const handleUpdate = async () => {
required
/>
<Input
v-if="editShowPesoFields"
v-model="model.max_amount_peso"
:id="$t('concept.maximumAmountPeso')"
type="number"
@ -218,6 +223,8 @@ const handleUpdate = async () => {
/>
</div>
<!-- Tabulador: unidad de medida y costo por unidad (UMA o pesos) -->
<div v-if="editIsFixedType" class="grid grid-cols-2 gap-4">
<Selectable
v-model="model.unit"
label="name"
@ -226,13 +233,6 @@ const handleUpdate = async () => {
:options="units"
required
/>
<div v-if="editIsFixedType">
<hr class="my-4 border-gray-300" />
<h4 class="text-lg font-semibold mb-2 text-gray-700">
{{ $t('concept.tabulator') }}
</h4>
<div class="grid grid-cols-2 gap-4">
<Input
v-if="editShowUmaFields"
v-model="model.unit_cost_uma"
@ -241,7 +241,6 @@ const handleUpdate = async () => {
step="0.01"
required
/>
<Input
v-if="editShowPesoFields"
v-model="model.unit_cost_peso"
@ -252,6 +251,5 @@ const handleUpdate = async () => {
/>
</div>
</div>
</div>
</Editview>
</template>

View File

@ -1,47 +1,31 @@
<script setup>
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { api, useForm } from '@Services/Api';
import { useForm } from '@Services/Api';
import { apiTo, transl, viewTo } from './Module';
import IconButton from '@Holos/Button/Icon.vue'
import Input from '@Holos/Form/Input.vue';
import Selectable from '@Holos/Form/Selectable.vue';
import IconButton from '@Holos/Button/Icon.vue';
import PageHeader from '@Holos/PageHeader.vue';
import Form from './Form.vue'
import Form from './Form.vue';
/** Definidores */
const router = useRouter();
/** Propiedades */
const form = useForm({
name: '',
paternal: '',
maternal: '',
curp: '',
membership_number: '',
name: '',
tutor: '',
photo: null,
});
/** Métodos */
function submit() {
form.transform(data => ({
...data,
})).post(apiTo('store'), {
form
.transform((data) => ({ ...data }))
.post(route('members.store'), {
onSuccess: () => {
Notify.success(Lang('register.create.onSuccess'))
Notify.success(transl('create.onSuccess'));
router.push(viewTo({ name: 'index' }));
}
})
}
/** Ciclos */
onMounted(() => {
api.get(route('system.roles'), {
onSuccess: (r) => {
roles.value = r.roles;
}
},
});
})
}
</script>
<template>

View File

@ -3,24 +3,23 @@ import { transl } from './Module';
import PrimaryButton from '@Holos/Button/Primary.vue';
import Input from '@Holos/Form/Input.vue';
import PhotoUpload from '@App/PhotoUpload.vue';
/** Eventos */
const emit = defineEmits([
'submit'
])
const emit = defineEmits(['submit']);
/** Propiedades */
defineProps({
action: {
default: 'create',
type: String
type: String,
},
form: Object
})
form: Object,
});
/** Métodos */
function submit() {
emit('submit')
emit('submit');
}
</script>
@ -29,33 +28,41 @@ function submit() {
<p class="text-justify text-sm" v-text="transl(`${action}.description`)" />
</div>
<div class="w-full">
<form @submit.prevent="submit" class="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<Input
v-model="form.name"
id="name"
:onError="form.errors.name"
autofocus
required
/>
<Input
v-model="form.paternal"
id="paternal"
:onError="form.errors.paternal"
required
/>
<Input
v-model="form.maternal"
id="maternal"
:onError="form.errors.maternal"
/>
<form
@submit.prevent="submit"
class="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
>
<Input
v-model="form.curp"
id="Curp"
:onError="form.errors.curp"
:id="$t('membership.curp')"
type="text"
:onError="form.errors.curp"
required
autofocus
/>
<Input
v-model="form.name"
:id="$t('membership.name')"
type="text"
:onError="form.errors.name"
required
/>
<Input
v-model="form.tutor"
:id="$t('membership.tutor')"
type="text"
:onError="form.errors.tutor"
/>
<PhotoUpload
v-model="form.photo"
:title="$t('membership.photo')"
:onError="form.errors.photo"
required
/>
<slot />
<div class="col-span-1 md:col-span-2 lg:col-span-3 xl:col-span-4 flex flex-col items-center justify-end space-y-4 mt-4">
<div
class="col-span-1 md:col-span-2 lg:col-span-3 xl:col-span-4 flex flex-col items-center justify-end space-y-4 mt-4"
>
<PrimaryButton
v-text="$t(action)"
:class="{ 'opacity-25': form.processing }"