Files
crewli/apps/app/src/App.vue
bert.hausmans f5a9e491ce feat(primevue): add Icon component and mount Toast + ConfirmDialog services
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>
2026-05-11 01:06:11 +02:00

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>