680 lines
20 KiB
TypeScript
680 lines
20 KiB
TypeScript
import NumberKeyboard from '@/components/NumberKeyboard';
|
||
import { HeaderBar } from '@/components/ui/HeaderBar';
|
||
import { WeightRecordCard } from '@/components/weight/WeightRecordCard';
|
||
import { Colors } from '@/constants/Colors';
|
||
import { getTabBarBottomPadding } from '@/constants/TabBar';
|
||
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||
import { useSafeAreaTop } from '@/hooks/useSafeAreaWithPadding';
|
||
import { deleteWeightRecord, fetchWeightHistory, updateUserProfile, updateWeightRecord, WeightHistoryItem } from '@/store/userSlice';
|
||
import { Ionicons } from '@expo/vector-icons';
|
||
import dayjs from 'dayjs';
|
||
import { LinearGradient } from 'expo-linear-gradient';
|
||
import { router } from 'expo-router';
|
||
import React, { useCallback, useEffect, useState } from 'react';
|
||
import {
|
||
Alert,
|
||
Modal,
|
||
ScrollView,
|
||
StyleSheet,
|
||
Text,
|
||
TouchableOpacity,
|
||
View
|
||
} from 'react-native';
|
||
|
||
export default function WeightRecordsPage() {
|
||
const safeAreaTop = useSafeAreaTop()
|
||
|
||
const dispatch = useAppDispatch();
|
||
const userProfile = useAppSelector((s) => s.user.profile);
|
||
const weightHistory = useAppSelector((s) => s.user.weightHistory);
|
||
const [showWeightPicker, setShowWeightPicker] = useState(false);
|
||
const [pickerType, setPickerType] = useState<'current' | 'initial' | 'target' | 'edit'>('current');
|
||
const [inputWeight, setInputWeight] = useState('');
|
||
const [editingRecord, setEditingRecord] = useState<WeightHistoryItem | null>(null);
|
||
|
||
const colorScheme = useColorScheme();
|
||
const themeColors = Colors[colorScheme ?? 'light'];
|
||
|
||
console.log('userProfile:', userProfile);
|
||
|
||
const loadWeightHistory = useCallback(async () => {
|
||
try {
|
||
await dispatch(fetchWeightHistory() as any);
|
||
} catch (error) {
|
||
console.error('加载体重历史失败:', error);
|
||
}
|
||
}, [dispatch]);
|
||
|
||
useEffect(() => {
|
||
loadWeightHistory();
|
||
}, [loadWeightHistory]);
|
||
|
||
const handleGoBack = () => {
|
||
router.back();
|
||
};
|
||
|
||
const initializeInput = (weight: number) => {
|
||
setInputWeight(weight.toString());
|
||
};
|
||
|
||
const handleAddWeight = () => {
|
||
setPickerType('current');
|
||
const weight = userProfile?.weight ? parseFloat(userProfile.weight) : 70.0;
|
||
initializeInput(weight);
|
||
setShowWeightPicker(true);
|
||
};
|
||
|
||
const handleEditInitialWeight = () => {
|
||
setPickerType('initial');
|
||
const initialWeight = userProfile?.initialWeight || userProfile?.weight || '70.0';
|
||
initializeInput(parseFloat(initialWeight));
|
||
setShowWeightPicker(true);
|
||
};
|
||
|
||
const handleEditTargetWeight = () => {
|
||
setPickerType('target');
|
||
const targetWeight = userProfile?.targetWeight || '60.0';
|
||
initializeInput(parseFloat(targetWeight));
|
||
setShowWeightPicker(true);
|
||
};
|
||
|
||
const handleEditWeightRecord = (record: WeightHistoryItem) => {
|
||
setPickerType('edit');
|
||
setEditingRecord(record);
|
||
initializeInput(parseFloat(record.weight));
|
||
setShowWeightPicker(true);
|
||
};
|
||
|
||
const handleDeleteWeightRecord = async (id: string) => {
|
||
try {
|
||
await dispatch(deleteWeightRecord(id) as any);
|
||
await loadWeightHistory();
|
||
} catch (error) {
|
||
console.error('删除体重记录失败:', error);
|
||
Alert.alert('错误', '删除体重记录失败,请重试');
|
||
}
|
||
};
|
||
|
||
const handleWeightSave = async () => {
|
||
const weight = parseFloat(inputWeight);
|
||
if (isNaN(weight) || weight <= 0 || weight > 500) {
|
||
alert('请输入有效的体重值(0-500kg)');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
if (pickerType === 'current') {
|
||
// Update current weight in profile and add weight record
|
||
await dispatch(updateUserProfile({ weight: weight }) as any);
|
||
} else if (pickerType === 'initial') {
|
||
// Update initial weight in profile
|
||
console.log('更新初始体重');
|
||
await dispatch(updateUserProfile({ initialWeight: weight }) as any);
|
||
} else if (pickerType === 'target') {
|
||
// Update target weight in profile
|
||
await dispatch(updateUserProfile({ targetWeight: weight }) as any);
|
||
} else if (pickerType === 'edit' && editingRecord) {
|
||
await dispatch(updateWeightRecord({ id: editingRecord.id, weight }) as any);
|
||
}
|
||
setShowWeightPicker(false);
|
||
setInputWeight('');
|
||
setEditingRecord(null);
|
||
await loadWeightHistory();
|
||
} catch (error) {
|
||
console.error('保存体重失败:', error);
|
||
Alert.alert('错误', '保存体重失败,请重试');
|
||
}
|
||
};
|
||
|
||
const handleNumberPress = (number: string) => {
|
||
setInputWeight(prev => {
|
||
// 防止输入多个0开头
|
||
if (prev === '0' && number === '0') return prev;
|
||
// 如果当前是0,输入非0数字时替换
|
||
if (prev === '0' && number !== '0') return number;
|
||
return prev + number;
|
||
});
|
||
};
|
||
|
||
const handleDeletePress = () => {
|
||
setInputWeight(prev => prev.slice(0, -1));
|
||
};
|
||
|
||
const handleDecimalPress = () => {
|
||
setInputWeight(prev => {
|
||
if (prev.includes('.')) return prev;
|
||
// 如果没有输入任何数字,自动添加0
|
||
if (!prev) return '0.';
|
||
return prev + '.';
|
||
});
|
||
};
|
||
|
||
// Process weight history data
|
||
const sortedHistory = [...weightHistory]
|
||
.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
||
|
||
// Group by month
|
||
const groupedHistory = sortedHistory.reduce((acc, item) => {
|
||
const monthKey = dayjs(item.createdAt).format('YYYY年MM月');
|
||
if (!acc[monthKey]) {
|
||
acc[monthKey] = [];
|
||
}
|
||
acc[monthKey].push(item);
|
||
return acc;
|
||
}, {} as Record<string, WeightHistoryItem[]>);
|
||
|
||
// Calculate statistics
|
||
const currentWeight = userProfile?.weight ? parseFloat(userProfile.weight) : 0;
|
||
const initialWeight = userProfile?.initialWeight ? parseFloat(userProfile.initialWeight) :
|
||
(sortedHistory.length > 0 ? parseFloat(sortedHistory[sortedHistory.length - 1].weight) : currentWeight);
|
||
const targetWeight = userProfile?.targetWeight ? parseFloat(userProfile.targetWeight) : 60.0;
|
||
const totalWeightLoss = initialWeight - currentWeight;
|
||
|
||
return (
|
||
<View style={styles.container}>
|
||
{/* 背景渐变 */}
|
||
<LinearGradient
|
||
colors={['#F0F9FF', '#E0F2FE']}
|
||
style={styles.gradientBackground}
|
||
start={{ x: 0, y: 0 }}
|
||
end={{ x: 1, y: 1 }}
|
||
/>
|
||
|
||
<HeaderBar
|
||
title="体重记录"
|
||
right={<TouchableOpacity onPress={handleAddWeight} style={styles.addButton}>
|
||
<Ionicons name="add" size={24} color="#192126" />
|
||
</TouchableOpacity>}
|
||
/>
|
||
|
||
<View style={{
|
||
paddingTop: safeAreaTop
|
||
}} />
|
||
{/* Weight Statistics */}
|
||
<View style={[styles.statsContainer]}>
|
||
<View style={styles.statsRow}>
|
||
<View style={styles.statItem}>
|
||
<Text style={styles.statValue}>{totalWeightLoss.toFixed(1)}kg</Text>
|
||
<Text style={styles.statLabel}>累计减重</Text>
|
||
</View>
|
||
<View style={styles.statItem}>
|
||
<Text style={styles.statValue}>{currentWeight.toFixed(1)}kg</Text>
|
||
<Text style={styles.statLabel}>当前体重</Text>
|
||
</View>
|
||
<View style={styles.statItem}>
|
||
<Text style={styles.statValue}>{initialWeight.toFixed(1)}kg</Text>
|
||
<View style={styles.statLabelContainer}>
|
||
<Text style={styles.statLabel}>初始体重</Text>
|
||
<TouchableOpacity onPress={handleEditInitialWeight} style={styles.editIcon}>
|
||
<Ionicons name="create-outline" size={14} color="#FF9500" />
|
||
</TouchableOpacity>
|
||
</View>
|
||
</View>
|
||
<View style={styles.statItem}>
|
||
<Text style={styles.statValue}>{targetWeight.toFixed(1)}kg</Text>
|
||
<View style={styles.statLabelContainer}>
|
||
<Text style={styles.statLabel}>目标体重</Text>
|
||
<TouchableOpacity onPress={handleEditTargetWeight} style={styles.editIcon}>
|
||
<Ionicons name="create-outline" size={14} color="#FF9500" />
|
||
</TouchableOpacity>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
|
||
<ScrollView
|
||
style={styles.content}
|
||
contentContainerStyle={[styles.contentContainer, { paddingBottom: getTabBarBottomPadding() + 20 }]}
|
||
showsVerticalScrollIndicator={false}
|
||
>
|
||
|
||
{/* Monthly Records */}
|
||
{Object.keys(groupedHistory).length > 0 ? (
|
||
Object.entries(groupedHistory).map(([month, records]) => (
|
||
<View key={month} style={styles.monthContainer}>
|
||
{/* Month Header Card */}
|
||
{/* <View style={styles.monthHeaderCard}>
|
||
<View style={styles.monthTitleRow}>
|
||
<Text style={styles.monthNumber}>
|
||
{dayjs(month, 'YYYY年MM月').format('MM')}
|
||
</Text>
|
||
<Text style={styles.monthText}>月</Text>
|
||
<Text style={styles.yearText}>
|
||
{dayjs(month, 'YYYY年MM月').format('YYYY年')}
|
||
</Text>
|
||
<View style={styles.expandIcon}>
|
||
<Ionicons name="chevron-up" size={16} color="#FF9500" />
|
||
</View>
|
||
</View>
|
||
<Text style={styles.monthStatsText}>
|
||
累计减重:<Text style={styles.statsBold}>{totalWeightLoss.toFixed(1)}kg</Text> 日均减重:<Text style={styles.statsBold}>{avgWeightLoss.toFixed(1)}kg</Text>
|
||
</Text>
|
||
</View> */}
|
||
|
||
{/* Individual Record Cards */}
|
||
{records.map((record, recordIndex) => {
|
||
// Calculate weight change from previous record
|
||
const prevRecord = recordIndex < records.length - 1 ? records[recordIndex + 1] : null;
|
||
const weightChange = prevRecord ?
|
||
parseFloat(record.weight) - parseFloat(prevRecord.weight) : 0;
|
||
|
||
return (
|
||
<WeightRecordCard
|
||
key={`${record.createdAt}-${recordIndex}`}
|
||
record={record}
|
||
onPress={handleEditWeightRecord}
|
||
onDelete={handleDeleteWeightRecord}
|
||
weightChange={weightChange}
|
||
/>
|
||
);
|
||
})}
|
||
</View>
|
||
))
|
||
) : (
|
||
<View style={styles.emptyContainer}>
|
||
<View style={styles.emptyContent}>
|
||
<Text style={styles.emptyText}>暂无体重记录</Text>
|
||
<Text style={styles.emptySubtext}>点击右上角添加按钮开始记录</Text>
|
||
</View>
|
||
</View>
|
||
)}
|
||
</ScrollView>
|
||
|
||
{/* Weight Input Modal */}
|
||
<Modal
|
||
visible={showWeightPicker}
|
||
animationType="fade"
|
||
transparent
|
||
onRequestClose={() => setShowWeightPicker(false)}
|
||
>
|
||
<View style={styles.modalContainer}>
|
||
<TouchableOpacity
|
||
style={styles.modalBackdrop}
|
||
activeOpacity={1}
|
||
onPress={() => setShowWeightPicker(false)}
|
||
/>
|
||
<View style={[styles.modalSheet, { backgroundColor: themeColors.background }]}>
|
||
{/* Header */}
|
||
<View style={styles.modalHeader}>
|
||
<TouchableOpacity onPress={() => setShowWeightPicker(false)}>
|
||
<Ionicons name="close" size={24} color={themeColors.text} />
|
||
</TouchableOpacity>
|
||
<Text style={[styles.modalTitle, { color: themeColors.text }]}>
|
||
{pickerType === 'current' && '记录体重'}
|
||
{pickerType === 'initial' && '编辑初始体重'}
|
||
{pickerType === 'target' && '编辑目标体重'}
|
||
{pickerType === 'edit' && '编辑体重记录'}
|
||
</Text>
|
||
<View style={{ width: 24 }} />
|
||
</View>
|
||
|
||
<ScrollView
|
||
style={styles.modalContent}
|
||
showsVerticalScrollIndicator={false}
|
||
>
|
||
{/* Weight Display Section */}
|
||
<View style={styles.inputSection}>
|
||
<View style={styles.weightInputContainer}>
|
||
<View style={styles.weightIcon}>
|
||
<Ionicons name="scale-outline" size={20} color="#6366F1" />
|
||
</View>
|
||
<View style={styles.inputWrapper}>
|
||
<Text style={[styles.weightDisplay, { color: inputWeight ? themeColors.text : themeColors.textSecondary }]}>
|
||
{inputWeight || '输入体重'}
|
||
</Text>
|
||
<Text style={[styles.unitLabel, { color: themeColors.textSecondary }]}>kg</Text>
|
||
</View>
|
||
</View>
|
||
|
||
{/* Weight Range Hint */}
|
||
<Text style={[styles.hintText, { color: themeColors.textSecondary }]}>
|
||
请输入 0-500 之间的数值,支持小数
|
||
</Text>
|
||
</View>
|
||
|
||
{/* Quick Selection */}
|
||
<View style={styles.quickSelectionSection}>
|
||
<Text style={[styles.quickSelectionTitle, { color: themeColors.text }]}>快速选择</Text>
|
||
<View style={styles.quickButtons}>
|
||
{[50, 60, 70, 80, 90].map((weight) => (
|
||
<TouchableOpacity
|
||
key={weight}
|
||
style={[
|
||
styles.quickButton,
|
||
inputWeight === weight.toString() && styles.quickButtonSelected
|
||
]}
|
||
onPress={() => setInputWeight(weight.toString())}
|
||
>
|
||
<Text style={[
|
||
styles.quickButtonText,
|
||
inputWeight === weight.toString() && styles.quickButtonTextSelected
|
||
]}>
|
||
{weight}kg
|
||
</Text>
|
||
</TouchableOpacity>
|
||
))}
|
||
</View>
|
||
</View>
|
||
</ScrollView>
|
||
|
||
{/* Custom Number Keyboard */}
|
||
<NumberKeyboard
|
||
onNumberPress={handleNumberPress}
|
||
onDeletePress={handleDeletePress}
|
||
onDecimalPress={handleDecimalPress}
|
||
hasDecimal={inputWeight.includes('.')}
|
||
maxLength={6}
|
||
currentValue={inputWeight}
|
||
/>
|
||
|
||
{/* Save Button */}
|
||
<View style={styles.modalFooter}>
|
||
<TouchableOpacity
|
||
style={[
|
||
styles.saveButton,
|
||
{ opacity: !inputWeight.trim() ? 0.5 : 1 }
|
||
]}
|
||
onPress={handleWeightSave}
|
||
disabled={!inputWeight.trim()}
|
||
>
|
||
<Text style={styles.saveButtonText}>确定</Text>
|
||
</TouchableOpacity>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</Modal>
|
||
</View>
|
||
);
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
flex: 1,
|
||
},
|
||
gradientBackground: {
|
||
position: 'absolute',
|
||
left: 0,
|
||
right: 0,
|
||
top: 0,
|
||
bottom: 0,
|
||
},
|
||
header: {
|
||
flexDirection: 'row',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
paddingTop: 60,
|
||
paddingHorizontal: 20,
|
||
paddingBottom: 10,
|
||
},
|
||
backButton: {
|
||
width: 40,
|
||
height: 40,
|
||
borderRadius: 20,
|
||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
},
|
||
addButton: {
|
||
width: 40,
|
||
height: 40,
|
||
borderRadius: 20,
|
||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
},
|
||
content: {
|
||
flex: 1,
|
||
paddingHorizontal: 20,
|
||
},
|
||
contentContainer: {
|
||
flexGrow: 1,
|
||
},
|
||
statsContainer: {
|
||
backgroundColor: '#FFFFFF',
|
||
borderRadius: 16,
|
||
padding: 20,
|
||
marginBottom: 20,
|
||
marginLeft: 20,
|
||
marginRight: 20,
|
||
shadowColor: '#000',
|
||
shadowOffset: { width: 0, height: 2 },
|
||
shadowOpacity: 0.1,
|
||
shadowRadius: 8,
|
||
elevation: 3,
|
||
},
|
||
statsRow: {
|
||
flexDirection: 'row',
|
||
justifyContent: 'space-between',
|
||
},
|
||
statItem: {
|
||
flex: 1,
|
||
flexDirection: 'column',
|
||
alignItems: 'center',
|
||
},
|
||
statValue: {
|
||
fontSize: 16,
|
||
fontWeight: '800',
|
||
color: '#192126',
|
||
marginBottom: 4,
|
||
},
|
||
statLabelContainer: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
},
|
||
statLabel: {
|
||
fontSize: 12,
|
||
color: '#687076',
|
||
marginRight: 4,
|
||
},
|
||
editIcon: {
|
||
padding: 2,
|
||
borderRadius: 8,
|
||
backgroundColor: 'rgba(255, 149, 0, 0.1)',
|
||
},
|
||
monthContainer: {
|
||
marginBottom: 20,
|
||
},
|
||
monthHeaderCard: {
|
||
backgroundColor: '#FFFFFF',
|
||
borderRadius: 16,
|
||
padding: 20,
|
||
marginBottom: 12,
|
||
shadowColor: '#000',
|
||
shadowOffset: { width: 0, height: 2 },
|
||
shadowOpacity: 0.08,
|
||
shadowRadius: 12,
|
||
elevation: 3,
|
||
},
|
||
monthTitleRow: {
|
||
flexDirection: 'row',
|
||
alignItems: 'baseline',
|
||
marginBottom: 12,
|
||
},
|
||
monthNumber: {
|
||
fontSize: 48,
|
||
fontWeight: '800',
|
||
color: '#192126',
|
||
lineHeight: 48,
|
||
},
|
||
monthText: {
|
||
fontSize: 16,
|
||
fontWeight: '600',
|
||
color: '#192126',
|
||
marginLeft: 4,
|
||
marginRight: 8,
|
||
},
|
||
yearText: {
|
||
fontSize: 16,
|
||
fontWeight: '500',
|
||
color: '#687076',
|
||
flex: 1,
|
||
},
|
||
expandIcon: {
|
||
padding: 4,
|
||
},
|
||
monthStatsText: {
|
||
fontSize: 14,
|
||
color: '#687076',
|
||
lineHeight: 20,
|
||
},
|
||
statsBold: {
|
||
fontWeight: '700',
|
||
color: '#192126',
|
||
},
|
||
|
||
emptyContainer: {
|
||
flex: 1,
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
minHeight: 300,
|
||
},
|
||
emptyContent: {
|
||
alignItems: 'center',
|
||
},
|
||
emptyText: {
|
||
fontSize: 16,
|
||
fontWeight: '700',
|
||
color: '#192126',
|
||
marginBottom: 8,
|
||
},
|
||
emptySubtext: {
|
||
fontSize: 14,
|
||
color: '#687076',
|
||
},
|
||
// Modal Styles
|
||
modalContainer: {
|
||
flex: 1,
|
||
},
|
||
modalBackdrop: {
|
||
...StyleSheet.absoluteFillObject,
|
||
backgroundColor: 'rgba(0,0,0,0.35)',
|
||
},
|
||
modalSheet: {
|
||
position: 'absolute',
|
||
left: 0,
|
||
right: 0,
|
||
bottom: 0,
|
||
borderTopLeftRadius: 20,
|
||
borderTopRightRadius: 20,
|
||
maxHeight: '85%',
|
||
minHeight: 500,
|
||
},
|
||
modalHeader: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
justifyContent: 'space-between',
|
||
paddingHorizontal: 20,
|
||
paddingTop: 20,
|
||
paddingBottom: 10,
|
||
},
|
||
modalTitle: {
|
||
fontSize: 18,
|
||
fontWeight: '600',
|
||
},
|
||
modalContent: {
|
||
flex: 1,
|
||
paddingHorizontal: 20,
|
||
},
|
||
inputSection: {
|
||
backgroundColor: '#FFFFFF',
|
||
borderRadius: 16,
|
||
padding: 16,
|
||
marginBottom: 12,
|
||
},
|
||
weightInputContainer: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
marginBottom: 8,
|
||
},
|
||
weightIcon: {
|
||
width: 32,
|
||
height: 32,
|
||
borderRadius: 16,
|
||
backgroundColor: '#F0F9FF',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
marginRight: 12,
|
||
},
|
||
inputWrapper: {
|
||
flex: 1,
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
borderBottomWidth: 2,
|
||
borderBottomColor: '#E5E7EB',
|
||
paddingBottom: 6,
|
||
},
|
||
weightDisplay: {
|
||
flex: 1,
|
||
fontSize: 24,
|
||
fontWeight: '600',
|
||
textAlign: 'center',
|
||
paddingVertical: 4,
|
||
},
|
||
unitLabel: {
|
||
fontSize: 18,
|
||
fontWeight: '500',
|
||
marginLeft: 8,
|
||
},
|
||
hintText: {
|
||
fontSize: 12,
|
||
textAlign: 'center',
|
||
marginTop: 4,
|
||
},
|
||
quickSelectionSection: {
|
||
paddingHorizontal: 4,
|
||
marginBottom: 20,
|
||
},
|
||
quickSelectionTitle: {
|
||
fontSize: 16,
|
||
fontWeight: '600',
|
||
marginBottom: 12,
|
||
textAlign: 'center',
|
||
},
|
||
quickButtons: {
|
||
flexDirection: 'row',
|
||
flexWrap: 'wrap',
|
||
justifyContent: 'center',
|
||
gap: 8,
|
||
},
|
||
quickButton: {
|
||
paddingHorizontal: 14,
|
||
paddingVertical: 8,
|
||
borderRadius: 18,
|
||
backgroundColor: '#F3F4F6',
|
||
borderWidth: 1,
|
||
borderColor: '#E5E7EB',
|
||
minWidth: 60,
|
||
alignItems: 'center',
|
||
},
|
||
quickButtonSelected: {
|
||
backgroundColor: '#6366F1',
|
||
borderColor: '#6366F1',
|
||
},
|
||
quickButtonText: {
|
||
fontSize: 13,
|
||
fontWeight: '500',
|
||
color: '#6B7280',
|
||
},
|
||
quickButtonTextSelected: {
|
||
color: '#FFFFFF',
|
||
fontWeight: '600',
|
||
},
|
||
modalFooter: {
|
||
paddingHorizontal: 20,
|
||
paddingTop: 16,
|
||
paddingBottom: 25,
|
||
},
|
||
saveButton: {
|
||
backgroundColor: '#6366F1',
|
||
borderRadius: 16,
|
||
paddingVertical: 16,
|
||
alignItems: 'center',
|
||
},
|
||
saveButtonText: {
|
||
color: '#FFFFFF',
|
||
fontSize: 18,
|
||
fontWeight: '600',
|
||
},
|
||
}); |