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>
This commit is contained in:
jeremy bayse
2026-04-29 07:01:41 +02:00
commit 26c6d8031c
150 changed files with 19863 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
<script setup>
import { ref, computed } from 'vue';
import { Head } from '@inertiajs/vue3';
import DiabetixLayout from '@/Layouts/DiabetixLayout.vue';
import ProgressBar from '@/Components/Diabetix/ProgressBar.vue';
import BadgeChip from '@/Components/Diabetix/BadgeChip.vue';
const props = defineProps({
challenges: Array,
badges: Array,
level: Object,
});
const tab = ref('defis');
const unlocked = computed(() => props.badges.filter(b => b.unlocked));
const locked = computed(() => props.badges.filter(b => !b.unlocked));
</script>
<template>
<Head title="Défis & Badges" />
<DiabetixLayout v-slot="{ tok, font }">
<div :style="{ background: tok.white, padding: '14px 20px 18px', borderBottom: '1px solid ' + tok.border }">
<div :style="{ fontFamily: font.title, fontSize: '20px', fontWeight: 600, color: tok.text, marginBottom: '14px' }">Défis & Badges</div>
<div :style="{ background: tok.light, borderRadius: '18px', padding: '16px' }">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
<div>
<div :style="{ fontSize: '11px', color: tok.muted }">Niveau actuel</div>
<div :style="{ fontFamily: font.title, fontSize: '17px', fontWeight: 600, color: tok.text }">{{ level.icon }} {{ level.label }}</div>
</div>
<div style="text-align:right;">
<div :style="{ fontSize: '11px', color: tok.muted }">Points</div>
<div :style="{ fontSize: '22px', fontWeight: 800, color: tok.amber }">{{ level.points.toLocaleString('fr-FR') }}</div>
</div>
</div>
<ProgressBar :value="level.points" :max="level.next_at" :color="tok.amber" :tok="tok" :height="8" />
<div style="display:flex;justify-content:space-between;margin-top:5px;">
<span :style="{ fontSize: '10px', color: tok.muted }">{{ level.icon }} {{ level.label }}</span>
<span :style="{ fontSize: '10px', color: tok.amber }">{{ level.remaining }} pts {{ level.next_icon }} {{ level.next_label }}</span>
</div>
</div>
</div>
<div style="padding:14px 20px 0;">
<div :style="{ display: 'flex', gap: '4px', background: tok.bgAlt, borderRadius: '12px', padding: '4px' }">
<button v-for="t in [['defis','🎯 Défis actifs'],['badges','🏅 Badges']]" :key="t[0]"
@click="tab = t[0]"
:style="{
flex: 1, padding: '8px', borderRadius: '9px', border: 'none',
background: tab === t[0] ? tok.primary : 'transparent',
color: tab === t[0] ? '#fff' : tok.muted,
fontSize: '12px', fontWeight: tab === t[0] ? 600 : 400, cursor: 'pointer',
}">{{ t[1] }}</button>
</div>
</div>
<div style="padding:14px 20px;display:flex;flex-direction:column;gap:14px;">
<template v-if="tab === 'defis'">
<div v-for="c in challenges" :key="c.id"
:style="{ background: tok.white, borderRadius: '18px', padding: '16px', boxShadow: '0 2px 12px rgba(42,53,51,0.06)' }">
<div style="display:flex;align-items:flex-start;gap:12px;">
<div style="font-size:28px;">{{ c.icon }}</div>
<div style="flex:1;">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div :style="{ fontSize: '14px', fontWeight: 600, color: tok.text }">{{ c.title }}</div>
<div :style="{ background: tok.amberLight, borderRadius: '20px', padding: '3px 8px', fontSize: '10px', color: tok.amber, fontWeight: 600 }">+{{ c.points }} pts</div>
</div>
<div :style="{ fontSize: '11px', color: tok.muted, marginBottom: '10px' }">{{ c.description }}</div>
<ProgressBar :value="c.progress" :tok="tok" :height="7" />
<div style="display:flex;justify-content:flex-end;margin-top:5px;">
<span :style="{ fontSize: '11px', color: tok.primary }">{{ c.progress }}%</span>
</div>
</div>
</div>
</div>
</template>
<template v-else>
<template v-if="unlocked.length">
<div :style="{ fontSize: '11px', color: tok.muted, fontWeight: 700, letterSpacing: '0.8px' }">DÉBLOQUÉS ({{ unlocked.length }})</div>
<div v-for="b in unlocked" :key="b.id"
:style="{ background: tok.white, borderRadius: '16px', padding: '14px 16px', boxShadow: '0 2px 10px rgba(42,53,51,0.06)', display: 'flex', alignItems: 'center', gap: '14px' }">
<div :style="{
width: '48px', height: '48px', borderRadius: '50%', flexShrink: 0,
background: tok.light, border: '2px solid ' + tok.primary,
display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '22px',
}">{{ b.icon }}</div>
<div style="flex:1;min-width:0;">
<div :style="{ fontSize: '13px', fontWeight: 700, color: tok.text }">{{ b.label }}</div>
<div :style="{ fontSize: '11px', color: tok.muted, marginTop: '2px', lineHeight: 1.4 }">{{ b.criteria }}</div>
</div>
<div :style="{ fontSize: '16px', flexShrink: 0 }"></div>
</div>
</template>
<template v-if="locked.length">
<div :style="{ fontSize: '11px', color: tok.muted, fontWeight: 700, letterSpacing: '0.8px', marginTop: unlocked.length ? '4px' : 0 }">À DÉBLOQUER ({{ locked.length }})</div>
<div v-for="b in locked" :key="b.id"
:style="{ background: tok.white, borderRadius: '16px', padding: '14px 16px', boxShadow: '0 2px 10px rgba(42,53,51,0.04)', display: 'flex', alignItems: 'center', gap: '14px', opacity: 0.7 }">
<div :style="{
width: '48px', height: '48px', borderRadius: '50%', flexShrink: 0,
background: tok.bgAlt, border: '2px solid ' + tok.border,
display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '22px',
filter: 'grayscale(1)',
}">{{ b.icon }}</div>
<div style="flex:1;min-width:0;">
<div :style="{ fontSize: '13px', fontWeight: 600, color: tok.muted }">{{ b.label }}</div>
<div :style="{ fontSize: '11px', color: tok.muted, marginTop: '2px', lineHeight: 1.4 }">{{ b.criteria }}</div>
</div>
<div :style="{ fontSize: '16px', flexShrink: 0 }">🔒</div>
</div>
</template>
</template>
</div>
</DiabetixLayout>
</template>

