Add Chinese translations for medication management and personal settings
- Introduced new translation files for medication, personal, and weight management in Chinese. - Updated the main index file to include the new translation modules. - Enhanced the medication type definitions to include 'ointment'. - Refactored workout type labels to utilize i18n for better localization support. - Improved sleep quality descriptions and recommendations with i18n integration.
This commit is contained in:
@@ -11,11 +11,12 @@ import { appStoreReviewService } from '@/services/appStoreReview';
|
||||
import { deleteWeightRecord, fetchWeightHistory, updateUserProfile, updateWeightRecord, WeightHistoryItem } from '@/store/userSlice';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { router } from 'expo-router';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import {
|
||||
Alert,
|
||||
Image,
|
||||
Modal,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
@@ -39,8 +40,6 @@ export default function WeightRecordsPage() {
|
||||
const colorScheme = useColorScheme();
|
||||
const themeColors = Colors[colorScheme ?? 'light'];
|
||||
|
||||
console.log('userProfile:', userProfile);
|
||||
|
||||
const loadWeightHistory = useCallback(async () => {
|
||||
try {
|
||||
await dispatch(fetchWeightHistory() as any);
|
||||
@@ -53,10 +52,6 @@ export default function WeightRecordsPage() {
|
||||
loadWeightHistory();
|
||||
}, [loadWeightHistory]);
|
||||
|
||||
const handleGoBack = () => {
|
||||
router.back();
|
||||
};
|
||||
|
||||
const initializeInput = (weight: number) => {
|
||||
setInputWeight(weight.toString());
|
||||
};
|
||||
@@ -166,7 +161,11 @@ export default function WeightRecordsPage() {
|
||||
|
||||
// Group by month
|
||||
const groupedHistory = sortedHistory.reduce((acc, item) => {
|
||||
const monthKey = dayjs(item.createdAt).format('YYYY年MM月');
|
||||
const date = dayjs(item.createdAt);
|
||||
const monthKey = t('weightRecords.historyMonthFormat', {
|
||||
year: date.format('YYYY'),
|
||||
month: date.format('MM')
|
||||
});
|
||||
if (!acc[monthKey]) {
|
||||
acc[monthKey] = [];
|
||||
}
|
||||
@@ -183,106 +182,157 @@ export default function WeightRecordsPage() {
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{/* 背景渐变 */}
|
||||
{/* 背景 */}
|
||||
<LinearGradient
|
||||
colors={['#F0F9FF', '#E0F2FE']}
|
||||
style={styles.gradientBackground}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
colors={['#f3f4fb', '#f3f4fb']}
|
||||
style={StyleSheet.absoluteFillObject}
|
||||
/>
|
||||
{/* 顶部装饰性渐变 */}
|
||||
<LinearGradient
|
||||
colors={['rgba(229, 252, 254, 0.8)', 'rgba(243, 244, 251, 0)']}
|
||||
style={styles.topGradient}
|
||||
start={{ x: 0.5, y: 0 }}
|
||||
end={{ x: 0.5, y: 1 }}
|
||||
/>
|
||||
|
||||
<HeaderBar
|
||||
title={t('weightRecords.title')}
|
||||
right={<TouchableOpacity onPress={handleAddWeight} style={styles.addButton}>
|
||||
<Ionicons name="add" size={24} color="#192126" />
|
||||
</TouchableOpacity>}
|
||||
right={
|
||||
isLiquidGlassAvailable() ? (
|
||||
<TouchableOpacity
|
||||
onPress={handleAddWeight}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<GlassView
|
||||
style={styles.addButtonGlass}
|
||||
glassEffectStyle="regular"
|
||||
tintColor="rgba(255, 255, 255, 0.4)"
|
||||
isInteractive={true}
|
||||
>
|
||||
<Ionicons name="add" size={24} color="#1c1f3a" />
|
||||
</GlassView>
|
||||
</TouchableOpacity>
|
||||
) : (
|
||||
<TouchableOpacity
|
||||
style={styles.addButtonFallback}
|
||||
onPress={handleAddWeight}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Ionicons name="add" size={24} color="#1c1f3a" />
|
||||
</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}>{t('weightRecords.stats.totalLoss')}</Text>
|
||||
</View>
|
||||
<View style={styles.statItem}>
|
||||
<Text style={styles.statValue}>{currentWeight.toFixed(1)}kg</Text>
|
||||
<Text style={styles.statLabel}>{t('weightRecords.stats.currentWeight')}</Text>
|
||||
</View>
|
||||
<View style={styles.statItem}>
|
||||
<Text style={styles.statValue}>{initialWeight.toFixed(1)}kg</Text>
|
||||
<View style={styles.statLabelContainer}>
|
||||
<Text style={styles.statLabel}>{t('weightRecords.stats.initialWeight')}</Text>
|
||||
<TouchableOpacity onPress={handleEditInitialWeight} style={styles.editIcon}>
|
||||
<Ionicons name="create-outline" size={12} 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}>{t('weightRecords.stats.targetWeight')}</Text>
|
||||
<TouchableOpacity onPress={handleEditTargetWeight} style={styles.editIcon}>
|
||||
<Ionicons name="create-outline" size={12} color="#FF9500" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<ScrollView
|
||||
style={styles.content}
|
||||
contentContainerStyle={[styles.contentContainer, { paddingBottom: getTabBarBottomPadding() + 20 }]}
|
||||
contentContainerStyle={[styles.contentContainer, { paddingBottom: getTabBarBottomPadding() + 20, paddingTop: safeAreaTop }]}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<View style={styles.headerBlock}>
|
||||
<Text style={styles.pageTitle}>{t('weightRecords.title')}</Text>
|
||||
<Text style={styles.pageSubtitle}>{t('weightRecords.pageSubtitle')}</Text>
|
||||
</View>
|
||||
|
||||
{/* Weight Statistics Cards */}
|
||||
<View style={styles.statsGrid}>
|
||||
{/* Current Weight - Hero Card */}
|
||||
<View style={styles.mainStatCard}>
|
||||
<View style={styles.mainStatContent}>
|
||||
<Text style={styles.mainStatLabel}>{t('weightRecords.stats.currentWeight')}</Text>
|
||||
<View style={styles.mainStatValueContainer}>
|
||||
<Text style={styles.mainStatValue}>{currentWeight.toFixed(1)}</Text>
|
||||
<Text style={styles.mainStatUnit}>kg</Text>
|
||||
</View>
|
||||
<View style={styles.totalLossTag}>
|
||||
<Ionicons name={totalWeightLoss <= 0 ? "trending-down" : "trending-up"} size={16} color="#ffffff" />
|
||||
<Text style={styles.totalLossText}>
|
||||
{totalWeightLoss > 0 ? '+' : ''}{totalWeightLoss.toFixed(1)} kg
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<LinearGradient
|
||||
colors={['#4F5BD5', '#6B6CFF']}
|
||||
style={StyleSheet.absoluteFillObject}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
// @ts-ignore
|
||||
borderRadius={24}
|
||||
/>
|
||||
<Image
|
||||
source={require('@/assets/images/icons/iconWeight.png')}
|
||||
style={styles.statIconBg}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Secondary Stats Row */}
|
||||
<View style={styles.secondaryStatsRow}>
|
||||
{/* Initial Weight */}
|
||||
<TouchableOpacity
|
||||
style={styles.secondaryStatCard}
|
||||
onPress={handleEditInitialWeight}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<View style={styles.secondaryStatHeader}>
|
||||
<Text style={styles.secondaryStatLabel}>{t('weightRecords.stats.initialWeight')}</Text>
|
||||
<Ionicons name="create-outline" size={14} color="#9ba3c7" />
|
||||
</View>
|
||||
<Text style={styles.secondaryStatValue}>{initialWeight.toFixed(1)}<Text style={styles.secondaryStatUnit}>kg</Text></Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* Target Weight */}
|
||||
<TouchableOpacity
|
||||
style={styles.secondaryStatCard}
|
||||
onPress={handleEditTargetWeight}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<View style={styles.secondaryStatHeader}>
|
||||
<Text style={styles.secondaryStatLabel}>{t('weightRecords.stats.targetWeight')}</Text>
|
||||
<Ionicons name="create-outline" size={14} color="#9ba3c7" />
|
||||
</View>
|
||||
<Text style={styles.secondaryStatValue}>{targetWeight.toFixed(1)}<Text style={styles.secondaryStatUnit}>kg</Text></Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 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> */}
|
||||
<View style={styles.historySection}>
|
||||
<Text style={styles.sectionTitle}>{t('weightRecords.history')}</Text>
|
||||
{Object.entries(groupedHistory).map(([month, records]) => (
|
||||
<View key={month} style={styles.monthContainer}>
|
||||
<View style={styles.monthHeader}>
|
||||
<Text style={styles.monthTitle}>{month}</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;
|
||||
{/* Individual Record Cards */}
|
||||
<View style={styles.recordsList}>
|
||||
{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>
|
||||
))
|
||||
return (
|
||||
<WeightRecordCard
|
||||
key={`${record.createdAt}-${recordIndex}`}
|
||||
record={record}
|
||||
onPress={handleEditWeightRecord}
|
||||
onDelete={handleDeleteWeightRecord}
|
||||
weightChange={weightChange}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
) : (
|
||||
<View style={styles.emptyContainer}>
|
||||
<Image
|
||||
source={require('@/assets/images/icons/iconWeight.png')}
|
||||
style={{ width: 80, height: 80, opacity: 0.5, marginBottom: 16, tintColor: '#cbd5e1' }}
|
||||
/>
|
||||
<View style={styles.emptyContent}>
|
||||
<Text style={styles.emptyText}>{t('weightRecords.empty.title')}</Text>
|
||||
<Text style={styles.emptySubtext}>{t('weightRecords.empty.subtitle')}</Text>
|
||||
@@ -304,13 +354,16 @@ export default function WeightRecordsPage() {
|
||||
activeOpacity={1}
|
||||
onPress={() => setShowWeightPicker(false)}
|
||||
/>
|
||||
<View style={[styles.modalSheet, { backgroundColor: themeColors.background }]}>
|
||||
<View style={[styles.modalSheet, { backgroundColor: '#ffffff' }]}>
|
||||
{/* Header */}
|
||||
<View style={styles.modalHeader}>
|
||||
<TouchableOpacity onPress={() => setShowWeightPicker(false)}>
|
||||
<Ionicons name="close" size={24} color={themeColors.text} />
|
||||
<TouchableOpacity
|
||||
onPress={() => setShowWeightPicker(false)}
|
||||
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
||||
>
|
||||
<Ionicons name="close" size={24} color="#1c1f3a" />
|
||||
</TouchableOpacity>
|
||||
<Text style={[styles.modalTitle, { color: themeColors.text }]}>
|
||||
<Text style={styles.modalTitle}>
|
||||
{pickerType === 'current' && t('weightRecords.modal.recordWeight')}
|
||||
{pickerType === 'initial' && t('weightRecords.modal.editInitialWeight')}
|
||||
{pickerType === 'target' && t('weightRecords.modal.editTargetWeight')}
|
||||
@@ -327,25 +380,26 @@ export default function WeightRecordsPage() {
|
||||
<View style={styles.inputSection}>
|
||||
<View style={styles.weightInputContainer}>
|
||||
<View style={styles.weightIcon}>
|
||||
<Ionicons name="scale-outline" size={20} color="#6366F1" />
|
||||
<Image
|
||||
source={require('@/assets/images/icons/iconWeight.png')}
|
||||
style={{ width: 24, height: 24, tintColor: '#4F5BD5' }}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<Text style={[styles.weightDisplay, { color: inputWeight ? themeColors.text : themeColors.textSecondary }]}>
|
||||
<Text style={[
|
||||
styles.weightDisplay,
|
||||
{ color: inputWeight ? '#1c1f3a' : '#9ba3c7' }
|
||||
]}>
|
||||
{inputWeight || t('weightRecords.modal.inputPlaceholder')}
|
||||
</Text>
|
||||
<Text style={[styles.unitLabel, { color: themeColors.textSecondary }]}>{t('weightRecords.modal.unit')}</Text>
|
||||
<Text style={styles.unitLabel}>{t('weightRecords.modal.unit')}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Weight Range Hint */}
|
||||
<Text style={[styles.hintText, { color: themeColors.textSecondary }]}>
|
||||
{t('weightRecords.modal.inputHint')}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Quick Selection */}
|
||||
<View style={styles.quickSelectionSection}>
|
||||
<Text style={[styles.quickSelectionTitle, { color: themeColors.text }]}>{t('weightRecords.modal.quickSelection')}</Text>
|
||||
<Text style={styles.quickSelectionTitle}>{t('weightRecords.modal.quickSelection')}</Text>
|
||||
<View style={styles.quickButtons}>
|
||||
{[50, 60, 70, 80, 90].map((weight) => (
|
||||
<TouchableOpacity
|
||||
@@ -355,6 +409,7 @@ export default function WeightRecordsPage() {
|
||||
inputWeight === weight.toString() && styles.quickButtonSelected
|
||||
]}
|
||||
onPress={() => setInputWeight(weight.toString())}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Text style={[
|
||||
styles.quickButtonText,
|
||||
@@ -387,8 +442,16 @@ export default function WeightRecordsPage() {
|
||||
]}
|
||||
onPress={handleWeightSave}
|
||||
disabled={!inputWeight.trim()}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<Text style={styles.saveButtonText}>{t('weightRecords.modal.confirm')}</Text>
|
||||
<LinearGradient
|
||||
colors={['#4F5BD5', '#6B6CFF']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
style={styles.saveButtonGradient}
|
||||
>
|
||||
<Text style={styles.saveButtonText}>{t('weightRecords.modal.confirm')}</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
@@ -402,144 +465,202 @@ const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
gradientBackground: {
|
||||
topGradient: {
|
||||
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',
|
||||
height: 300,
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
contentContainer: {
|
||||
flexGrow: 1,
|
||||
paddingBottom: 40,
|
||||
},
|
||||
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,
|
||||
headerBlock: {
|
||||
paddingHorizontal: 24,
|
||||
marginTop: 10,
|
||||
marginBottom: 24,
|
||||
},
|
||||
statsRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
statItem: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
},
|
||||
statValue: {
|
||||
fontSize: 14,
|
||||
pageTitle: {
|
||||
fontSize: 28,
|
||||
fontWeight: '800',
|
||||
color: '#192126',
|
||||
color: '#1c1f3a',
|
||||
fontFamily: 'AliBold',
|
||||
marginBottom: 4,
|
||||
},
|
||||
statLabelContainer: {
|
||||
flexDirection: 'row',
|
||||
pageSubtitle: {
|
||||
fontSize: 16,
|
||||
color: '#6f7ba7',
|
||||
fontFamily: 'AliRegular',
|
||||
},
|
||||
// Add Button Styles
|
||||
addButtonGlass: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 20,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
statLabel: {
|
||||
fontSize: 12,
|
||||
color: '#687076',
|
||||
marginRight: 4,
|
||||
textAlign: 'center'
|
||||
addButtonFallback: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 20,
|
||||
backgroundColor: '#ffffff',
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(0,0,0,0.05)',
|
||||
},
|
||||
editIcon: {
|
||||
padding: 2,
|
||||
borderRadius: 8,
|
||||
backgroundColor: 'rgba(255, 149, 0, 0.1)',
|
||||
|
||||
// Stats Grid
|
||||
statsGrid: {
|
||||
paddingHorizontal: 24,
|
||||
marginBottom: 32,
|
||||
gap: 16,
|
||||
},
|
||||
monthContainer: {
|
||||
marginBottom: 20,
|
||||
mainStatCard: {
|
||||
backgroundColor: '#4F5BD5',
|
||||
borderRadius: 28,
|
||||
padding: 24,
|
||||
height: 160,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
shadowColor: '#4F5BD5',
|
||||
shadowOffset: { width: 0, height: 10 },
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 16,
|
||||
elevation: 8,
|
||||
},
|
||||
monthHeaderCard: {
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderRadius: 16,
|
||||
padding: 20,
|
||||
marginBottom: 12,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.08,
|
||||
mainStatContent: {
|
||||
zIndex: 2,
|
||||
height: '100%',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
mainStatLabel: {
|
||||
fontSize: 16,
|
||||
color: 'rgba(255, 255, 255, 0.9)',
|
||||
fontFamily: 'AliRegular',
|
||||
},
|
||||
mainStatValueContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'baseline',
|
||||
},
|
||||
mainStatValue: {
|
||||
fontSize: 48,
|
||||
fontWeight: '800',
|
||||
color: '#ffffff',
|
||||
fontFamily: 'AliBold',
|
||||
marginRight: 8,
|
||||
},
|
||||
mainStatUnit: {
|
||||
fontSize: 20,
|
||||
fontWeight: '600',
|
||||
color: 'rgba(255, 255, 255, 0.9)',
|
||||
fontFamily: 'AliRegular',
|
||||
},
|
||||
totalLossTag: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.2)',
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 12,
|
||||
alignSelf: 'flex-start',
|
||||
},
|
||||
totalLossText: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
color: '#ffffff',
|
||||
marginLeft: 4,
|
||||
fontFamily: 'AliBold',
|
||||
},
|
||||
statIconBg: {
|
||||
position: 'absolute',
|
||||
right: -20,
|
||||
bottom: -20,
|
||||
width: 140,
|
||||
height: 140,
|
||||
opacity: 0.2,
|
||||
transform: [{ rotate: '-15deg' }],
|
||||
tintColor: '#ffffff'
|
||||
},
|
||||
secondaryStatsRow: {
|
||||
flexDirection: 'row',
|
||||
gap: 16,
|
||||
},
|
||||
secondaryStatCard: {
|
||||
flex: 1,
|
||||
backgroundColor: '#ffffff',
|
||||
borderRadius: 24,
|
||||
padding: 16,
|
||||
shadowColor: 'rgba(30, 41, 59, 0.06)',
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 12,
|
||||
elevation: 3,
|
||||
},
|
||||
monthTitleRow: {
|
||||
secondaryStatHeader: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'baseline',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 12,
|
||||
},
|
||||
monthNumber: {
|
||||
fontSize: 48,
|
||||
fontWeight: '800',
|
||||
color: '#192126',
|
||||
lineHeight: 48,
|
||||
secondaryStatLabel: {
|
||||
fontSize: 13,
|
||||
color: '#6f7ba7',
|
||||
fontFamily: 'AliRegular',
|
||||
},
|
||||
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: {
|
||||
secondaryStatValue: {
|
||||
fontSize: 20,
|
||||
fontWeight: '700',
|
||||
color: '#192126',
|
||||
color: '#1c1f3a',
|
||||
fontFamily: 'AliBold',
|
||||
},
|
||||
secondaryStatUnit: {
|
||||
fontSize: 14,
|
||||
color: '#6f7ba7',
|
||||
fontWeight: '500',
|
||||
fontFamily: 'AliRegular',
|
||||
marginLeft: 2,
|
||||
},
|
||||
|
||||
// History Section
|
||||
historySection: {
|
||||
paddingHorizontal: 24,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: '700',
|
||||
color: '#1c1f3a',
|
||||
marginBottom: 16,
|
||||
fontFamily: 'AliBold',
|
||||
},
|
||||
monthContainer: {
|
||||
marginBottom: 24,
|
||||
},
|
||||
monthHeader: {
|
||||
marginBottom: 12,
|
||||
paddingHorizontal: 4,
|
||||
},
|
||||
monthTitle: {
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
color: '#6f7ba7',
|
||||
fontFamily: 'AliRegular',
|
||||
},
|
||||
recordsList: {
|
||||
gap: 12,
|
||||
},
|
||||
|
||||
emptyContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minHeight: 300,
|
||||
paddingVertical: 60,
|
||||
},
|
||||
emptyContent: {
|
||||
alignItems: 'center',
|
||||
@@ -547,145 +668,161 @@ const styles = StyleSheet.create({
|
||||
emptyText: {
|
||||
fontSize: 16,
|
||||
fontWeight: '700',
|
||||
color: '#192126',
|
||||
color: '#1c1f3a',
|
||||
marginBottom: 8,
|
||||
fontFamily: 'AliBold',
|
||||
},
|
||||
emptySubtext: {
|
||||
fontSize: 14,
|
||||
color: '#687076',
|
||||
fontFamily: 'AliRegular',
|
||||
},
|
||||
// Modal Styles
|
||||
|
||||
// Modal Styles (Retain but refined)
|
||||
modalContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
modalBackdrop: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: 'rgba(0,0,0,0.35)',
|
||||
backgroundColor: 'rgba(0,0,0,0.4)',
|
||||
},
|
||||
modalSheet: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
borderTopLeftRadius: 32,
|
||||
borderTopRightRadius: 32,
|
||||
maxHeight: '85%',
|
||||
minHeight: 500,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: -4 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 12,
|
||||
elevation: 10,
|
||||
},
|
||||
modalHeader: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: 20,
|
||||
paddingTop: 20,
|
||||
paddingBottom: 10,
|
||||
paddingHorizontal: 24,
|
||||
paddingTop: 24,
|
||||
paddingBottom: 16,
|
||||
},
|
||||
modalTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
fontWeight: '700',
|
||||
color: '#1c1f3a',
|
||||
fontFamily: 'AliBold',
|
||||
},
|
||||
modalContent: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 20,
|
||||
paddingHorizontal: 24,
|
||||
},
|
||||
inputSection: {
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderRadius: 16,
|
||||
padding: 16,
|
||||
marginBottom: 12,
|
||||
backgroundColor: '#F8F9FC',
|
||||
borderRadius: 24,
|
||||
padding: 24,
|
||||
marginBottom: 24,
|
||||
marginTop: 8,
|
||||
},
|
||||
weightInputContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 8,
|
||||
},
|
||||
weightIcon: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 16,
|
||||
backgroundColor: '#F0F9FF',
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 24,
|
||||
backgroundColor: '#EEF0FF',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginRight: 12,
|
||||
marginRight: 16,
|
||||
},
|
||||
inputWrapper: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
alignItems: 'baseline',
|
||||
borderBottomWidth: 2,
|
||||
borderBottomColor: '#E5E7EB',
|
||||
paddingBottom: 6,
|
||||
borderBottomColor: '#E2E8F0',
|
||||
paddingBottom: 8,
|
||||
},
|
||||
weightDisplay: {
|
||||
flex: 1,
|
||||
fontSize: 24,
|
||||
fontWeight: '600',
|
||||
fontSize: 36,
|
||||
fontWeight: '700',
|
||||
textAlign: 'center',
|
||||
paddingVertical: 4,
|
||||
color: '#1c1f3a',
|
||||
fontFamily: 'AliBold',
|
||||
},
|
||||
unitLabel: {
|
||||
fontSize: 18,
|
||||
fontWeight: '500',
|
||||
fontWeight: '600',
|
||||
color: '#6f7ba7',
|
||||
marginLeft: 8,
|
||||
},
|
||||
hintText: {
|
||||
fontSize: 12,
|
||||
textAlign: 'center',
|
||||
marginTop: 4,
|
||||
fontFamily: 'AliRegular',
|
||||
},
|
||||
quickSelectionSection: {
|
||||
paddingHorizontal: 4,
|
||||
marginBottom: 20,
|
||||
marginBottom: 24,
|
||||
},
|
||||
quickSelectionTitle: {
|
||||
fontSize: 16,
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
color: '#6f7ba7',
|
||||
marginBottom: 12,
|
||||
textAlign: 'center',
|
||||
fontFamily: 'AliRegular',
|
||||
marginLeft: 4,
|
||||
},
|
||||
quickButtons: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
quickButton: {
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 18,
|
||||
backgroundColor: '#F3F4F6',
|
||||
borderWidth: 1,
|
||||
borderColor: '#E5E7EB',
|
||||
minWidth: 60,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 10,
|
||||
borderRadius: 20,
|
||||
backgroundColor: '#F1F5F9',
|
||||
minWidth: 64,
|
||||
alignItems: 'center',
|
||||
},
|
||||
quickButtonSelected: {
|
||||
backgroundColor: '#6366F1',
|
||||
borderColor: '#6366F1',
|
||||
backgroundColor: '#4F5BD5',
|
||||
},
|
||||
quickButtonText: {
|
||||
fontSize: 13,
|
||||
fontWeight: '500',
|
||||
color: '#6B7280',
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
color: '#64748B',
|
||||
fontFamily: 'AliRegular',
|
||||
},
|
||||
quickButtonTextSelected: {
|
||||
color: '#FFFFFF',
|
||||
fontWeight: '600',
|
||||
fontWeight: '700',
|
||||
},
|
||||
modalFooter: {
|
||||
paddingHorizontal: 20,
|
||||
paddingHorizontal: 24,
|
||||
paddingTop: 16,
|
||||
paddingBottom: 25,
|
||||
paddingBottom: 34,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: '#F1F5F9',
|
||||
},
|
||||
saveButton: {
|
||||
backgroundColor: '#6366F1',
|
||||
borderRadius: 16,
|
||||
borderRadius: 24,
|
||||
overflow: 'hidden',
|
||||
shadowColor: '#4F5BD5',
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 12,
|
||||
elevation: 8,
|
||||
},
|
||||
saveButtonGradient: {
|
||||
paddingVertical: 16,
|
||||
alignItems: 'center',
|
||||
},
|
||||
saveButtonText: {
|
||||
color: '#FFFFFF',
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
fontWeight: '700',
|
||||
fontFamily: 'AliBold',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user