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>
114 lines
6.9 KiB
Vue
114 lines
6.9 KiB
Vue
<script setup>
|
||
import { Head, router } from '@inertiajs/vue3';
|
||
import DiabetixLayout from '@/Layouts/DiabetixLayout.vue';
|
||
import GlucoseChart from '@/Components/Diabetix/GlucoseChart.vue';
|
||
|
||
const props = defineProps({
|
||
period: String,
|
||
points: Array,
|
||
stats: Object,
|
||
history: Array,
|
||
target: Object,
|
||
});
|
||
|
||
const tabs = [
|
||
{ id: 'day', label: 'Auj.' },
|
||
{ id: 'week', label: 'Sem.' },
|
||
{ id: 'month', label: 'Mois' },
|
||
{ id: 'quarter', label: 'Trim.' },
|
||
];
|
||
|
||
function setPeriod(p) {
|
||
router.get(route('stats'), { period: p }, { preserveState: false, preserveScroll: true });
|
||
}
|
||
|
||
function fmt(v) {
|
||
return v == null ? '–' : String(v);
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<Head title="Statistiques" />
|
||
<DiabetixLayout v-slot="{ tok, font }">
|
||
<div :style="{ background: tok.white, padding: '14px 20px', borderBottom: '1px solid ' + tok.border }">
|
||
<div :style="{ fontFamily: font.title, fontSize: '20px', fontWeight: 600, color: tok.text, marginBottom: '12px' }">Statistiques</div>
|
||
<div :style="{ display: 'flex', gap: '3px', background: tok.bgAlt, borderRadius: '12px', padding: '3px' }">
|
||
<button v-for="t in tabs" :key="t.id" @click="setPeriod(t.id)"
|
||
:style="{
|
||
flex: 1, padding: '7px 4px', borderRadius: '10px', border: 'none',
|
||
background: period === t.id ? tok.primary : 'transparent',
|
||
color: period === t.id ? '#fff' : tok.muted,
|
||
fontSize: '12px', fontWeight: period === t.id ? 600 : 400, cursor: 'pointer',
|
||
}">{{ t.label }}</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="padding:14px 20px;display:flex;flex-direction:column;gap:14px;">
|
||
<div :style="{ background: tok.white, borderRadius: '20px', padding: '20px', boxShadow: '0 2px 14px rgba(42,53,51,0.06)' }">
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
|
||
<div :style="{ fontSize: '13px', fontWeight: 600, color: tok.text }">Courbe glycémique</div>
|
||
<div style="display:flex;gap:8px;">
|
||
<span :style="{ display: 'flex', alignItems: 'center', gap: '3px', fontSize: '9px', color: tok.muted }">
|
||
<span :style="{ width: '7px', height: '7px', borderRadius: '2px', background: tok.primary, display: 'inline-block' }" />Dans la cible
|
||
</span>
|
||
<span :style="{ display: 'flex', alignItems: 'center', gap: '3px', fontSize: '9px', color: tok.muted }">
|
||
<span :style="{ width: '7px', height: '7px', borderRadius: '2px', background: tok.amber, display: 'inline-block' }" />Hors cible
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<GlucoseChart :data="points" :tok="tok" :width="316" :height="120" :target-min="target.min" :target-max="target.max" />
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
|
||
<div :style="{ background: tok.white, borderRadius: '16px', padding: '14px', boxShadow: '0 2px 10px rgba(42,53,51,0.05)' }">
|
||
<div style="font-size:16px;margin-bottom:4px;">📊</div>
|
||
<div :style="{ fontSize: '22px', fontWeight: 800, color: tok.text }">{{ fmt(stats.avg) }}</div>
|
||
<div :style="{ fontSize: '10px', color: tok.muted, marginTop: '2px' }">Moyenne · mg/dL</div>
|
||
</div>
|
||
<div :style="{ background: tok.white, borderRadius: '16px', padding: '14px', boxShadow: '0 2px 10px rgba(42,53,51,0.05)' }">
|
||
<div style="font-size:16px;margin-bottom:4px;">🎯</div>
|
||
<div :style="{ fontSize: '22px', fontWeight: 800, color: tok.primary }">{{ stats.in_range_pct }}%</div>
|
||
<div :style="{ fontSize: '10px', color: tok.muted, marginTop: '2px' }">Dans la cible</div>
|
||
</div>
|
||
<div :style="{ background: tok.white, borderRadius: '16px', padding: '14px', boxShadow: '0 2px 10px rgba(42,53,51,0.05)' }">
|
||
<div style="font-size:16px;margin-bottom:4px;">⬇️</div>
|
||
<div :style="{ fontSize: '22px', fontWeight: 800, color: tok.amber }">{{ fmt(stats.min) }}</div>
|
||
<div :style="{ fontSize: '10px', color: tok.muted, marginTop: '2px' }">Minimum · mg/dL</div>
|
||
</div>
|
||
<div :style="{ background: tok.white, borderRadius: '16px', padding: '14px', boxShadow: '0 2px 10px rgba(42,53,51,0.05)' }">
|
||
<div style="font-size:16px;margin-bottom:4px;">⬆️</div>
|
||
<div :style="{ fontSize: '22px', fontWeight: 800, color: '#d4826a' }">{{ fmt(stats.max) }}</div>
|
||
<div :style="{ fontSize: '10px', color: tok.muted, marginTop: '2px' }">Maximum · mg/dL</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div :style="{ background: tok.white, borderRadius: '20px', padding: '20px', boxShadow: '0 2px 14px rgba(42,53,51,0.06)' }">
|
||
<div :style="{ fontSize: '13px', fontWeight: 600, color: tok.text, marginBottom: '14px' }">Historique</div>
|
||
<div v-for="(e, i) in history" :key="e.id"
|
||
:style="{
|
||
display: 'flex', alignItems: 'center', gap: '12px',
|
||
paddingBottom: i < history.length - 1 ? '12px' : 0,
|
||
borderBottom: i < history.length - 1 ? '1px solid ' + tok.border : 'none',
|
||
marginBottom: i < history.length - 1 ? '12px' : 0,
|
||
}">
|
||
<div style="display:flex;flex-direction:column;align-items:center;width:12px;">
|
||
<div :style="{ width: '10px', height: '10px', borderRadius: '50%', background: e.in_range ? tok.primary : tok.amber }" />
|
||
<div v-if="i < history.length - 1" :style="{ width: '1px', height: '24px', background: tok.border, marginTop: '2px' }" />
|
||
</div>
|
||
<div style="flex:1;">
|
||
<div style="display:flex;justify-content:space-between;align-items:center;">
|
||
<div>
|
||
<span :style="{ fontSize: '14px', fontWeight: 700, color: tok.text }">{{ fmt(e.value) }} </span>
|
||
<span :style="{ fontSize: '11px', color: tok.muted }">mg/dL </span>
|
||
<span v-if="!e.in_range" :style="{ fontSize: '11px', color: tok.amber, fontWeight: 600 }">⚠️</span>
|
||
</div>
|
||
<span :style="{ fontSize: '11px', color: tok.muted }">{{ e.time }}</span>
|
||
</div>
|
||
<div :style="{ fontSize: '11px', color: tok.muted }">{{ e.context }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</DiabetixLayout>
|
||
</template>
|