Forráskód Böngészése

✨ feat(selects): adicionar componentes de seleção para categorias, parceiros, cargos e setores

Fase: dev | Origin: melhoria-interna
Gustavo Zanatta 1 hete
szülő
commit
f189e14787

+ 75 - 0
src/components/selects/CategorySelect.vue

@@ -0,0 +1,75 @@
+<template>
+  <DefaultSelect
+    v-model="selectedCategory"
+    v-bind="$attrs"
+    use-input
+    hide-selected
+    fill-input
+    clearable
+    :options="categoryOptions"
+    :label
+    :loading
+    :placeholder
+    @filter="filterFn"
+  >
+    <template #no-option>
+      <q-item>
+        <q-item-section class="text-grey">
+          {{ $t("http.errors.no_records_found") }}
+        </q-item-section>
+      </q-item>
+    </template>
+  </DefaultSelect>
+</template>
+
+<script setup>
+import { ref, onMounted } from "vue";
+import { getCategories } from "src/api/category";
+import { normalizeString } from "src/helpers/utils";
+import { useI18n } from "vue-i18n";
+import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
+
+const { label, placeholder, type } = defineProps({
+  label: {
+    type: String,
+    default: () => useI18n().t("associado.category"),
+  },
+  placeholder: {
+    type: String,
+    default: () => useI18n().t("common.actions.search"),
+  },
+  type: {
+    type: String,
+    default: null,
+  },
+});
+
+const selectedCategory = defineModel({ type: Object });
+
+const loading = ref(true);
+const baseOptions = ref([]);
+const categoryOptions = ref([]);
+
+const filterFn = (val, update) => {
+  const needle = normalizeString(val);
+  categoryOptions.value = baseOptions.value.filter((v) =>
+    normalizeString(v.label).includes(needle),
+  );
+  update();
+};
+
+onMounted(async () => {
+  try {
+    const categories = await getCategories(type);
+    baseOptions.value = categories.map((c) => ({
+      label: c.name,
+      value: c.id,
+    }));
+    categoryOptions.value = baseOptions.value;
+  } catch (e) {
+    console.error(e);
+  } finally {
+    loading.value = false;
+  }
+});
+</script>

+ 17 - 0
src/components/selects/PartnerAgreementCategorySelect.vue

@@ -0,0 +1,17 @@
+<template>
+  <CategorySelect v-model="model" v-bind="$attrs" type="partner" :label="label" />
+</template>
+
+<script setup>
+import { useI18n } from "vue-i18n";
+import CategorySelect from "src/components/selects/CategorySelect.vue";
+
+const { label } = defineProps({
+  label: {
+    type: String,
+    default: () => useI18n().t("parceiro.category"),
+  },
+});
+
+const model = defineModel({ type: Object });
+</script>

+ 71 - 0
src/components/selects/PartnerAgreementSelect.vue

@@ -0,0 +1,71 @@
+<template>
+  <DefaultSelect
+    v-model="selectedPartner"
+    v-bind="$attrs"
+    use-input
+    hide-selected
+    fill-input
+    clearable
+    :options="partnerOptions"
+    :label
+    :loading
+    :placeholder
+    @filter="filterFn"
+  >
+    <template #no-option>
+      <q-item>
+        <q-item-section class="text-grey">
+          {{ $t("http.errors.no_records_found") }}
+        </q-item-section>
+      </q-item>
+    </template>
+  </DefaultSelect>
+</template>
+
+<script setup>
+import { ref, onMounted } from "vue";
+import { getPartnerAgreements } from "src/api/partnerAgreement";
+import { normalizeString } from "src/helpers/utils";
+import { useI18n } from "vue-i18n";
+import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
+
+const { label, placeholder } = defineProps({
+  label: {
+    type: String,
+    default: () => useI18n().t("ui.navigation.convenios"),
+  },
+  placeholder: {
+    type: String,
+    default: () => useI18n().t("common.actions.search"),
+  },
+});
+
+const selectedPartner = defineModel({ type: Object });
+
+const loading = ref(true);
+const baseOptions = ref([]);
+const partnerOptions = ref([]);
+
+const filterFn = (val, update) => {
+  const needle = normalizeString(val);
+  partnerOptions.value = baseOptions.value.filter((v) =>
+    normalizeString(v.label).includes(needle),
+  );
+  update();
+};
+
+onMounted(async () => {
+  try {
+    const partners = await getPartnerAgreements();
+    baseOptions.value = partners.map((p) => ({
+      label: p.trade_name || p.company_name,
+      value: p.id,
+    }));
+    partnerOptions.value = baseOptions.value;
+  } catch (e) {
+    console.error(e);
+  } finally {
+    loading.value = false;
+  }
+});
+</script>

+ 69 - 0
src/components/selects/PartnerAgreementServiceSelect.vue

