Переглянути джерело

feat: add unit selector to DefaultHeaderPage

- Show DefaultSelect when user has more than one unit
- Loading spinner appears briefly after unit change
- Fix null slot scope crash in DefaultSelect slot forwarding
ebagabee 2 тижнів тому
батько
коміт
d13bb48068

+ 1 - 1
src/components/defaults/DefaultSelect.vue

@@ -19,7 +19,7 @@
         @update:model-value="error = null"
       >
         <template v-for="(_, slotName) in $slots" #[slotName]="scope">
-          <slot :name="slotName" v-bind="scope" />
+          <slot :name="slotName" v-bind="scope ?? {}" />
         </template>
 
         <template #append>

+ 41 - 1
src/components/layout/DefaultHeaderPage.vue

@@ -41,6 +41,26 @@
         <slot name="after" />
 
         <div class="flex items-center no-wrap" style="gap: 12px">
+          <!-- Seletor de unidade: aparece apenas quando o usuário tem mais de uma -->
+          <template v-if="userUnits.length > 1">
+            <DefaultSelect
+              :model-value="store.selectedUnit"
+              :options="userUnits"
+              option-value="id"
+              option-label="fantasy_name"
+              label="Unidade"
+              outlined
+              style="width: 280px; flex-shrink: 0"
+              @update:model-value="store.setSelectedUnit"
+            />
+            <q-spinner
+              v-if="isUnitLoading"
+              color="primary"
+              size="18px"
+              style="flex-shrink: 0"
+            />
+          </template>
+
           <template v-if="$q.screen.gt.sm && lastLoginFormatted">
             <div
               class="column"
@@ -71,10 +91,11 @@
 </template>
 
 <script setup>
-import { computed } from "vue";
+import { computed, ref, watch } from "vue";
 import { useRoute } from "vue-router";
 import { useI18n } from "vue-i18n";
 import { userStore } from "src/stores/user";
+import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
 
 const { breadcrumbs, showFilterIcon, title } = defineProps({
   breadcrumbs: {
@@ -95,6 +116,24 @@ const route = useRoute();
 const { t } = useI18n();
 const store = userStore();
 
+const userUnits = computed(() => store.user?.units ?? []);
+
+const isUnitLoading = ref(false);
+let loadingTimer = null;
+
+watch(
+  () => store.selectedUnit?.id,
+  (newId, oldId) => {
+    if (newId && oldId !== undefined && newId !== oldId) {
+      isUnitLoading.value = true;
+      clearTimeout(loadingTimer);
+      loadingTimer = setTimeout(() => {
+        isUnitLoading.value = false;
+      }, 1500);
+    }
+  },
+);
+
 const lastLoginFormatted = computed(() => {
   const raw = store.user?.last_login_at;
   if (!raw) return null;
@@ -152,4 +191,5 @@ const displayBreadcrumbs = computed(() => {
 .default-header-page :deep(.q-breadcrumbs__el) {
   max-width: max-content;
 }
+
 </style>