|
|
@@ -0,0 +1,233 @@
|
|
|
+<template>
|
|
|
+ <q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
|
+ <div style="width: 100%; max-width: 700px">
|
|
|
+ <q-card class="overflow-hidden" style="width: 100%">
|
|
|
+ <q-btn
|
|
|
+ flat
|
|
|
+ round
|
|
|
+ dense
|
|
|
+ icon="mdi-close"
|
|
|
+ class="absolute-top-right q-ma-sm"
|
|
|
+ style="z-index: 1"
|
|
|
+ @click="onDialogCancel"
|
|
|
+ />
|
|
|
+
|
|
|
+ <q-form ref="formRef" @submit="onOKClick">
|
|
|
+ <q-card-section class="q-pt-lg">
|
|
|
+ <div class="row q-col-gutter-sm">
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.name"
|
|
|
+ label="Nome do Pacote"
|
|
|
+ class="col-12"
|
|
|
+ />
|
|
|
+
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.quantity_classes"
|
|
|
+ label="Quantidade de Aulas"
|
|
|
+ class="col-12"
|
|
|
+ type="number"
|
|
|
+ />
|
|
|
+
|
|
|
+ <DefaultCurrencyInput
|
|
|
+ v-model="form.contract_register_value"
|
|
|
+ label="R$ Matrícula"
|
|
|
+ class="col-4"
|
|
|
+ />
|
|
|
+
|
|
|
+ <DefaultCurrencyInput
|
|
|
+ v-model="form.contract_value"
|
|
|
+ label="R$ Total do Contrato"
|
|
|
+ class="col-4"
|
|
|
+ />
|
|
|
+
|
|
|
+ <DefaultInput
|
|
|
+ v-model="form.contrat_discount_value"
|
|
|
+ label="Desconto em %"
|
|
|
+ class="col-4"
|
|
|
+ type="number"
|
|
|
+ min="0"
|
|
|
+ max="100"
|
|
|
+ />
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-for="(material, index) in form.materials"
|
|
|
+ :key="index"
|
|
|
+ class="col-12"
|
|
|
+ >
|
|
|
+ <div class="row q-col-gutter-sm items-center">
|
|
|
+ <DefaultSelect
|
|
|
+ v-model="material.product_id"
|
|
|
+ label="Material"
|
|
|
+ class="col"
|
|
|
+ :options="productOptions"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ @update:model-value="onProductSelected(material)"
|
|
|
+ />
|
|
|
+
|
|
|
+ <DefaultInput
|
|
|
+ v-model="material.quantity"
|
|
|
+ label="Qtd"
|
|
|
+ class="col-2"
|
|
|
+ type="number"
|
|
|
+ min="1"
|
|
|
+ />
|
|
|
+
|
|
|
+ <DefaultCurrencyInput
|
|
|
+ v-model="material.price"
|
|
|
+ label="R$ Unitário"
|
|
|
+ class="col-3"
|
|
|
+ />
|
|
|
+
|
|
|
+ <div class="col-auto">
|
|
|
+ <q-btn
|
|
|
+ v-if="index === form.materials.length - 1"
|
|
|
+ color="primary"
|
|
|
+ icon="mdi-plus"
|
|
|
+ unelevated
|
|
|
+ style="border-radius: 8px; height: 40px; width: 40px"
|
|
|
+ @click="addMaterial"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ v-else
|
|
|
+ flat
|
|
|
+ round
|
|
|
+ dense
|
|
|
+ icon="mdi-delete-outline"
|
|
|
+ color="negative"
|
|
|
+ @click="removeMaterial(index)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-actions align="right" class="q-px-md q-pb-md">
|
|
|
+ <q-btn
|
|
|
+ outline
|
|
|
+ color="primary"
|
|
|
+ label="Cancelar"
|
|
|
+ @click="onDialogCancel"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ color="primary"
|
|
|
+ label="Salvar"
|
|
|
+ type="submit"
|
|
|
+ :loading="loading"
|
|
|
+ />
|
|
|
+ </q-card-actions>
|
|
|
+ </q-form>
|
|
|
+ </q-card>
|
|
|
+ </div>
|
|
|
+ </q-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed, onMounted } from "vue";
|
|
|
+import { useDialogPluginComponent } from "quasar";
|
|
|
+
|
|
|
+import DefaultInput from "src/components/defaults/DefaultInput.vue";
|
|
|
+import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
|
|
|
+import DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
|
|
|
+
|
|
|
+import {
|
|
|
+ getUnitPackage,
|
|
|
+ createUnitPackage,
|
|
|
+ updateUnitPackage,
|
|
|
+} from "src/api/package";
|
|
|
+import { getProductsForSelect } from "src/api/product";
|
|
|
+
|
|
|
+defineEmits([...useDialogPluginComponent.emits]);
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ package: {
|
|
|
+ type: Object,
|
|
|
+ default: null,
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
|
+ useDialogPluginComponent();
|
|
|
+
|
|
|
+const formRef = ref(null);
|
|
|
+const loading = ref(false);
|
|
|
+
|
|
|
+const products = ref([]);
|
|
|
+
|
|
|
+const productOptions = computed(() =>
|
|
|
+ products.value.map((p) => ({
|
|
|
+ label: p.name,
|
|
|
+ value: p.id,
|
|
|
+ price_sale: p.price_sale,
|
|
|
+ })),
|
|
|
+);
|
|
|
+
|
|
|
+const form = ref({
|
|
|
+ name: props.package?.name ?? null,
|
|
|
+ quantity_classes: props.package?.quantity_classes ?? null,
|
|
|
+ contract_register_value: props.package?.contract_register_value ?? null,
|
|
|
+ contract_value: props.package?.contract_value ?? null,
|
|
|
+ contrat_discount_value: props.package?.contrat_discount_value ?? null,
|
|
|
+ materials: [{ product_id: null, quantity: 1, price: null }],
|
|
|
+});
|
|
|
+
|
|
|
+const onProductSelected = (material) => {
|
|
|
+ const option = productOptions.value.find(
|
|
|
+ (o) => o.value === material.product_id,
|
|
|
+ );
|
|
|
+ if (option) material.price = option.price_sale;
|
|
|
+};
|
|
|
+
|
|
|
+const addMaterial = () => {
|
|
|
+ form.value.materials.push({ product_id: null, quantity: 1, price: null });
|
|
|
+};
|
|
|
+
|
|
|
+const removeMaterial = (index) => {
|
|
|
+ form.value.materials.splice(index, 1);
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ const [allProducts] = await Promise.all([getProductsForSelect()]);
|
|
|
+ products.value = allProducts;
|
|
|
+
|
|
|
+ if (props.package?.id) {
|
|
|
+ const pkg = await getUnitPackage(props.package.id);
|
|
|
+ if (pkg.materials?.length) {
|
|
|
+ form.value.materials = pkg.materials.map((m) => ({
|
|
|
+ product_id: m.product_id,
|
|
|
+ quantity: m.quantity,
|
|
|
+ price: m.price,
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const onOKClick = async () => {
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const validMaterials = form.value.materials.filter((m) => m.product_id);
|
|
|
+
|
|
|
+ const payload = {
|
|
|
+ name: form.value.name,
|
|
|
+ quantity_classes: form.value.quantity_classes,
|
|
|
+ contract_value: form.value.contract_value,
|
|
|
+ contract_register_value: form.value.contract_register_value,
|
|
|
+ contrat_discount_value: form.value.contrat_discount_value,
|
|
|
+ materials: validMaterials.map((m) => ({
|
|
|
+ product_id: m.product_id,
|
|
|
+ quantity: Number(m.quantity),
|
|
|
+ price: Number(m.price),
|
|
|
+ })),
|
|
|
+ };
|
|
|
+
|
|
|
+ const result = props.package?.id
|
|
|
+ ? await updateUnitPackage(props.package.id, payload)
|
|
|
+ : await createUnitPackage(payload);
|
|
|
+
|
|
|
+ onDialogOK(result);
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|