128 lines
3.6 KiB
TypeScript
128 lines
3.6 KiB
TypeScript
import React from 'react';
|
||
import { View, StyleSheet, TouchableOpacity, Text, Platform, ActivityIndicator } from 'react-native';
|
||
import { useTranslation } from 'react-i18next';
|
||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||
import { LinearGradient } from 'expo-linear-gradient';
|
||
import { OnboardingColors } from '@/constants/OnboardingTheme';
|
||
import AddIcon from '@/assets/images/icon/add_icon.svg';
|
||
import ReduceIcon from '@/assets/images/icon/reduce_icon.svg';
|
||
import BtnClicked from '@/assets/images/icon/btn_clicked.svg';
|
||
|
||
interface ReminderStepProps {
|
||
value: number;
|
||
onChange: (value: number) => void;
|
||
onFinish: () => void;
|
||
onSkip?: () => void;
|
||
/** 完成后请求通知权限时的加载态 */
|
||
loading?: boolean;
|
||
}
|
||
|
||
export function ReminderStep({ value, onChange, onFinish, loading = false }: ReminderStepProps) {
|
||
const { t } = useTranslation();
|
||
const insets = useSafeAreaInsets();
|
||
|
||
const handleReduce = () => {
|
||
// 本页最小为 1;不接收提醒请使用右上角 Skip
|
||
if (value > 1) onChange(value - 1);
|
||
};
|
||
|
||
const handleAdd = () => {
|
||
if (value < 5) onChange(value + 1);
|
||
};
|
||
|
||
return (
|
||
<View style={styles.container}>
|
||
<View style={styles.counterContainer}>
|
||
<TouchableOpacity onPress={handleReduce} disabled={loading} activeOpacity={0.7}>
|
||
<ReduceIcon width={47} height={47} />
|
||
</TouchableOpacity>
|
||
|
||
<View style={styles.numberWrapper}>
|
||
<Text style={styles.numberText}>{value}</Text>
|
||
<Text style={styles.unitText}>
|
||
{value === 1 ? t('dailyReminder.timesUnitSingular') : t('dailyReminder.timesUnit')}
|
||
</Text>
|
||
</View>
|
||
|
||
<TouchableOpacity onPress={handleAdd} disabled={loading} activeOpacity={0.7}>
|
||
<AddIcon width={47} height={47} />
|
||
</TouchableOpacity>
|
||
</View>
|
||
|
||
<View style={[styles.footer, { bottom: insets.bottom + 16 }]}>
|
||
<TouchableOpacity onPress={onFinish} disabled={loading} activeOpacity={0.8}>
|
||
<View style={styles.finishWrap}>
|
||
{loading ? (
|
||
<LinearGradient
|
||
colors={['#F69F7B', '#F99CC0']}
|
||
start={{ x: 0, y: 0 }}
|
||
end={{ x: 1, y: 0 }}
|
||
style={[styles.loadingPill, styles.finishDisabled]}
|
||
>
|
||
<ActivityIndicator size="small" color="#FFFFFF" />
|
||
</LinearGradient>
|
||
) : (
|
||
<BtnClicked width={87} height={57} />
|
||
)}
|
||
</View>
|
||
</TouchableOpacity>
|
||
</View>
|
||
</View>
|
||
);
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
flex: 1,
|
||
alignItems: 'center',
|
||
paddingTop: 20,
|
||
},
|
||
counterContainer: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
width: '100%',
|
||
marginTop: 40,
|
||
},
|
||
numberWrapper: {
|
||
flexDirection: 'row',
|
||
alignItems: 'flex-end',
|
||
marginHorizontal: 40,
|
||
},
|
||
numberText: {
|
||
fontSize: 107,
|
||
fontFamily: Platform.OS === 'ios' ? 'STIX Two Text' : 'serif',
|
||
fontWeight: '600',
|
||
color: OnboardingColors.textPrimary,
|
||
lineHeight: 120,
|
||
},
|
||
unitText: {
|
||
fontSize: 17,
|
||
fontFamily: Platform.OS === 'ios' ? 'STIX Two Text' : 'serif',
|
||
fontWeight: '600',
|
||
color: OnboardingColors.textPrimary,
|
||
marginBottom: 20,
|
||
marginLeft: 4,
|
||
},
|
||
footer: {
|
||
position: 'absolute',
|
||
alignItems: 'center',
|
||
},
|
||
finishWrap: {
|
||
width: 87,
|
||
height: 57,
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
},
|
||
finishDisabled: {
|
||
opacity: 0.7,
|
||
},
|
||
loadingPill: {
|
||
width: 87,
|
||
height: 57,
|
||
borderRadius: 28.5,
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
},
|
||
});
|