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>
91 lines
4.6 KiB
Vue
91 lines
4.6 KiB
Vue
<script setup>
|
|
import { reactive } from 'vue';
|
|
import { useForm } from '@inertiajs/vue3';
|
|
|
|
const props = defineProps({
|
|
tok: { type: Object, required: true },
|
|
font: { type: Object, required: true },
|
|
});
|
|
|
|
const emit = defineEmits(['close']);
|
|
|
|
const form = useForm({
|
|
value: '',
|
|
context: 'before_meal',
|
|
carbs_g: '',
|
|
insulin_units: '',
|
|
});
|
|
|
|
const contexts = [
|
|
{ id: 'fasting', label: 'À jeun' },
|
|
{ id: 'before_meal', label: 'Avant repas' },
|
|
{ id: 'after_meal', label: 'Après repas' },
|
|
{ id: 'bedtime', label: 'Coucher' },
|
|
];
|
|
|
|
function submit() {
|
|
form.post(route('measurements.store'), {
|
|
preserveScroll: true,
|
|
onSuccess: () => {
|
|
form.reset();
|
|
emit('close');
|
|
},
|
|
});
|
|
}
|
|
|
|
function close(e) {
|
|
if (e.target === e.currentTarget) emit('close');
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div @click="close" :style="{
|
|
position: 'fixed', inset: 0, zIndex: 50, background: 'rgba(0,0,0,0.45)',
|
|
display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
|
|
}">
|
|
<div :style="{ width: '100%', maxWidth: '440px', background: tok.white, borderRadius: '24px 24px 0 0', padding: '6px 20px 36px', boxShadow: '0 -8px 40px rgba(0,0,0,0.18)' }">
|
|
<div :style="{ width: '40px', height: '4px', borderRadius: '2px', background: tok.border, margin: '12px auto 20px' }" />
|
|
<div :style="{ fontFamily: font.title, fontSize: '20px', fontWeight: 600, color: tok.text, marginBottom: '20px' }">Saisir une mesure</div>
|
|
|
|
<div :style="{ background: tok.bg, borderRadius: '20px', padding: '16px 20px', marginBottom: '16px', textAlign: 'center' }">
|
|
<div :style="{ fontSize: '11px', color: tok.muted, marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '0.8px', fontWeight: 600 }">Glycémie (mg/dL)</div>
|
|
<input v-model="form.value" type="number" step="1" min="20" max="600" placeholder="105"
|
|
:style="{ width: '100%', textAlign: 'center', fontSize: '52px', fontWeight: 800, color: tok.text, border: 'none', background: 'transparent', outline: 'none' }" />
|
|
<div v-if="form.errors.value" :style="{ color: '#c43', fontSize: '11px' }">{{ form.errors.value }}</div>
|
|
</div>
|
|
|
|
<div style="margin-bottom:16px;">
|
|
<div :style="{ fontSize: '11px', color: tok.muted, marginBottom: '8px', textTransform: 'uppercase', letterSpacing: '0.8px', fontWeight: 600 }">Contexte</div>
|
|
<div style="display:flex;flex-wrap:wrap;gap:6px;">
|
|
<button v-for="c in contexts" :key="c.id" @click="form.context = c.id" type="button"
|
|
:style="{
|
|
padding: '7px 14px', borderRadius: '20px',
|
|
border: '1.5px solid ' + (form.context === c.id ? tok.primary : tok.border),
|
|
background: form.context === c.id ? tok.light : tok.white,
|
|
color: form.context === c.id ? tok.dark : tok.muted,
|
|
fontSize: '12px', fontWeight: form.context === c.id ? 600 : 400, cursor: 'pointer',
|
|
}">{{ c.label }}</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display:flex;gap:10px;margin-bottom:20px;">
|
|
<div style="flex:1;">
|
|
<div :style="{ fontSize: '11px', color: tok.muted, marginBottom: '6px' }">Glucides (g) · optionnel</div>
|
|
<input v-model="form.carbs_g" type="number" placeholder="45"
|
|
:style="{ width: '100%', padding: '10px 12px', borderRadius: '12px', border: '1.5px solid ' + tok.border, background: tok.bg, fontSize: '14px', color: tok.text, outline: 'none', boxSizing: 'border-box' }" />
|
|
</div>
|
|
<div style="flex:1;">
|
|
<div :style="{ fontSize: '11px', color: tok.muted, marginBottom: '6px' }">Insuline (u) · optionnel</div>
|
|
<input v-model="form.insulin_units" type="number" step="0.5" placeholder="4"
|
|
:style="{ width: '100%', padding: '10px 12px', borderRadius: '12px', border: '1.5px solid ' + tok.border, background: tok.bg, fontSize: '14px', color: tok.text, outline: 'none', boxSizing: 'border-box' }" />
|
|
</div>
|
|
</div>
|
|
|
|
<button @click="submit" :disabled="form.processing"
|
|
:style="{ width: '100%', padding: '16px', background: tok.primary, color: '#fff', borderRadius: '16px', border: 'none', fontSize: '16px', fontWeight: 600, cursor: 'pointer', opacity: form.processing ? 0.6 : 1 }">
|
|
Enregistrer la mesure ✓
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|