81 lines
3.0 KiB
Dart
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);
|
|
});
|