@@ -0,0 +1,69 @@
+<template>
+  <DefaultSelect
+    v-model="selectedService"
+    v-bind="$attrs"
+    :options="serviceOptions"
+    :label
+    :loading
+    :placeholder
+    :disable="!partnerAgreementId"
+  >
+    <template #no-option>
+      <q-item>
+        <q-item-section class="text-grey">
+          {{ $t("http.errors.no_records_found") }}
+        </q-item-section>
+      </q-item>
+    </template>
+  </DefaultSelect>
+</template>
+
+<script setup>
+import { ref, watch } from "vue";
+import { getServicesByPartner } from "src/api/partnerAgreementService";
+import { useI18n } from "vue-i18n";
+import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
+
+const { label, placeholder, partnerAgreementId } = defineProps({
+  label: {
+    type: String,
+    default: () => useI18n().t("associado.service"),
+  },
+  placeholder: {
+    type: String,
+    default: () => useI18n().t("common.actions.search"),
+  },
+  partnerAgreementId: {
+    type: Number,
+    default: null,
+  },
+});
+
+const selectedService = defineModel({ type: Object });
+
+const loading = ref(false);
+const serviceOptions = ref([]);
+
+watch(
+  () => partnerAgreementId,
+  async (id) => {
+    selectedService.value = null;
+    serviceOptions.value = [];
+    if (!id) return;
+    loading.value = true;
+    try {
+      const services = await getServicesByPartner(id);
+      serviceOptions.value = services.map((s) => ({
+        label: s.name,
+        value: s.id,
+        data: s,
+      }));
+    } catch (e) {
+      console.error(e);
+    } finally {
+      loading.value = false;
+    }
+  },
+  { immediate: true },
+);
+</script>

+ 68 - 0
src/components/selects/PositionSelect.vue

@@ -0,0 +1,68 @@
+<template>
+  <DefaultSelect
+    v-model="selected"
+    v-bind="$attrs"
+    use-input
+    hide-selected
+    fill-input
+    clearable
+    :options="filteredOptions"
+    :label
+    :loading
+    :placeholder
+    @filter="filterFn"
+  >
+    <template #no-option>
+      <q-item>
+        <q-item-section class="text-grey">
+          {{ $t("http.errors.no_records_found") }}
+        </q-item-section>
+      </q-item>
+    </template>
+  </DefaultSelect>
+</template>
+
+<script setup>
+import { ref, onMounted } from "vue";
+import { getPositions } from "src/api/position";
+import { normalizeString } from "src/helpers/utils";
+import { useI18n } from "vue-i18n";
+import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
+
+const { label, placeholder } = defineProps({
+  label: {
+    type: String,
+    default: () => useI18n().t("associado.position"),
+  },
+  placeholder: {
+    type: String,
+    default: () => useI18n().t("common.actions.search"),
+  },
+});
+
+const selected = defineModel({ type: Object });
+
+const loading = ref(true);
+const baseOptions = ref([]);
+const filteredOptions = ref([]);
+
+const filterFn = (val, update) => {
+  const needle = normalizeString(val);
+  filteredOptions.value = baseOptions.value.filter((v) =>
+    normalizeString(v.label).includes(needle),
+  );
+  update();
+};
+
+onMounted(async () => {
+  try {
+    const items = await getPositions();
+    baseOptions.value = items.map((p) => ({ label: p.name, value: p.id }));
+    filteredOptions.value = baseOptions.value;
+  } catch (e) {
+    console.error(e);
+  } finally {
+    loading.value = false;
+  }
+});
+</script>

+ 68 - 0
src/components/selects/SectorSelect.vue

@@ -0,0 +1,68 @@
+<template>
+  <DefaultSelect
+    v-model="selected"
+    v-bind="$attrs"
+    use-input
+    hide-selected
+    fill-input
+    clearable
+    :options="filteredOptions"
+    :label
+    :loading
+    :placeholder
+    @filter="filterFn"
+  >
+    <template #no-option>
+      <q-item>
+        <q-item-section class="text-grey">
+          {{ $t("http.errors.no_records_found") }}
+        </q-item-section>
+      </q-item>
+    </template>
+  </DefaultSelect>
+</template>
+
+<script setup>
+import { ref, onMounted } from "vue";
+import { getSectors } from "src/api/sector";
+import { normalizeString } from "src/helpers/utils";
+import { useI18n } from "vue-i18n";
+import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
+
+const { label, placeholder } = defineProps({
+  label: {
+    type: String,
+    default: () => useI18n().t("associado.sector"),
+  },
+  placeholder: {
+    type: String,
+    default: () => useI18n().t("common.actions.search"),
+  },
+});
+
+const selected = defineModel({ type: Object });
+
+const loading = ref(true);
+const baseOptions = ref([]);
+const filteredOptions = ref([]);
+
+const filterFn = (val, update) => {
+  const needle = normalizeString(val);
+  filteredOptions.value = baseOptions.value.filter((v) =>
+    normalizeString(v.label).includes(needle),
+  );
+  update();
+};
+
+onMounted(async () => {
+  try {
+    const items = await getSectors();
+    baseOptions.value = items.map((s) => ({ label: s.name, value: s.id }));
+    filteredOptions.value = baseOptions.value;
+  } catch (e) {
+    console.error(e);
+  } finally {
+    loading.value = false;
+  }
+});
+</script>