Application Laravel 12 + Inertia + Vue 3 + Tailwind. Fonctionnalités : dashboard glycémique, saisie de mesures, courbe SVG, statistiques (jour/semaine/mois/trimestre), défis & badges, chat coach IA (Gemini), paramètres profil avec palette de couleurs, pages auth redessinées, emails transactionnels via Resend avec thème Diabetix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
71 lines
3.0 KiB
Vue
71 lines
3.0 KiB
Vue
<script setup>
|
||
import { computed, ref } from 'vue';
|
||
import { Link, router, usePage } from '@inertiajs/vue3';
|
||
import { tokens, FONT } from '@/Components/Diabetix/palette.js';
|
||
import InputModal from '@/Components/Diabetix/InputModal.vue';
|
||
|
||
const page = usePage();
|
||
const palette = computed(() => page.props.auth.user?.palette ?? 'mint');
|
||
const tok = computed(() => tokens(palette.value));
|
||
const font = FONT;
|
||
|
||
const inputOpen = ref(false);
|
||
|
||
const items = [
|
||
{ name: 'dashboard', label: 'Accueil', icon: '🏠' },
|
||
{ name: 'stats', label: 'Stats', icon: '📊' },
|
||
{ name: 'add', label: '', icon: '+' },
|
||
{ name: 'challenges', label: 'Défis', icon: '🏆' },
|
||
{ name: 'chat', label: 'Coach', icon: '🤖' },
|
||
];
|
||
|
||
const user = computed(() => page.props.auth.user);
|
||
|
||
function go(name) {
|
||
if (name === 'add') {
|
||
inputOpen.value = true;
|
||
return;
|
||
}
|
||
router.visit(route(name));
|
||
}
|
||
|
||
function active(name) {
|
||
return route().current(name);
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div :style="{ minHeight: '100vh', background: '#eeece8', fontFamily: font.body, color: tok.text }">
|
||
<div :style="{ maxWidth: '440px', margin: '0 auto', minHeight: '100vh', background: tok.bg, position: 'relative', boxShadow: '0 0 60px rgba(0,0,0,0.04)', display: 'flex', flexDirection: 'column' }">
|
||
<main style="flex:1;padding-bottom:78px;">
|
||
<slot :tok="tok" :font="font" :open-input="() => inputOpen = true" />
|
||
</main>
|
||
|
||
<nav :style="{
|
||
position: 'fixed', bottom: 0, left: '50%', transform: 'translateX(-50%)',
|
||
width: '100%', maxWidth: '440px',
|
||
background: tok.white, borderTop: '1px solid ' + tok.border,
|
||
display: 'flex', justifyContent: 'space-around', alignItems: 'center',
|
||
padding: '8px 0 14px', zIndex: 30,
|
||
}">
|
||
<button v-for="it in items" :key="it.name" @click="go(it.name)"
|
||
:style="{
|
||
flex: 1, background: 'none', border: 'none', cursor: 'pointer',
|
||
display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '2px',
|
||
color: active(it.name) ? tok.primary : tok.muted,
|
||
}">
|
||
<span v-if="it.name !== 'add'" style="font-size:20px;line-height:1;">{{ it.icon }}</span>
|
||
<span v-else :style="{
|
||
width: '46px', height: '46px', borderRadius: '50%', background: tok.primary, color: '#fff',
|
||
display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '26px', marginTop: '-22px',
|
||
boxShadow: '0 6px 18px rgba(123,191,181,0.45)', fontWeight: 600,
|
||
}">+</span>
|
||
<span v-if="it.label" style="font-size:10px;font-weight:500;">{{ it.label }}</span>
|
||
</button>
|
||
</nav>
|
||
|
||
<InputModal v-if="inputOpen" :tok="tok" :font="font" @close="inputOpen = false" />
|
||
</div>
|
||
</div>
|
||
</template>
|