Hello from MCP server

List Files | Just Commands | Repo | Logs

← back |
<template>
  <ion-app>
    <ion-menu side="start" menu-id="main-menu" content-id="main-content">
      <ion-header>
        <ion-toolbar>
          <div class="menu-header">
            <img
              :src="customLogo || '/images/branding-dark.png'"
              alt="The New Flat Rate"
              class="branding-logo"
            />
          </div>
        </ion-toolbar>
      </ion-header>
      <ion-content>
        <div class="menu-content">
          <ion-list class="menu-list">
            <ion-menu-toggle>
              <ion-item button @click="navigateTo('/review')">
                <ion-icon :icon="briefcaseOutline" slot="start" color="primary" />
                <ion-label>Work Orders</ion-label>
              </ion-item>
            </ion-menu-toggle>
            <ion-menu-toggle>
              <ion-item button @click="navigateTo('/training-lab')">
                <ion-icon :icon="schoolOutline" slot="start" color="primary" />
                <ion-label>Training Lab</ion-label>
              </ion-item>
            </ion-menu-toggle>
            <ion-menu-toggle>
              <ion-item button @click="navigateTo('/presentation-scripts')">
                <ion-icon :icon="documentTextOutline" slot="start" color="primary" />
                <ion-label>Presentation Scripts</ion-label>
              </ion-item>
            </ion-menu-toggle>
            <ion-menu-toggle>
              <ion-item button @click="navigateTo('/terminology-guides')">
                <ion-icon :icon="bookOutline" slot="start" color="primary" />
                <ion-label>Terminology Guides</ion-label>
              </ion-item>
            </ion-menu-toggle>
            <ion-menu-toggle>
              <ion-item button @click="resetCart">
                <ion-icon :icon="refreshOutline" slot="start" color="primary" />
                <ion-label>Reset Cart</ion-label>
              </ion-item>
            </ion-menu-toggle>
            <ion-menu-toggle>
              <ion-item button @click="navigateTo('/profile')">
                <ion-icon :icon="personOutline" slot="start" color="primary" />
                <ion-label>Profile</ion-label>
              </ion-item>
            </ion-menu-toggle>
            <ion-menu-toggle>
              <ion-item button @click="navigateTo('/settings')">
                <ion-icon :icon="settingsOutline" slot="start" color="primary" />
                <ion-label>Settings</ion-label>
              </ion-item>
            </ion-menu-toggle>
            <ion-menu-toggle>
              <ion-item button @click="navigateTo('/auth/logout')">
                <ion-icon :icon="logOutOutline" slot="start" color="primary" />
                <ion-label>Logout</ion-label>
              </ion-item>
            </ion-menu-toggle>
          </ion-list>
          <div class="menu-version">
            {{ appVersion }}
          </div>
        </div>
      </ion-content>
    </ion-menu>

    <ion-router-outlet id="main-content" />

    <!-- Global Bulk Upload Modal (Secret Mode) -->
    <BulkUploadModal />
  </ion-app>
</template>

<script setup lang="ts">
import { onMounted, ref, computed } from "vue";
import {
  IonApp,
  IonContent,
  IonHeader,
  IonIcon,
  IonItem,
  IonLabel,
  IonList,
  IonMenu,
  IonMenuToggle,
  IonRouterOutlet,
  IonTitle,
  IonToolbar,
} from "@ionic/vue";
import {
  briefcaseOutline,
  logOutOutline,
  personOutline,
  settingsOutline,
  schoolOutline,
  documentTextOutline,
  bookOutline,
  refreshOutline,
} from "ionicons/icons";
import { useRouter } from "vue-router";
import { useTheme } from "@/composables/useTheme";
import { useLogo } from "@/composables/useLogo";
import { useSessionStore } from "@/stores/session";
import { usePreferencesStore } from "@/stores/preferences";
import { useTnfrStore } from "@/stores/tnfr";
import BulkUploadModal from "@/components/BulkUploadModal.vue";

const router = useRouter();
const { loadTheme } = useTheme();
const { logo, loadLogos } = useLogo();
const sessionStore = useSessionStore();
const preferences = usePreferencesStore();
const tnfrStore = useTnfrStore();

// Use computed to reactively get the logo
const customLogo = computed(() => logo.value);

// App version from environment
const appVersion = import.meta.env.VITE_APP_VERSION || 'Development';

const navigateTo = (path: string) => {
  router.push(path);
};

const resetCart = () => {
  // Clear the cart/tnfr store and navigate to directory
  tnfrStore.clear();
  router.push('/directory');
};

onMounted(async () => {
  console.log('[App] Loading preferences...');
  // Load preferences first so theme can be loaded from them
  await preferences.getPreferences();

  console.log('[App] Loading session data...');
  // Load session data which includes theme colors
  await sessionStore.load();

  console.log('[App] Loading theme...');
  // Apply saved theme or default theme
  await loadTheme();

  console.log('[App] Loading logos...');
  // Load custom logos from IndexedDB
  await loadLogos();

  console.log('[App] App initialization complete');
});
</script>

<style scoped>
.menu-content {
  display: flex;
  flex-direction: column;
  height: 100%;
  /* Remove min-height: 100vh; */
}

.menu-list {
  flex: 1;
  /* Ensure the list doesn't create its own scroll */
  overflow: visible;
}

/* Ensure ion-content doesn't scroll */
ion-content {
  --overflow: hidden;
}

.menu-header {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 16px 12px;
}

.branding-logo {
  max-width: 100%;
  height: auto;
  max-height: 50px;
}

.menu-version {
  padding: 16px;
  text-align: center;
  font-size: 12px;
  color: var(--ion-color-medium);
  margin-top: auto;
}
</style>