Files
Diabetix_v2/app/resources/js/Pages/Diabetix/Home.vue
jeremy bayse 26c6d8031c Initial commit — Diabetix V2
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>
2026-04-29 07:01:41 +02:00

129 lines
7.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { computed } from 'vue';
import { Head, Link, usePage } from '@inertiajs/vue3';
import DiabetixLayout from '@/Layouts/DiabetixLayout.vue';
import ProgressBar from '@/Components/Diabetix/ProgressBar.vue';
import CoachAvatar from '@/Components/Diabetix/CoachAvatar.vue';
import BadgeChip from '@/Components/Diabetix/BadgeChip.vue';
import GlucoseChart from '@/Components/Diabetix/GlucoseChart.vue';
const props = defineProps({
metrics: Object,
day_chart: Array,
challenges: Array,
badges: Array,
});
const page = usePage();
const userName = computed(() => page.props.auth.user?.first_name ?? 'ami');
const latest = computed(() => props.metrics.latest);
const inRange = computed(() => latest.value?.in_range);
</script>
<template>
<Head title="Accueil" />
<DiabetixLayout v-slot="{ tok, font, openInput }">
<!-- Header -->
<div :style="{ background: tok.white, padding: '14px 20px 18px', borderBottom: '1px solid ' + tok.border }">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:14px;">
<CoachAvatar :size="42" :tok="tok" />
<div style="flex:1;">
<div :style="{ fontFamily: font.title, fontSize: '19px', color: tok.text, fontWeight: 600 }">
Bonjour <Link :href="route('profile.edit')" :style="{ color: tok.text, textDecoration: 'none', borderBottom: '1.5px dashed ' + tok.primary }">{{ userName }}</Link> ! 👋
</div>
<div :style="{ fontSize: '11px', color: tok.muted }">Coach IA · En ligne</div>
</div>
<div v-if="latest" :style="{
background: inRange ? tok.light : tok.amberLight,
borderRadius: '14px', padding: '8px 14px', textAlign: 'center',
border: '2px solid ' + (inRange ? tok.primary : tok.amber),
}">
<div :style="{ fontSize: '20px', fontWeight: 800, color: tok.text, lineHeight: 1 }">
{{ latest.value }}
</div>
<div :style="{ fontSize: '9px', color: inRange ? tok.primary : tok.amber, marginTop: '2px' }">
mg/dL {{ inRange ? '✓' : '⚠' }}
</div>
</div>
</div>
<div :style="{ background: tok.light, borderRadius: '16px', padding: '12px 14px' }">
<div :style="{ fontSize: '12px', color: tok.text, lineHeight: 1.6 }">
🤖 Votre glycémie actuelle est
<strong>{{ inRange ? 'dans la cible' : 'à surveiller' }}</strong>.
Essayez une marche de 10 min ce soir je vous rappellerai à 19h30 !
</div>
<button :style="{
marginTop: '10px', padding: '5px 14px', borderRadius: '20px',
background: tok.white, border: '1.5px solid ' + tok.primary,
fontSize: '11px', color: tok.primary, fontWeight: 600, cursor: 'pointer',
}">Ajouter ce défi </button>
</div>
</div>
<div style="padding:14px 20px;display:flex;flex-direction:column;gap:14px;">
<!-- Stats row -->
<div style="display:flex;gap:14px;">
<div :style="{ flex: 1, background: tok.white, borderRadius: '16px', padding: '14px', textAlign: 'center', boxShadow: '0 2px 10px rgba(42,53,51,0.05)' }">
<div :style="{ fontSize: '26px', fontWeight: 800, color: tok.text }">🔥 {{ metrics.streak_days }}</div>
<div :style="{ fontSize: '10px', color: tok.muted, marginTop: '3px' }">jours dans la cible</div>
</div>
<div :style="{ flex: 1, background: tok.white, borderRadius: '16px', padding: '14px', textAlign: 'center', boxShadow: '0 2px 10px rgba(42,53,51,0.05)' }">
<div :style="{ fontSize: '26px', fontWeight: 800, color: tok.primary }">{{ metrics.time_in_range }}%</div>
<div :style="{ fontSize: '10px', color: tok.muted, marginTop: '3px' }">temps dans la cible</div>
</div>
</div>
<!-- Day chart -->
<div :style="{ background: tok.white, borderRadius: '20px', padding: '18px 18px 12px', boxShadow: '0 2px 16px rgba(42,53,51,0.06)' }">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
<div :style="{ fontSize: '13px', fontWeight: 600, color: tok.text }">Aujourd'hui</div>
<Link :href="route('stats')" :style="{ fontSize: '11px', color: tok.primary, textDecoration: 'none' }">Détails →</Link>
</div>
<div v-if="day_chart.length === 0" :style="{ fontSize: '12px', color: tok.muted, textAlign: 'center', padding: '18px 0' }">
Aucune mesure aujourd'hui tapez pour en ajouter une.
</div>
<GlucoseChart v-else :data="day_chart" :tok="tok" :width="316" :height="120" :target-min="metrics.target_min" :target-max="metrics.target_max" />
</div>
<!-- Active challenges -->
<div :style="{ background: tok.white, borderRadius: '20px', padding: '20px', boxShadow: '0 2px 16px rgba(42,53,51,0.06)' }">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;">
<div :style="{ fontSize: '13px', fontWeight: 600, color: tok.text }">Défis actifs</div>
<Link :href="route('challenges')" :style="{ fontSize: '11px', color: tok.primary, textDecoration: 'none' }">Voir tout </Link>
</div>
<div v-if="!challenges.length" :style="{ fontSize: '12px', color: tok.muted }">Aucun défi en cours.</div>
<div v-for="(c, i) in challenges" :key="c.id" :style="{ marginBottom: i < challenges.length - 1 ? '14px' : 0, display: 'flex', alignItems: 'center', gap: '10px' }">
<div style="font-size:24px;">{{ c.icon }}</div>
<div style="flex:1;">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div :style="{ fontSize: '13px', fontWeight: 600, color: tok.text }">{{ c.title }}</div>
<div :style="{ fontSize: '11px', color: tok.amber, fontWeight: 600 }">+{{ c.points }} pts</div>
</div>
<div :style="{ fontSize: '11px', color: tok.muted, marginBottom: '6px' }">{{ c.description }}</div>
<ProgressBar :value="c.progress" :tok="tok" />
</div>
</div>
</div>
<!-- Badges -->
<div :style="{ background: tok.white, borderRadius: '20px', padding: '20px', boxShadow: '0 2px 16px rgba(42,53,51,0.06)' }">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;">
<div :style="{ fontSize: '13px', fontWeight: 600, color: tok.text }">Badges débloqués</div>
<Link :href="route('challenges')" :style="{ fontSize: '11px', color: tok.primary, textDecoration: 'none' }">Voir tout </Link>
</div>
<div style="display:flex;justify-content:space-around;">
<BadgeChip v-for="(b, i) in badges.slice(0, 4)" :key="i" :icon="b.icon" :label="b.label" :unlocked="b.unlocked" :tok="tok" />
</div>
</div>
<button @click="openInput" :style="{
width: '100%', padding: '14px', background: tok.primary, color: '#fff',
borderRadius: '16px', border: 'none', fontSize: '15px', fontWeight: 600,
cursor: 'pointer', boxShadow: '0 6px 18px rgba(123,191,181,0.35)',
}"> Saisir une mesure</button>
</div>
</DiabetixLayout>
</template>