Просмотр исходного кода

feat(DefaultHeaderPage): enhance user profile and settings menu with dynamic data

ebagabee 3 недель назад
Родитель
Сommit
418d412dea
1 измененных файлов с 140 добавлено и 2 удалено
  1. 140 2
      src/components/layout/DefaultHeaderPage.vue

+ 140 - 2
src/components/layout/DefaultHeaderPage.vue

@@ -169,8 +169,104 @@
                 </div>
               </q-menu>
             </q-btn>
-            <q-btn flat round dense icon="mdi-account" color="secondary" />
-            <q-btn flat round dense icon="mdi-cog-outline" color="secondary" />
+
+            <!-- Perfil do usuário -->
+            <q-btn flat round dense icon="mdi-account" color="secondary">
+              <q-menu
+                anchor="bottom right"
+                self="top right"
+                :offset="[0, 8]"
+                class="header-menu"
+              >
+                <div class="profile-panel q-pa-md">
+                  <div class="row items-center no-wrap q-gutter-x-md">
+                    <q-img
+                      :src="user?.avatar_url || 'icons/user-icon.jpg'"
+                      class="avatar-circle"
+                    />
+                    <div class="column" style="min-width: 0">
+                      <span class="text-body2 text-primary text-weight-medium ellipsis">
+                        {{ user?.name || "Usuário" }}
+                      </span>
+                      <span class="text-caption text-grey-6 ellipsis">
+                        {{ user?.email }}
+                      </span>
+                    </div>
+                  </div>
+                  <q-separator class="q-my-md" />
+                  <q-btn
+                    v-close-popup
+                    flat
+                    no-caps
+                    align="left"
+                    class="full-width"
+                    color="primary"
+                    icon="mdi-account-edit-outline"
+                    label="Editar perfil"
+                    @click="goToEditProfile"
+                  />
+                </div>
+              </q-menu>
+            </q-btn>
+
+            <!-- Configurações -->
+            <q-btn flat round dense icon="mdi-cog-outline" color="secondary">
+              <q-menu
+                anchor="bottom right"
+                self="top right"
+                :offset="[0, 8]"
+                class="header-menu"
+                @before-show="loadUnitDetails"
+              >
+                <div class="settings-panel q-pa-md">
+                  <div class="column q-gutter-y-sm">
+                    <div>
+                      <span class="text-caption text-grey-6">Nome fantasia</span>
+                      <div class="text-body2 text-primary text-weight-medium ellipsis">
+                        {{ unitInfo.fantasy_name || "Não informado" }}
+                      </div>
+                    </div>
+                    <div>
+                      <span class="text-caption text-grey-6">Razão social</span>
+                      <div class="text-body2 text-primary text-weight-medium ellipsis">
+                        {{ unitInfo.social_reason || "Não informado" }}
+                      </div>
+                    </div>
+                    <div>
+                      <span class="text-caption text-grey-6">Responsável pela unidade</span>
+                      <div class="text-body2 text-primary text-weight-medium ellipsis">
+                        {{ unitInfo.name_responsible || "Não informado" }}
+                      </div>
+                    </div>
+                  </div>
+
+                  <q-separator class="q-my-md" />
+
+                  <q-btn
+                    v-close-popup
+                    flat
+                    no-caps
+                    align="left"
+                    class="full-width"
+                    color="primary"
+                    icon="mdi-store-edit-outline"
+                    label="Editar unidade"
+                    @click="goToEditUnit"
+                  />
+                  <q-btn
+                    v-close-popup
+                    flat
+                    no-caps
+                    align="left"
+                    class="full-width q-mt-xs"
+                    color="negative"
+                    icon="mdi-logout"
+                    label="Sair"
+                    @click="logoutFn"
+                  />
+                </div>
+              </q-menu>
+            </q-btn>
           </div>
         </div>
       </div>
@@ -184,7 +280,9 @@ import { computed, ref, watch, onMounted, onBeforeUnmount } from "vue";
 import { useRoute, useRouter } from "vue-router";
 import { useI18n } from "vue-i18n";
 import { userStore } from "src/stores/user";
+import { useAuth } from "src/composables/useAuth";
 import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
+import { getUnitMe } from "src/api/unit";
 import {
   getMyNotifications,
   getUnreadCount,
@@ -212,8 +310,12 @@ const route = useRoute();
 const router = useRouter();
 const { t } = useI18n();
 const store = userStore();
+const { logout } = useAuth();
 
 const userUnits = computed(() => store.user?.units ?? []);
+const user = computed(() => store.user);
+const unitDetails = ref(null);
+const unitInfo = computed(() => unitDetails.value || store.selectedUnit || {});
 
 // ------------------- Notificações (sino) -------------------
 const notifications = ref([]);
@@ -335,6 +437,29 @@ const lastLoginFormatted = computed(() => {
   }).format(d);
 });
 
+const loadUnitDetails = async () => {
+  try {
+    unitDetails.value = await getUnitMe();
+  } catch (e) {
+    unitDetails.value = store.selectedUnit;
+    console.error("Falha ao carregar dados da unidade:", e);
+  }
+};
+
+const goToEditProfile = () => {
+  if (!user.value?.id) return;
+  router.push({ name: "UserEditPage", params: { id: user.value.id } });
+};
+
+const goToEditUnit = () => {
+  router.push({ name: "UnitDataPage" });
+};
+
+const logoutFn = async () => {
+  await logout();
+  router.push({ name: "LoginPage" });
+};
+
 const displayTitle = computed(() => {
   if (title) {
     if (typeof title === "string") return title;
@@ -387,4 +512,17 @@ const displayBreadcrumbs = computed(() => {
   width: 340px;
   max-width: 90vw;
 }
+
+.avatar-circle {
+  width: 36px;
+  height: 36px;
+  border-radius: 50%;
+  flex-shrink: 0;
+}
+
+.profile-panel,
+.settings-panel {
+  width: 280px;
+  max-width: 90vw;
+}
 </style>