feat: 更新个人信息和打卡功能
- 在个人信息页面中修改用户姓名字段为“name”,并添加注销帐号功能,支持用户删除帐号及相关数据 - 在打卡页面中集成从后端获取当天打卡列表的功能,确保用户数据的实时同步 - 更新 Redux 状态管理,支持打卡记录的同步和更新 - 新增打卡服务,提供创建、更新和删除打卡记录的 API 接口 - 优化样式以适应新功能的展示和交互
This commit is contained in:
@@ -2,8 +2,10 @@ import { HeaderBar } from '@/components/ui/HeaderBar';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import { removeExercise, setCurrentDate, toggleExerciseCompleted } from '@/store/checkinSlice';
|
||||
import type { CheckinExercise } from '@/store/checkinSlice';
|
||||
import { getDailyCheckins, removeExercise, setCurrentDate, syncCheckin, toggleExerciseCompleted } from '@/store/checkinSlice';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
import { useRouter } from 'expo-router';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { Alert, FlatList, SafeAreaView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
@@ -26,8 +28,22 @@ export default function CheckinHome() {
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setCurrentDate(today));
|
||||
// 进入页面立即从后端获取当天打卡列表,回填本地
|
||||
dispatch(getDailyCheckins(today)).unwrap().catch((err: any) => {
|
||||
Alert.alert('获取打卡失败', err?.message || '请稍后重试');
|
||||
});
|
||||
}, [dispatch, today]);
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
// 返回本页时确保与后端同步(若本地有内容则上报,后台 upsert)
|
||||
if (record?.items && Array.isArray(record.items)) {
|
||||
dispatch(syncCheckin({ date: today, items: record.items as CheckinExercise[], note: record?.note }));
|
||||
}
|
||||
return () => { };
|
||||
}, [dispatch, today, record?.items])
|
||||
);
|
||||
|
||||
return (
|
||||
<SafeAreaView style={[styles.safeArea, { backgroundColor: theme === 'light' ? colorTokens.pageBackgroundEmphasis : colorTokens.background }]}>
|
||||
<View style={[styles.container, { backgroundColor: theme === 'light' ? colorTokens.pageBackgroundEmphasis : colorTokens.background }]}>
|
||||
@@ -68,7 +84,13 @@ export default function CheckinHome() {
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={item.completed ? '已完成,点击取消完成' : '未完成,点击标记完成'}
|
||||
style={styles.doneIconBtn}
|
||||
onPress={() => dispatch(toggleExerciseCompleted({ date: today, key: item.key }))}
|
||||
onPress={() => {
|
||||
dispatch(toggleExerciseCompleted({ date: today, key: item.key }));
|
||||
const nextItems: CheckinExercise[] = (record?.items || []).map((it: CheckinExercise) =>
|
||||
it.key === item.key ? { ...it, completed: !it.completed } : it
|
||||
);
|
||||
dispatch(syncCheckin({ date: today, items: nextItems, note: record?.note }));
|
||||
}}
|
||||
hitSlop={{ top: 6, bottom: 6, left: 6, right: 6 }}
|
||||
>
|
||||
<Ionicons
|
||||
@@ -85,7 +107,11 @@ export default function CheckinHome() {
|
||||
{
|
||||
text: '移除',
|
||||
style: 'destructive',
|
||||
onPress: () => dispatch(removeExercise({ date: today, key: item.key })),
|
||||
onPress: () => {
|
||||
dispatch(removeExercise({ date: today, key: item.key }));
|
||||
const nextItems: CheckinExercise[] = (record?.items || []).filter((it: CheckinExercise) => it.key !== item.key);
|
||||
dispatch(syncCheckin({ date: today, items: nextItems, note: record?.note }));
|
||||
},
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { HeaderBar } from '@/components/ui/HeaderBar';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { useAppDispatch } from '@/hooks/redux';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import { addExercise } from '@/store/checkinSlice';
|
||||
import { addExercise, syncCheckin } from '@/store/checkinSlice';
|
||||
import { EXERCISE_LIBRARY, getCategories, searchExercises } from '@/utils/exerciseLibrary';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import * as Haptics from 'expo-haptics';
|
||||
@@ -79,6 +79,21 @@ export default function SelectExerciseScreen() {
|
||||
reps: reps && reps > 0 ? reps : undefined,
|
||||
},
|
||||
}));
|
||||
console.log('addExercise', today, selected.key, sets, reps);
|
||||
// 同步到后端(读取最新 store 需要在返回后由首页触发 load,或此处直接上报)
|
||||
// 简单做法:直接上报新增项(其余项由后端合并/覆盖)
|
||||
dispatch(syncCheckin({
|
||||
date: today,
|
||||
items: [
|
||||
{
|
||||
key: selected.key,
|
||||
name: selected.name,
|
||||
category: selected.category,
|
||||
sets: Math.max(1, sets),
|
||||
reps: reps && reps > 0 ? reps : undefined,
|
||||
},
|
||||
],
|
||||
}));
|
||||
router.back();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user