port-nimara-client-portal/components/PWAInstallBanner.vue

196 lines
5.2 KiB
Vue

<template>
<v-slide-y-transition>
<v-card
v-if="showBanner"
class="mt-4 mx-auto"
max-width="350"
elevation="2"
rounded
>
<v-card-text class="pa-4">
<v-row align="center" no-gutters>
<v-col cols="auto" class="mr-3">
<v-img
src="/Port_Nimara_Logo_2_Colour_New_Transparent.png"
width="48"
height="48"
class="rounded-circle"
/>
</v-col>
<v-col>
<div class="text-body-2 font-weight-medium mb-1">
Install Port Nimara Portal
</div>
<div class="text-caption text-grey-darken-1">
Get faster access and work offline
</div>
</v-col>
<v-col cols="auto">
<v-btn
icon="mdi-close"
variant="text"
size="small"
@click="dismissBanner"
/>
</v-col>
</v-row>
<v-row class="mt-3" no-gutters>
<v-col>
<v-btn
color="primary"
variant="tonal"
size="small"
block
@click="installApp"
:loading="installing"
>
<v-icon left>mdi-download</v-icon>
Install App
</v-btn>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-slide-y-transition>
<!-- Installation Instructions Dialog -->
<v-dialog v-model="showInstructions" max-width="400">
<v-card>
<v-card-title class="d-flex align-center">
<v-img
src="/Port_Nimara_Logo_2_Colour_New_Transparent.png"
width="32"
height="32"
class="rounded-circle mr-2"
/>
Install Port Nimara Portal
</v-card-title>
<v-divider />
<v-card-text class="pa-4">
<div v-if="isIOS">
<div class="text-body-2 mb-3">
To install this app on your iPhone/iPad:
</div>
<v-list density="compact">
<v-list-item prepend-icon="mdi-share-variant">
<v-list-item-title class="text-body-2">
Tap the <strong>Share</strong> button at the bottom
</v-list-item-title>
</v-list-item>
<v-list-item prepend-icon="mdi-plus-box">
<v-list-item-title class="text-body-2">
Scroll down and tap <strong>"Add to Home Screen"</strong>
</v-list-item-title>
</v-list-item>
<v-list-item prepend-icon="mdi-check">
<v-list-item-title class="text-body-2">
Tap <strong>"Add"</strong> to confirm
</v-list-item-title>
</v-list-item>
</v-list>
<v-alert type="info" variant="tonal" class="mt-3">
<div class="text-caption">
Make sure you're using Safari browser for this to work.
</div>
</v-alert>
</div>
<div v-else>
<div class="text-body-2 mb-3">
Your browser doesn't support automatic installation.
</div>
<div class="text-caption text-grey-darken-1">
Try using Chrome or another modern browser for the best experience.
</div>
</div>
</v-card-text>
<v-divider />
<v-card-actions>
<v-spacer />
<v-btn @click="showInstructions = false" variant="text">
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
const { isInstalled, isMobile, isIOS, canInstall, install, init } = usePWA();
const showBanner = ref(false);
const showInstructions = ref(false);
const installing = ref(false);
// Check if banner has been dismissed
const wasDismissed = computed(() => {
if (process.client) {
return localStorage.getItem('pwa-install-dismissed') === 'true';
}
return false;
});
// Check if should show banner
const shouldShowBanner = computed(() => {
return canInstall.value && !wasDismissed.value;
});
const dismissBanner = () => {
showBanner.value = false;
if (process.client) {
localStorage.setItem('pwa-install-dismissed', 'true');
}
};
const installApp = async () => {
installing.value = true;
try {
const success = await install();
if (success) {
dismissBanner();
} else if (isIOS.value) {
// iOS - show instructions
showInstructions.value = true;
} else {
// Other platforms - show instructions
showInstructions.value = true;
}
} catch (error) {
console.error('Install failed:', error);
if (isIOS.value) {
showInstructions.value = true;
}
} finally {
installing.value = false;
}
};
onMounted(() => {
if (process.client) {
// Initialize PWA functionality
init();
// Show banner if conditions are met
if (shouldShowBanner.value) {
// Small delay to let the page load
setTimeout(() => {
showBanner.value = true;
}, 1000);
}
// Watch for installation status changes
watch(isInstalled, (newValue) => {
if (newValue) {
dismissBanner();
}
});
}
});
</script>