فهرست منبع

feat: cria a tab de billings

ebagabee 1 ماه پیش
والد
کامیت
a3150a27bb
3فایلهای تغییر یافته به همراه203 افزوده شده و 10 حذف شده
  1. 10 4
      src/components/defaults/DefaultTable.vue
  2. 85 0
      src/pages/tbr/components/GenerateBillingsDialog.vue
  3. 108 6
      src/pages/tbr/tabs/BillingsTab.vue

+ 10 - 4
src/components/defaults/DefaultTable.vue

@@ -34,12 +34,13 @@
         <q-btn
           v-if="addItem"
           color="primary"
-          style="width: 40px; height: 40px"
-          icon="mdi-plus"
+          :style="addItemLabel ? '' : 'width: 40px; height: 40px'"
+          :icon="addItemLabel ? undefined : 'mdi-plus'"
+          :label="addItemLabel || undefined"
           :outline="outlineAdd"
+          unelevated
           @click="onAddItem"
-        >
-        </q-btn>
+        />
       </div>
 
       <div class="flex full-width align-center q-mb-md" style="gap: 1rem">
@@ -189,6 +190,7 @@ const {
   openItem,
   openItemRoute,
   addItem,
+  addItemLabel,
   addItemRoute,
   rowsPerPage,
   showSearchField,
@@ -232,6 +234,10 @@ const {
     type: Boolean,
     default: false,
   },
+  addItemLabel: {
+    type: String,
+    default: "",
+  },
   addItemRoute: {
     type: String,
     default: "",

+ 85 - 0
src/pages/tbr/components/GenerateBillingsDialog.vue

@@ -0,0 +1,85 @@
+<template>
+  <q-dialog ref="dialogRef" @hide="onDialogHide">
+    <q-card class="q-dialog-plugin overflow-hidden" style="width: 100%; max-width: 400px">
+      <DefaultDialogHeader :title="() => 'Mês de Cobrança'" @close="onDialogCancel" />
+
+      <q-form ref="formRef" @submit="onGenerate">
+        <q-card-section class="q-pt-none">
+          <DefaultInput
+            v-model="monthDisplay"
+            label="Mês"
+            outlined
+            readonly
+            clearable
+            :rules="[inputRules.required]"
+            @clear="onClearMonth"
+          >
+            <template #append>
+              <q-icon name="mdi-calendar" class="cursor-pointer">
+                <q-popup-proxy cover transition-show="scale" transition-hide="scale">
+                  <q-date
+                    v-model="month"
+                    mask="MM/YYYY"
+                    emit-immediately
+                    default-view="Months"
+                    @update:model-value="onMonthSelect"
+                  >
+                    <div class="row items-center justify-end">
+                      <q-btn v-close-popup label="OK" color="primary" flat />
+                    </div>
+                  </q-date>
+                </q-popup-proxy>
+              </q-icon>
+            </template>
+          </DefaultInput>
+        </q-card-section>
+
+        <q-card-actions>
+          <q-space />
+          <q-btn outline label="Cancelar" @click="onDialogCancel" />
+          <q-btn
+            color="primary-2"
+            label="Gerar"
+            type="submit"
+            :loading="loading"
+          />
+        </q-card-actions>
+      </q-form>
+    </q-card>
+  </q-dialog>
+</template>
+
+<script setup>
+import { ref } from "vue";
+import { useDialogPluginComponent } from "quasar";
+import { useInputRules } from "src/composables/useInputRules";
+import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
+import DefaultInput from "src/components/defaults/DefaultInput.vue";
+
+defineEmits([...useDialogPluginComponent.emits]);
+
+const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
+  useDialogPluginComponent();
+
+const { inputRules } = useInputRules();
+
+const formRef = ref(null);
+const loading = ref(false);
+const month = ref(null);
+const monthDisplay = ref(null);
+
+function onMonthSelect(value) {
+  if (!value) return;
+  monthDisplay.value = value;
+}
+
+function onClearMonth() {
+  month.value = null;
+  monthDisplay.value = null;
+}
+
+async function onGenerate() {
+  // TODO: call generate billings API with month.value (MM/YYYY)
+  onDialogOK({ month: month.value });
+}
+</script>

+ 108 - 6
src/pages/tbr/tabs/BillingsTab.vue

@@ -1,8 +1,110 @@
-<script setup>
-</script>
-
 <template>
-  <div>
-    <h6>Ver Cobranças Geradas</h6>
-  </div>
+  <DefaultTable
+    v-model:rows="rows"
+    :columns="columns"
+    :no-api-call="true"
+    :show-search-field="true"
+    :add-item="true"
+    add-item-label="Gerar Cobranças"
+    @on-add-item="onAddItem"
+  >
+    <template #top>
+      <DefaultInput
+        v-model="monthYearDisplay"
+        label="Filtrar Mês e Ano"
+        dense
+        readonly
+        clearable
+        style="min-width: 180px"
+        @clear="onClearMonthYear"
+      >
+        <template #append>
+          <q-icon name="mdi-calendar" class="cursor-pointer">
+            <q-popup-proxy cover transition-show="scale" transition-hide="scale">
+              <q-date
+                v-model="monthYear"
+                mask="MM/YYYY"
+                emit-immediately
+                default-view="Months"
+                @update:model-value="onMonthYearSelect"
+              >
+                <div class="row items-center justify-end">
+                  <q-btn v-close-popup label="OK" color="primary" flat />
+                </div>
+              </q-date>
+            </q-popup-proxy>
+          </q-icon>
+        </template>
+      </DefaultInput>
+    </template>
+
+    <template #body-cell-tbr_value="{ row }">
+      <q-td>{{ formatToBRLCurrency(row.tbr_value) }}</q-td>
+    </template>
+
+    <template #body-cell-royalties_value="{ row }">
+      <q-td>{{ formatToBRLCurrency(row.royalties_value) }}</q-td>
+    </template>
+
+    <template #body-cell-fnm_value="{ row }">
+      <q-td>{{ formatToBRLCurrency(row.fnm_value) }}</q-td>
+    </template>
+
+    <template #body-cell-maintenance_value="{ row }">
+      <q-td>{{ formatToBRLCurrency(row.maintenance_value) }}</q-td>
+    </template>
+
+    <template #body-cell-total="{ row }">
+      <q-td>{{ formatToBRLCurrency(row.total) }}</q-td>
+    </template>
+
+    <template #body-cell-actions>
+      <q-td align="center">
+        <q-btn flat round dense icon="mdi-eye-outline" size="sm" />
+      </q-td>
+    </template>
+  </DefaultTable>
 </template>
+
+<script setup>
+import { ref } from "vue";
+import { useQuasar } from "quasar";
+import DefaultTable from "src/components/defaults/DefaultTable.vue";
+import DefaultInput from "src/components/defaults/DefaultInput.vue";
+import GenerateBillingsDialog from "src/pages/tbr/components/GenerateBillingsDialog.vue";
+import { formatToBRLCurrency } from "src/helpers/utils";
+
+const $q = useQuasar();
+const rows = ref([]);
+const monthYear = ref(null);
+const monthYearDisplay = ref(null);
+
+const columns = [
+  { name: "id", label: "ID", field: "id", align: "left" },
+  { name: "unit_name", label: "Unidade", field: "unit_name", align: "left" },
+  { name: "tbr_value", label: "TBR", field: "tbr_value", align: "left" },
+  { name: "royalties_value", label: "Royalties", field: "royalties_value", align: "left" },
+  { name: "royalties_rule", label: "Regra", field: "royalties_rule", align: "left" },
+  { name: "fnm_value", label: "FNM", field: "fnm_value", align: "left" },
+  { name: "fnm_rule", label: "Regra", field: "fnm_rule", align: "left" },
+  { name: "maintenance_value", label: "Manutenção", field: "maintenance_value", align: "left" },
+  { name: "total", label: "Total", field: "total", align: "left" },
+  { name: "actions", label: "Ações", field: "actions", align: "center" },
+];
+
+function onMonthYearSelect(value) {
+  if (!value) return;
+  monthYearDisplay.value = value;
+}
+
+function onClearMonthYear() {
+  monthYear.value = null;
+  monthYearDisplay.value = null;
+}
+
+function onAddItem() {
+  $q.dialog({ component: GenerateBillingsDialog }).onOk(() => {
+    // TODO: reload billings after generation
+  });
+}
+</script>