99 lines
4.2 KiB
JavaScript
99 lines
4.2 KiB
JavaScript
|
|
import { getToken } from '../context/AuthContext'
|
||
|
|
|
||
|
|
let _profileId = null
|
||
|
|
export function setProfileId(id) { _profileId = id }
|
||
|
|
|
||
|
|
const BASE = '/api'
|
||
|
|
|
||
|
|
function hdrs(extra={}) {
|
||
|
|
const h = {...extra}
|
||
|
|
if (_profileId) h['X-Profile-Id'] = _profileId
|
||
|
|
const token = getToken()
|
||
|
|
if (token) h['X-Auth-Token'] = token
|
||
|
|
return h
|
||
|
|
}
|
||
|
|
|
||
|
|
async function req(path, opts={}) {
|
||
|
|
const res = await fetch(BASE+path, {...opts, headers:hdrs(opts.headers||{})})
|
||
|
|
if (!res.ok) { const err=await res.text(); throw new Error(err) }
|
||
|
|
return res.json()
|
||
|
|
}
|
||
|
|
const json=(d)=>({method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(d)})
|
||
|
|
const jput=(d)=>({method:'PUT', headers:{'Content-Type':'application/json'},body:JSON.stringify(d)})
|
||
|
|
|
||
|
|
export const api = {
|
||
|
|
// Profiles
|
||
|
|
listProfiles: () => req('/profiles'),
|
||
|
|
createProfile: (d) => req('/profiles', json(d)),
|
||
|
|
updateProfile: (id,d) => req(`/profiles/${id}`, jput(d)),
|
||
|
|
deleteProfile: (id) => req(`/profiles/${id}`, {method:'DELETE'}),
|
||
|
|
getProfile: () => req('/profile'),
|
||
|
|
updateActiveProfile:(d)=> req('/profile', jput(d)),
|
||
|
|
|
||
|
|
// Weight
|
||
|
|
listWeight: (l=365) => req(`/weight?limit=${l}`),
|
||
|
|
upsertWeight: (date,weight,note='') => req('/weight',json({date,weight,note})),
|
||
|
|
updateWeight: (id,date,weight,note='') => req(`/weight/${id}`,jput({date,weight,note})),
|
||
|
|
deleteWeight: (id) => req(`/weight/${id}`,{method:'DELETE'}),
|
||
|
|
weightStats: () => req('/weight/stats'),
|
||
|
|
|
||
|
|
// Circumferences
|
||
|
|
listCirc: (l=100) => req(`/circumferences?limit=${l}`),
|
||
|
|
upsertCirc: (d) => req('/circumferences',json(d)),
|
||
|
|
updateCirc: (id,d) => req(`/circumferences/${id}`,jput(d)),
|
||
|
|
deleteCirc: (id) => req(`/circumferences/${id}`,{method:'DELETE'}),
|
||
|
|
|
||
|
|
// Caliper
|
||
|
|
listCaliper: (l=100) => req(`/caliper?limit=${l}`),
|
||
|
|
upsertCaliper: (d) => req('/caliper',json(d)),
|
||
|
|
updateCaliper: (id,d) => req(`/caliper/${id}`,jput(d)),
|
||
|
|
deleteCaliper: (id) => req(`/caliper/${id}`,{method:'DELETE'}),
|
||
|
|
|
||
|
|
// Activity
|
||
|
|
listActivity: (l=200)=> req(`/activity?limit=${l}`),
|
||
|
|
createActivity: (d) => req('/activity',json(d)),
|
||
|
|
updateActivity: (id,d) => req(`/activity/${id}`,jput(d)),
|
||
|
|
deleteActivity: (id) => req(`/activity/${id}`,{method:'DELETE'}),
|
||
|
|
activityStats: () => req('/activity/stats'),
|
||
|
|
importActivityCsv: async(file)=>{
|
||
|
|
const fd=new FormData();fd.append('file',file)
|
||
|
|
const r=await fetch(`${BASE}/activity/import-csv`,{method:'POST',body:fd,headers:hdrs()})
|
||
|
|
const d=await r.json();if(!r.ok)throw new Error(d.detail||JSON.stringify(d));return d
|
||
|
|
},
|
||
|
|
|
||
|
|
// Photos
|
||
|
|
uploadPhoto: (file,date='')=>{
|
||
|
|
const fd=new FormData();fd.append('file',file);fd.append('date',date)
|
||
|
|
return fetch(`${BASE}/photos`,{method:'POST',body:fd,headers:hdrs()}).then(r=>r.json())
|
||
|
|
},
|
||
|
|
listPhotos: () => req('/photos'),
|
||
|
|
photoUrl: (pid) => `${BASE}/photos/${pid}`,
|
||
|
|
|
||
|
|
// Nutrition
|
||
|
|
importCsv: async(file)=>{
|
||
|
|
const fd=new FormData();fd.append('file',file)
|
||
|
|
const r=await fetch(`${BASE}/nutrition/import-csv`,{method:'POST',body:fd,headers:hdrs()})
|
||
|
|
const d=await r.json();if(!r.ok)throw new Error(d.detail||JSON.stringify(d));return d
|
||
|
|
},
|
||
|
|
listNutrition: (l=365) => req(`/nutrition?limit=${l}`),
|
||
|
|
nutritionCorrelations: () => req('/nutrition/correlations'),
|
||
|
|
nutritionWeekly: (w=16) => req(`/nutrition/weekly?weeks=${w}`),
|
||
|
|
|
||
|
|
// Stats & AI
|
||
|
|
getStats: () => req('/stats'),
|
||
|
|
insightTrend: () => req('/insights/trend',{method:'POST'}),
|
||
|
|
insightPipeline: () => req('/insights/pipeline',{method:'POST'}),
|
||
|
|
listInsights: () => req('/insights'),
|
||
|
|
latestInsights: () => req('/insights/latest'),
|
||
|
|
exportZip: () => window.open(`${BASE}/export/zip`),
|
||
|
|
exportJson: () => window.open(`${BASE}/export/json`),
|
||
|
|
exportCsv: () => window.open(`${BASE}/export/csv`),
|
||
|
|
|
||
|
|
// Admin
|
||
|
|
adminListProfiles: () => req('/admin/profiles'),
|
||
|
|
adminCreateProfile: (d) => req('/admin/profiles',json(d)),
|
||
|
|
adminDeleteProfile: (id) => req(`/admin/profiles/${id}`,{method:'DELETE'}),
|
||
|
|
adminSetPermissions: (id,d) => req(`/admin/profiles/${id}/permissions`,jput(d)),
|
||
|
|
changePin: (pin) => req('/auth/pin',json({pin})),
|
||
|
|
}
|