Two additions complete the F3 runtime scaffolding: apps/app/src/components/Icon.vue — generic Iconify renderer wrapping @iconify/vue's <Icon> component. F4 migration substitutes <VIcon icon="tabler-X" /> with <Icon name="tabler-X" /> at call-sites, producing real SVG output and using the existing Crewli "tabler-*" naming convention. Props: name (required, e.g. "tabler-eye"), optional size. The component avoids @iconify/vue's auto-import for clarity at call-sites. apps/app/src/App.vue — mounts <Toast /> and <ConfirmDialog /> at the template root inside VLocaleProvider. Both render alongside the existing VSnackbar and VDialog confirm patterns during the F3–F4 parallel-mode window. F4 sub-packages migrate call-sites to PrimeVue's useToast() / useConfirm() composables. UnoCSS-style i-tabler-* utility-class rendering (RFC AD-5 v1.0 wording) is not adopted — UnoCSS is not installed in the Crewli stack. The RFC will be aligned in B9. Verification: - pnpm typecheck — clean. - pnpm test — 402 tests pass unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
83 lines
2.4 KiB
Vue
83 lines
2.4 KiB
Vue
<script setup lang="ts">
|
|
import { useTheme } from 'vuetify'
|
|
import Toast from 'primevue/toast'
|
|
import ConfirmDialog from 'primevue/confirmdialog'
|
|
import ScrollToTop from '@core/components/ScrollToTop.vue'
|
|
import initCore from '@core/initCore'
|
|
import { initConfigStore, useConfigStore } from '@core/stores/config'
|
|
import { hexToRgb } from '@core/utils/colorConverter'
|
|
import { useAuthStore } from '@/stores/useAuthStore'
|
|
import { useImpersonationStore } from '@/stores/useImpersonationStore'
|
|
import { useNotificationStore } from '@/stores/useNotificationStore'
|
|
|
|
const { global } = useTheme()
|
|
|
|
initCore()
|
|
initConfigStore()
|
|
|
|
const configStore = useConfigStore()
|
|
const authStore = useAuthStore()
|
|
const impersonationStore = useImpersonationStore()
|
|
const notificationStore = useNotificationStore()
|
|
|
|
// Restore impersonation state and listen for cross-tab sync
|
|
impersonationStore.restoreFromStorage()
|
|
impersonationStore.listenForBroadcasts()
|
|
|
|
// Validate stored token on app startup — must complete before rendering protected content
|
|
authStore.initialize()
|
|
</script>
|
|
|
|
<template>
|
|
<VLocaleProvider :rtl="configStore.isAppRTL">
|
|
<VApp :style="`--v-global-theme-primary: ${hexToRgb(global.current.value.colors.primary)}`">
|
|
<!-- Show loading state while validating auth token -->
|
|
<template v-if="!authStore.isInitialized">
|
|
<div
|
|
class="d-flex align-center justify-center"
|
|
style="min-height: 100vh;"
|
|
>
|
|
<VProgressCircular
|
|
indeterminate
|
|
color="primary"
|
|
size="48"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- Only render app shell after auth is resolved -->
|
|
<template v-else>
|
|
<RouterView />
|
|
<ScrollToTop />
|
|
</template>
|
|
</VApp>
|
|
|
|
<!-- Global notification snackbar -->
|
|
<VSnackbar
|
|
v-model="notificationStore.visible"
|
|
:color="notificationStore.type"
|
|
:timeout="notificationStore.timeout"
|
|
location="top end"
|
|
>
|
|
{{ notificationStore.message }}
|
|
|
|
<template #actions>
|
|
<VBtn
|
|
variant="text"
|
|
@click="notificationStore.hide()"
|
|
>
|
|
Close
|
|
</VBtn>
|
|
</template>
|
|
</VSnackbar>
|
|
|
|
<!--
|
|
PrimeVue overlay services (F3 — parallel-mode with VSnackbar above
|
|
and the legacy VDialog confirm patterns until F4 sub-packages
|
|
migrate call-sites to useToast() and useConfirm()).
|
|
-->
|
|
<Toast />
|
|
<ConfirmDialog />
|
|
</VLocaleProvider>
|
|
</template>
|