Files
2026-09-28 16:40:32 +08:00

81 lines
3.0 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../api/health_api.dart';
import '../models/health.dart';
/// 「强宝健康」的状态。
///
/// 全部用 autoDispose 的 FutureProvider:体重和饮食都要跨设备看,
/// 数据在服务端是唯一真相,本地缓存一份只会带来「改完看到旧数据」的问题。
/// 页面每次进入重新拉一次,代价是一个很轻的请求,换来的是不会看到过期数字。
/// 减重目标(含每周应减、理想曲线、进度)
final weightGoalProvider = FutureProvider.autoDispose<WeightGoal>((ref) {
return ref.watch(healthApiProvider).goal();
});
/// 体重折线图
final weightChartProvider =
FutureProvider.autoDispose<WeightChart>((ref) {
return ref.watch(healthApiProvider).weightChart();
});
/// 体重历史记录
final weightHistoryProvider =
FutureProvider.autoDispose<List<WeightRecordItem>>((ref) {
return ref.watch(healthApiProvider).weightHistory();
});
/// 今日饮食明细
final dietTodayProvider = FutureProvider.autoDispose<DietDay>((ref) {
return ref.watch(healthApiProvider).dietDay();
});
/// 首页卡片用:只想知道「今天吃了多少 kcal、记了几条」。
///
/// 故意不复用 [dietTodayProvider] —— 那个会把整天的明细都拉回来,
/// 就为了一个数字。首页卡片只要合计。
final dietTodayTotalsProvider =
FutureProvider.autoDispose<NutritionTotals>((ref) {
return ref.watch(healthApiProvider).todayTotals();
});
/// 食物搜索关键词 → 结果。family 让每个关键词有独立的缓存。
final foodSearchProvider = FutureProvider.autoDispose
.family<List<FoodItem>, String>((ref, keyword) {
if (keyword.trim().isEmpty) return Future.value(const []);
return ref.watch(healthApiProvider).searchFood(keyword.trim());
});
/// 一级食物分类(分类浏览入口)
final foodCategoriesProvider =
FutureProvider.autoDispose<List<FoodCategory>>((ref) {
return ref.watch(healthApiProvider).foodCategories();
});
/// 某个分类下的食物
final foodByCategoryProvider = FutureProvider.autoDispose
.family<List<FoodItem>, ({String category, String? subCategory})>(
(ref, key) {
return ref
.watch(healthApiProvider)
.foodByCategory(key.category, subCategory: key.subCategory);
});
/// 某个一级分类下的二级分类
final foodSubCategoriesProvider =
FutureProvider.autoDispose.family<List<FoodCategory>, String>(
(ref, category) {
return ref.watch(healthApiProvider).foodSubCategories(category);
});
/// 首页卡片的减肥进度摘要。
///
/// 只取目标和「最近一次体重」,不拉折线图 —— 卡片上只显示一个进度条
/// 和几个数字,没必要为此把半年的数据点都取回来。
final healthSummaryProvider = FutureProvider.autoDispose<
({WeightGoal goal, double? currentWeight})>((ref) async {
final goal = await ref.watch(weightGoalProvider.future);
return (goal: goal, currentWeight: goal.currentWeight);
});