commit 710d672307a3030359f673856ad32df644187648 Author: AI Company Date: Tue Jul 21 18:36:41 2026 +0000 feat: initial MetaBloom cross-platform MVP diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..176e6a5 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "enabledPlugins": { + "expo@claude-plugins-official": true + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4774329 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +.expo/ +*.log +.DS_Store diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..0e6bc80 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,3 @@ +# Expo HAS CHANGED + +Read the exact versioned docs at https://docs.expo.dev/versions/v57.0.0/ before writing any code. diff --git a/App.tsx b/App.tsx new file mode 100644 index 0000000..9270c97 --- /dev/null +++ b/App.tsx @@ -0,0 +1,56 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { LinearGradient } from 'expo-linear-gradient'; +import { StatusBar } from 'expo-status-bar'; +import React, { useEffect, useMemo, useState } from 'react'; +import { Alert, Pressable, SafeAreaView, ScrollView, StyleSheet, Text, TextInput, View, useWindowDimensions } from 'react-native'; + +type Tab = 'today' | 'journal' | 'progress' | 'profile'; +type Entry = { date: string; weight: number; water: number; steps: number; glucose?: number }; +const C = { ink:'#15211c', muted:'#637169', cream:'#f6f7f2', white:'#fff', green:'#1d6b50', mint:'#dcefe5', coral:'#ef835f', yellow:'#f4d58d', line:'#e5e9e3' }; +const seed: Entry[] = [ + {date:'Lun',weight:91.4,water:1500,steps:6100,glucose:112},{date:'Mar',weight:91.2,water:1800,steps:7400,glucose:108}, + {date:'Mer',weight:91.1,water:1600,steps:6900,glucose:110},{date:'Jeu',weight:90.9,water:2000,steps:8200,glucose:105}, + {date:'Ven',weight:90.8,water:2100,steps:8600,glucose:104},{date:'Sam',weight:90.7,water:1750,steps:7200,glucose:107},{date:'Auj.',weight:90.6,water:1250,steps:6240,glucose:103}, +]; + +function Card({children, style}: any){return {children}} +function Pill({children, tone='green'}:any){return {children}} +function Metric({emoji,label,value,sub,onPress}:any){return [s.metric,pressed&&{opacity:.7}]}>{emoji}{label}{value}{sub}} +function ProgressBar({value,color=C.green}:any){return } +function Nav({tab,setTab}:any){const items:[Tab,string,string][]=[['today','⌂','Aujourd’hui'],['journal','+','Journal'],['progress','↗','Progrès'],['profile','○','Profil']];return {items.map(([id,icon,label])=>setTab(id)} style={s.navItem}>{icon}{label})}} + +export default function App(){ + const [tab,setTab]=useState('today'); const [entries,setEntries]=useState(seed); const [water,setWater]=useState(1250); const [steps,setSteps]=useState(6240); + const [weight,setWeight]=useState('90.6'); const [glucose,setGlucose]=useState('103'); const [saved,setSaved]=useState(false); const {width}=useWindowDimensions(); + useEffect(()=>{AsyncStorage.getItem('metabloom').then(v=>{if(v){const d=JSON.parse(v);setEntries(d.entries||seed);setWater(d.water||1250);setSteps(d.steps||6240)}}).catch(()=>{})},[]); + useEffect(()=>{AsyncStorage.setItem('metabloom',JSON.stringify({entries,water,steps})).catch(()=>{})},[entries,water,steps]); + const score=Math.round((Math.min(water/2000,1)+Math.min(steps/8000,1)+.82+.75)*25); + const save=()=>{const w=parseFloat(weight.replace(',','.')); const g=parseFloat(glucose); if(!w||w<30||w>300){Alert.alert('Valeur à vérifier','Saisis un poids compris entre 30 et 300 kg.');return} setEntries(x=>[...x.slice(0,6),{date:'Auj.',weight:w,water,steps,glucose:g||undefined}]);setSaved(true);setTimeout(()=>setSaved(false),2200)}; + const content=useMemo(()=>tab==='today'?:tab==='journal'?:tab==='progress'?:{setEntries(seed);setWater(1250);setSteps(6240);AsyncStorage.removeItem('metabloom')}}/>,[tab,score,water,steps,weight,glucose,saved,entries]); + return 900?1120:640}]}>{content}