feat: 新增健康档案模块,支持家庭邀请与个人健康数据管理
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import NumberKeyboard from '@/components/NumberKeyboard';
|
||||
import { HeaderBar } from '@/components/ui/HeaderBar';
|
||||
import { WeightProgressBar } from '@/components/weight/WeightProgressBar';
|
||||
import { WeightRecordCard } from '@/components/weight/WeightRecordCard';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { getTabBarBottomPadding } from '@/constants/TabBar';
|
||||
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
||||
import { useAuthGuard } from '@/hooks/useAuthGuard';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useSafeAreaTop } from '@/hooks/useSafeAreaWithPadding';
|
||||
@@ -39,14 +41,16 @@ export default function WeightRecordsPage() {
|
||||
|
||||
const colorScheme = useColorScheme();
|
||||
const themeColors = Colors[colorScheme ?? 'light'];
|
||||
const { isLoggedIn, ensureLoggedIn } = useAuthGuard();
|
||||
|
||||
const loadWeightHistory = useCallback(async () => {
|
||||
if (!isLoggedIn) return;
|
||||
try {
|
||||
await dispatch(fetchWeightHistory() as any);
|
||||
} catch (error) {
|
||||
console.error(t('weightRecords.loadingHistory'), error);
|
||||
}
|
||||
}, [dispatch]);
|
||||
}, [dispatch, isLoggedIn]);
|
||||
|
||||
useEffect(() => {
|
||||
loadWeightHistory();
|
||||
@@ -56,28 +60,36 @@ export default function WeightRecordsPage() {
|
||||
setInputWeight(weight.toString());
|
||||
};
|
||||
|
||||
const handleAddWeight = () => {
|
||||
const handleAddWeight = async () => {
|
||||
const ok = await ensureLoggedIn();
|
||||
if (!ok) return;
|
||||
setPickerType('current');
|
||||
const weight = userProfile?.weight ? parseFloat(userProfile.weight) : 70.0;
|
||||
initializeInput(weight);
|
||||
setShowWeightPicker(true);
|
||||
};
|
||||
|
||||
const handleEditInitialWeight = () => {
|
||||
const handleEditInitialWeight = async () => {
|
||||
const ok = await ensureLoggedIn();
|
||||
if (!ok) return;
|
||||
setPickerType('initial');
|
||||
const initialWeight = userProfile?.initialWeight || userProfile?.weight || '70.0';
|
||||
initializeInput(parseFloat(initialWeight));
|
||||
setShowWeightPicker(true);
|
||||
};
|
||||
|
||||
const handleEditTargetWeight = () => {
|
||||
const handleEditTargetWeight = async () => {
|
||||
const ok = await ensureLoggedIn();
|
||||
if (!ok) return;
|
||||
setPickerType('target');
|
||||
const targetWeight = userProfile?.targetWeight || '60.0';
|
||||
initializeInput(parseFloat(targetWeight));
|
||||
setShowWeightPicker(true);
|
||||
};
|
||||
|
||||
const handleEditWeightRecord = (record: WeightHistoryItem) => {
|
||||
const handleEditWeightRecord = async (record: WeightHistoryItem) => {
|
||||
const ok = await ensureLoggedIn();
|
||||
if (!ok) return;
|
||||
setPickerType('edit');
|
||||
setEditingRecord(record);
|
||||
initializeInput(parseFloat(record.weight));
|
||||
@@ -85,6 +97,8 @@ export default function WeightRecordsPage() {
|
||||
};
|
||||
|
||||
const handleDeleteWeightRecord = async (id: string) => {
|
||||
const ok = await ensureLoggedIn();
|
||||
if (!ok) return;
|
||||
try {
|
||||
await dispatch(deleteWeightRecord(id) as any);
|
||||
await loadWeightHistory();
|
||||
@@ -180,6 +194,12 @@ export default function WeightRecordsPage() {
|
||||
const targetWeight = userProfile?.targetWeight ? parseFloat(userProfile.targetWeight) : 60.0;
|
||||
const totalWeightLoss = initialWeight - currentWeight;
|
||||
|
||||
// 计算减重进度
|
||||
const hasTargetWeight = targetWeight > 0 && initialWeight > targetWeight;
|
||||
const totalToLose = initialWeight - targetWeight;
|
||||
const actualLost = initialWeight - currentWeight;
|
||||
const weightProgress = hasTargetWeight && totalToLose > 0 ? actualLost / totalToLose : 0;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{/* 背景 */}
|
||||
@@ -295,6 +315,19 @@ export default function WeightRecordsPage() {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 减重进度条 - 仅在设置了目标体重时显示 */}
|
||||
{hasTargetWeight && (
|
||||
<View style={styles.progressContainer}>
|
||||
<WeightProgressBar
|
||||
progress={weightProgress}
|
||||
currentWeight={currentWeight}
|
||||
targetWeight={targetWeight}
|
||||
initialWeight={initialWeight}
|
||||
showTopBorder={false}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Monthly Records */}
|
||||
{Object.keys(groupedHistory).length > 0 ? (
|
||||
<View style={styles.historySection}>
|
||||
@@ -628,6 +661,20 @@ const styles = StyleSheet.create({
|
||||
marginLeft: 2,
|
||||
},
|
||||
|
||||
// Progress Container
|
||||
progressContainer: {
|
||||
marginHorizontal: 24,
|
||||
marginBottom: 24,
|
||||
backgroundColor: '#ffffff',
|
||||
borderRadius: 24,
|
||||
padding: 20,
|
||||
shadowColor: 'rgba(30, 41, 59, 0.06)',
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 12,
|
||||
elevation: 3,
|
||||
},
|
||||
|
||||
// History Section
|
||||
historySection: {
|
||||
paddingHorizontal: 24,
|
||||
|
||||
Reference in New Issue
Block a user