View File

@@ -0,0 +1,73 @@
<script setup>
import { ref, watch, nextTick } from 'vue';
import { Head, useForm } from '@inertiajs/vue3';
import DiabetixLayout from '@/Layouts/DiabetixLayout.vue';
import CoachAvatar from '@/Components/Diabetix/CoachAvatar.vue';
const props = defineProps({
messages: Array,
});
const form = useForm({ body: '' });
const listRef = ref(null);
function send() {
if (!form.body.trim()) return;
form.post(route('chat.store'), {
preserveScroll: true,
onSuccess: () => form.reset('body'),
});
}
watch(() => props.messages.length, async () => {
await nextTick();
if (listRef.value) listRef.value.scrollTop = listRef.value.scrollHeight;
}, { immediate: true });
</script>
<template>
<Head title="Coach IA" />
<DiabetixLayout v-slot="{ tok, font }">
<div :style="{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 78px)', background: tok.bg }">
<div :style="{ background: tok.white, padding: '12px 16px', display: 'flex', alignItems: 'center', gap: '10px', borderBottom: '1px solid ' + tok.border, flexShrink: 0 }">
<CoachAvatar :size="36" :tok="tok" />
<div>
<div :style="{ fontFamily: font.title, fontSize: '16px', fontWeight: 600, color: tok.text }">Coach IA</div>
<div :style="{ fontSize: '11px', color: tok.primary }">🟢 En ligne · Répond en quelques secondes</div>
</div>
</div>
<div ref="listRef" style="flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px;">
<div v-for="(msg, i) in messages" :key="msg.id ?? i"
:style="{ display: 'flex', flexDirection: 'column', alignItems: msg.sender === 'coach' ? 'flex-start' : 'flex-end', gap: '5px' }">
<div :style="{ display: 'flex', alignItems: 'flex-end', gap: '8px', flexDirection: msg.sender === 'coach' ? 'row' : 'row-reverse' }">
<CoachAvatar v-if="msg.sender === 'coach'" :size="28" :tok="tok" />
<div :style="{
maxWidth: '78%',
background: msg.sender === 'coach' ? tok.light : tok.primary,
color: msg.sender === 'coach' ? tok.text : '#fff',
borderRadius: msg.sender === 'coach' ? '14px 14px 14px 3px' : '14px 14px 3px 14px',
padding: '10px 14px', fontSize: '13px', lineHeight: 1.5,
}">{{ msg.body }}</div>
</div>
<div v-if="msg.actions && msg.actions.length" :style="{ display: 'flex', flexWrap: 'wrap', gap: '6px', marginLeft: msg.sender === 'coach' ? '36px' : 0 }">
<button v-for="(a, j) in msg.actions" :key="j" :style="{
padding: '5px 13px', borderRadius: '20px', background: tok.white,
border: '1.5px solid ' + tok.primary, fontSize: '11px',
color: tok.primary, fontWeight: 500, cursor: 'pointer',
}">{{ a }}</button>
</div>
<div :style="{ fontSize: '9px', color: tok.muted, paddingLeft: msg.sender === 'coach' ? '36px' : 0 }">{{ msg.time }}</div>
</div>
</div>
<div :style="{ padding: '10px 14px', background: tok.white, borderTop: '1px solid ' + tok.border, flexShrink: 0, display: 'flex', gap: '8px', alignItems: 'center' }">
<input v-model="form.body" @keydown.enter="send"
placeholder="Écrire au coach..."
:style="{ flex: 1, padding: '10px 14px', borderRadius: '20px', border: '1.5px solid ' + tok.border, background: tok.bg, fontSize: '13px', color: tok.text, outline: 'none' }" />
<button @click="send" :disabled="form.processing"
:style="{ width: '38px', height: '38px', borderRadius: '50%', background: tok.primary, border: 'none', color: '#fff', fontSize: '17px', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', opacity: form.processing ? 0.6 : 1 }"></button>
</div>
</div>
</DiabetixLayout>
</template>

View File

@@ -0,0 +1,128 @@
<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>

View File

@@ -0,0 +1,113 @@
<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>