Sfoglia il codice sorgente

feat: :sparkles: feat (separacao parceiro convenio) foi criada nova tela para separar parceiro e convenio

foi criado um novo item no menu lateral para separar a tela de parceiros e a tela de convenios medicos

fase:dev | origin:escopo
Gustavo Zanatta 2 giorni fa
parent
commit
0cb5022dd8

+ 4 - 2
src/api/partnerAgreement.js

@@ -1,7 +1,9 @@
 import api from "src/api";
 
-export const getPartnerAgreements = async () => {
-  const { data } = await api.get("/associado-partner-agreement");
+export const getPartnerAgreements = async ({ type } = {}) => {
+  const params = {};
+  if (type) params.type = type;
+  const { data } = await api.get("/associado-partner-agreement", { params });
   return data.payload;
 };
 

+ 5 - 2
src/i18n/locales/en.json

@@ -11,7 +11,10 @@
         "description": "Your digital membership card with QR Code"
       },
       "convenios": {
-        "description": "Browse available partners and agreements"
+        "description": "Browse available agreements"
+      },
+      "parceiros": {
+        "description": "Browse available partners"
       },
       "loja": {
         "description": "Browse available store items"
@@ -411,7 +414,7 @@
       "state": "State",
       "country": "Country",
       "exit": "Exit",
-      "partners": "Partners/Agreements",
+      "partners": "Partners",
       "partner_agreements": "Agreements",
       "partner_services": "Services",
       "store": "Store",

+ 5 - 2
src/i18n/locales/es.json

@@ -11,7 +11,10 @@
         "description": "Su tarjeta digital con código QR de identificación"
       },
       "convenios": {
-        "description": "Consulte los socios y convenios disponibles"
+        "description": "Consulte los convenios disponibles"
+      },
+      "parceiros": {
+        "description": "Consulte los socios disponibles"
       },
       "loja": {
         "description": "Consulte los artículos disponibles en la tienda"
@@ -411,7 +414,7 @@
       "state": "Estado/Provincia",
       "country": "País",
       "exit": "Salir",
-      "partners": "Socios/Convenios",
+      "partners": "Socios",
       "partner_agreements": "Convenios",
       "partner_services": "Servicios",
       "store": "Tienda",

+ 5 - 2
src/i18n/locales/pt.json

@@ -11,7 +11,10 @@
         "description": "Sua carteira digital com QR Code de identificação"
       },
       "convenios": {
-        "description": "Confira os parceiros e convênios disponíveis para você"
+        "description": "Confira os convênios disponíveis para você"
+      },
+      "parceiros": {
+        "description": "Confira os parceiros disponíveis para você"
       },
       "loja": {
         "description": "Confira os itens disponíveis na loja"
@@ -411,7 +414,7 @@
       "state": "Estados",
       "country": "Países",
       "exit": "Sair",
-      "partners": "Parceiros/Convênios",
+      "partners": "Parceiros",
       "partner_agreements": "Convênios",
       "partner_services": "Serviços",
       "store": "Loja",

+ 2 - 2
src/pages/associado/convenios/ConveniosPage.vue

@@ -89,8 +89,8 @@ const filteredPartners = computed(() => {
 onMounted(async () => {
   try {
     const [partners, cats] = await Promise.all([
-      getPartnerAgreements(),
-      getCategories("partner"),
+      getPartnerAgreements({ type: "agreement" }),
+      getCategories("agreement"),
     ]);
     allPartners.value = partners;
     categories.value = cats;

+ 158 - 0
src/pages/associado/convenios/ParceirosPage.vue

@@ -0,0 +1,158 @@
+<template>
+  <div class="parceiros-page">
+    <DefaultHeaderPage class="q-mx-md"/>
+
+    <div class="q-pb-sm q-ma-md">
+      <q-input
+        v-model="searchQuery"
+        outlined
+        dense
+        bg-color="white"
+        :placeholder="$t('parceiro.search_placeholder')"
+        clearable
+        class="parceiros-page__search-input"
+      >
+        <template #prepend>
+          <q-icon name="mdi-magnify" />
+        </template>
+      </q-input>
+    </div>
+
+    <div class="chips-scroll q-ma-md">
+      <div
+        :class="['cat-chip', activeCategory === 'all' ? 'cat-chip--selected' : 'cat-chip--default']"
+        @click="activeCategory = 'all'"
+      >
+        {{ $t('common.terms.all') }}
+      </div>
+      <div
+        v-for="cat in categories"
+        :key="cat.id"
+        :class="['cat-chip', activeCategory === String(cat.id) ? 'cat-chip--selected' : 'cat-chip--default']"
+        @click="activeCategory = String(cat.id)"
+      >
+        {{ cat.name }}
+      </div>
+    </div>
+
+    <div v-if="loading" class="flex flex-center q-pa-xl q-ma-md">
+      <q-spinner color="violet-normal" size="50px" />
+    </div>
+
+    <div v-else-if="filteredPartners.length === 0" class="flex flex-center q-pa-xl text-grey-6 q-ma-md">
+      {{ $t("http.errors.no_records_found") }}
+    </div>
+
+    <div v-else class="cards-column q-ma-md">
+      <PartnerAgreementCard
+        v-for="partner in filteredPartners"
+        :key="partner.id"
+        :partner="partner"
+        :editable="false"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from "vue";
+import { getPartnerAgreements } from "src/api/partnerAgreement";
+import { getCategories } from "src/api/category";
+import { normalizeString } from "src/helpers/utils";
+import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
+import PartnerAgreementCard from "./components/PartnerAgreementCard.vue";
+
+const loading = ref(true);
+const allPartners = ref([]);
+const categories = ref([]);
+const activeCategory = ref("all");
+const searchQuery = ref("");
+
+const filteredPartners = computed(() => {
+  let list = allPartners.value;
+
+  if (activeCategory.value !== "all") {
+    list = list.filter((p) => String(p.category_id) === activeCategory.value);
+  }
+
+  if (searchQuery.value) {
+    const needle = normalizeString(searchQuery.value);
+    list = list.filter((p) => {
+      const fields = [p.company_name, p.cnpj, p.responsible, p.email, p.phone, p.category?.name, p.address, p.city?.name];
+      return fields.some((f) => f && normalizeString(String(f)).includes(needle));
+    });
+  }
+
+  return list;
+});
+
+onMounted(async () => {
+  try {
+    const [partners, cats] = await Promise.all([
+      getPartnerAgreements({ type: "partner" }),
+      getCategories("partner"),
+    ]);
+    allPartners.value = partners;
+    categories.value = cats;
+  } finally {
+    loading.value = false;
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+@use "src/css/quasar.variables.scss" as vars;
+
+.parceiros-page {
+  background: vars.$violet-light;
+  min-height: calc(100dvh - 68px);
+  box-sizing: border-box;
+  overflow-x: hidden;
+  max-width: 100vw;
+  width: 100%;
+  padding-bottom: 16px;
+}
+
+.parceiros-page__search-input {
+  max-width: 700px;
+  width: 100%;
+}
+
+.chips-scroll {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+
+.cat-chip {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  height: 28px;
+  padding: 0 12px;
+  border-radius: 5px;
+  font-size: 12px;
+  font-weight: 500;
+  cursor: pointer;
+  user-select: none;
+  white-space: nowrap;
+  transition: background 0.15s, color 0.15s;
+}
+
+.cat-chip--default {
+  background: #c9a3dc;
+  color: #fff;
+}
+
+.cat-chip--selected {
+  background: #4d1658;
+  color: #fff;
+}
+
+.cards-column {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+}
+</style>

+ 11 - 0
src/router/routes/associado.route.js

@@ -10,6 +10,17 @@ export default [
       breadcrumbs: [{ name: "MeuPerfilPage", title: "ui.navigation.meu_perfil", translate: true }],
     },
   },
+  {
+    path: "/associado/parceiros",
+    name: "ParceirosPage",
+    component: () => import("pages/associado/convenios/ParceirosPage.vue"),
+    meta: {
+      title: { value: "ui.navigation.partners", translate: true },
+      description: { value: "page.associado.parceiros.description", translate: true },
+      requireAuth: true,
+      breadcrumbs: [{ name: "ParceirosPage", title: "ui.navigation.partners", translate: true }],
+    },
+  },
   {
     path: "/associado/convenios",
     name: "ConveniosPage",

+ 10 - 1
src/stores/navigation.js

@@ -22,11 +22,20 @@ export const navigationStore = defineStore("navigation", () => {
       permission: false,
       permissionScope: "associado.perfil",
     },
+    {
+      type: "single",
+      title: "ui.navigation.partners",
+      name: "ParceirosPage",
+      icon: "mdi-handshake-outline",
+      disable: false,
+      permission: false,
+      permissionScope: "associado.convenio",
+    },
     {
       type: "single",
       title: "ui.navigation.convenios",
       name: "ConveniosPage",
-      icon: "mdi-handshake-outline",
+      icon: "mdi-hospital-box-outline",
       disable: false,
       permission: false,
       permissionScope: "associado.convenio",