feat: 个人信息优化
This commit is contained in:
parent
11ceca9753
commit
7c4d1529d4
BIN
assets/images/png/icon/doneIP.png
Normal file
BIN
assets/images/png/icon/doneIP.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
49
components/ui/button/stepButton.tsx
Normal file
49
components/ui/button/stepButton.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { ThemedText } from "@/components/ThemedText";
|
||||||
|
import { ActivityIndicator, StyleSheet, TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isLoading?: boolean;
|
||||||
|
onPress?: () => void;
|
||||||
|
text: string
|
||||||
|
bg?: string
|
||||||
|
color?: string
|
||||||
|
}
|
||||||
|
const StepButton = (props: Props) => {
|
||||||
|
const { isLoading, onPress, text, bg, color } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.button, isLoading && styles.disabledButton, { backgroundColor: bg ? bg : '#E2793F' }]}
|
||||||
|
onPress={onPress}
|
||||||
|
disabled={isLoading}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<ActivityIndicator color="#fff" />
|
||||||
|
) : (
|
||||||
|
<ThemedText style={[styles.buttonText, { color: color ? color : '#FFFFFF' }]}>
|
||||||
|
{text}
|
||||||
|
</ThemedText>
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
button: {
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: '#E2793F',
|
||||||
|
borderRadius: 32,
|
||||||
|
padding: 18,
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
disabledButton: {
|
||||||
|
opacity: 0.7,
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
color: '#FFFFFF',
|
||||||
|
fontWeight: '600',
|
||||||
|
fontSize: 18,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default StepButton
|
||||||
@ -1,66 +1,98 @@
|
|||||||
import DoneSvg from '@/assets/icons/svg/done.svg';
|
|
||||||
import { router } from 'expo-router';
|
import { router } from 'expo-router';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Platform, TouchableOpacity, View } from 'react-native';
|
import { Dimensions, Image, PixelRatio, Platform, StyleSheet, View } from 'react-native';
|
||||||
|
import Animated, {
|
||||||
|
Easing,
|
||||||
|
useAnimatedStyle,
|
||||||
|
useSharedValue,
|
||||||
|
withTiming
|
||||||
|
} from 'react-native-reanimated';
|
||||||
import { ThemedText } from '../ThemedText';
|
import { ThemedText } from '../ThemedText';
|
||||||
import { Fireworks } from '../firework';
|
import { Fireworks } from '../firework';
|
||||||
import Lottie from '../lottie/lottie';
|
import StepButton from '../ui/button/stepButton';
|
||||||
|
|
||||||
export default function Done() {
|
export default function Done() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const height = Dimensions.get('window').height;
|
||||||
|
const fontSize = (size: number) => {
|
||||||
|
const scale = PixelRatio.getFontScale();
|
||||||
|
return size / scale;
|
||||||
|
};
|
||||||
|
// Animation values
|
||||||
|
const translateX = useSharedValue(300);
|
||||||
|
const translateY = useSharedValue(300);
|
||||||
|
const opacity = useSharedValue(0);
|
||||||
|
|
||||||
|
// Animation style
|
||||||
|
const animatedStyle = useAnimatedStyle(() => ({
|
||||||
|
transform: [
|
||||||
|
{ translateX: translateX.value },
|
||||||
|
{ translateY: translateY.value }
|
||||||
|
],
|
||||||
|
opacity: opacity.value
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Start animation when component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
translateX.value = withTiming(0, {
|
||||||
|
duration: 800,
|
||||||
|
easing: Easing.out(Easing.cubic)
|
||||||
|
});
|
||||||
|
translateY.value = withTiming(0, {
|
||||||
|
duration: 800,
|
||||||
|
easing: Easing.out(Easing.cubic)
|
||||||
|
});
|
||||||
|
opacity.value = withTiming(1, {
|
||||||
|
duration: 1000,
|
||||||
|
easing: Easing.out(Easing.cubic)
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleContinue = () => {
|
const handleContinue = () => {
|
||||||
router.replace('/ask')
|
router.replace('/ask')
|
||||||
};
|
};
|
||||||
return (
|
|
||||||
<View className="flex-1">
|
const renderWebView = () => (
|
||||||
{
|
<View style={styles.webContainer}>
|
||||||
Platform.OS === 'web'
|
<View style={styles.webContent}>
|
||||||
?
|
<ThemedText style={styles.title}>
|
||||||
<View className="flex-1 bg-bgPrimary absolute top-0 left-0 right-0 bottom-0 h-full">
|
|
||||||
<View className="absolute top-[2rem] left-0 right-0 bottom-[10rem] justify-center items-center">
|
|
||||||
<ThemedText className="!text-4xl !text-white text-center">
|
|
||||||
{t('auth.userMessage.allDone', { ns: 'login' })}
|
{t('auth.userMessage.allDone', { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
</View>
|
</View>
|
||||||
<View className='flex-1' />
|
<View style={styles.flex1} />
|
||||||
<View className="flex-row justify-end">
|
<View style={styles.lottieContainer}>
|
||||||
<DoneSvg />
|
<Animated.View style={animatedStyle}>
|
||||||
|
<Image
|
||||||
|
source={require('@/assets/images/png/icon/doneIP.png')}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
</View>
|
</View>
|
||||||
{/* Next Button */}
|
<View style={styles.webButtonContainer}>
|
||||||
<View className="absolute bottom-[1rem] left-0 right-0 p-[1rem] z-99">
|
<StepButton
|
||||||
<TouchableOpacity
|
text={t('auth.userMessage.next', { ns: 'login' })}
|
||||||
className={`w-full bg-buttonFill rounded-full p-4 items-center`}
|
|
||||||
onPress={handleContinue}
|
onPress={handleContinue}
|
||||||
>
|
/>
|
||||||
<ThemedText className="!text-white text-lg font-semibold">
|
|
||||||
{t('auth.userMessage.next', { ns: 'login' })}
|
|
||||||
</ThemedText>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
:
|
);
|
||||||
<View className="flex-1 bg-transparent">
|
|
||||||
{/* 文字 */}
|
const renderMobileView = () => (
|
||||||
<View className="absolute top-0 left-0 right-0 bottom-0 z-30">
|
<View style={styles.mobileContainer}>
|
||||||
<View className="flex-1 justify-center items-center">
|
<View style={styles.mobileContent}>
|
||||||
<ThemedText className="!text-4xl !text-white text-center">
|
<View style={[styles.mobileTextContainer, { marginTop: -height * 0.15 }]}>
|
||||||
|
<ThemedText style={[styles.title, { fontSize: fontSize(36) }]}>
|
||||||
{t('auth.userMessage.allDone', { ns: 'login' })}
|
{t('auth.userMessage.allDone', { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
</View>
|
</View>
|
||||||
{/* Next Button */}
|
<View style={styles.mobileButtonContainer}>
|
||||||
<View className="absolute bottom-[1rem] left-0 right-0 p-[1rem] z-99">
|
<StepButton
|
||||||
<TouchableOpacity
|
text={t('auth.userMessage.next', { ns: 'login' })}
|
||||||
className={`w-full bg-buttonFill rounded-full p-4 items-center`}
|
|
||||||
onPress={handleContinue}
|
onPress={handleContinue}
|
||||||
>
|
/>
|
||||||
<ThemedText className="!text-white text-lg font-semibold">
|
|
||||||
{t('auth.userMessage.next', { ns: 'login' })}
|
|
||||||
</ThemedText>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{/* 背景动画 - 烟花 */}
|
<View style={styles.fireworksContainer}>
|
||||||
<View className="absolute top-0 left-0 right-0 bottom-0 z-10">
|
|
||||||
<Fireworks
|
<Fireworks
|
||||||
autoPlay={true}
|
autoPlay={true}
|
||||||
loop={false}
|
loop={false}
|
||||||
@ -68,22 +100,117 @@ export default function Done() {
|
|||||||
particleCount={90}
|
particleCount={90}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
<View style={styles.lottieContainer}>
|
||||||
{/* 前景动画 - Lottie */}
|
<Animated.View style={animatedStyle}>
|
||||||
<View className="absolute top-0 left-0 right-0 bottom-0 z-20">
|
<Image
|
||||||
<Lottie
|
source={require('@/assets/images/png/icon/doneIP.png')}
|
||||||
source={'allDone'}
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
backgroundColor: 'transparent'
|
|
||||||
}}
|
|
||||||
loop={false}
|
|
||||||
/>
|
/>
|
||||||
|
</Animated.View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
{Platform.OS === 'web' ? renderWebView() : renderMobileView()}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
</View>
|
const styles = StyleSheet.create({
|
||||||
)
|
container: {
|
||||||
}
|
flex: 1,
|
||||||
|
},
|
||||||
|
flex1: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
webContainer: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#FFB645',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
webContent: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 32,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 160,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
doneSvgContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
|
webButtonContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 16,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
padding: 16,
|
||||||
|
zIndex: 99,
|
||||||
|
},
|
||||||
|
mobileContainer: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
},
|
||||||
|
mobileContent: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
zIndex: 30,
|
||||||
|
},
|
||||||
|
mobileTextContainer: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
mobileButtonContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 16,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
padding: 16,
|
||||||
|
zIndex: 99,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 36,
|
||||||
|
lineHeight: 40,
|
||||||
|
color: '#FFFFFF',
|
||||||
|
textAlign: 'center',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
nextButton: {
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: '#3B82F6',
|
||||||
|
borderRadius: 999,
|
||||||
|
padding: 16,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
color: '#FFFFFF',
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
fireworksContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
zIndex: 10,
|
||||||
|
},
|
||||||
|
lottieContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
zIndex: 20
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@ -4,8 +4,10 @@ import LookSvg from '@/assets/icons/svg/look.svg';
|
|||||||
import { ThemedText } from '@/components/ThemedText';
|
import { ThemedText } from '@/components/ThemedText';
|
||||||
import { FileUploadItem } from '@/lib/background-uploader/types';
|
import { FileUploadItem } from '@/lib/background-uploader/types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ActivityIndicator, Alert, Image, TouchableOpacity, View } from 'react-native';
|
import { Alert, Image, StyleSheet, View } from 'react-native';
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import FilesUploader from '../file-upload/files-uploader';
|
import FilesUploader from '../file-upload/files-uploader';
|
||||||
|
import StepButton from '../ui/button/stepButton';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
setSteps?: (steps: Steps) => void;
|
setSteps?: (steps: Steps) => void;
|
||||||
@ -19,57 +21,51 @@ interface Props {
|
|||||||
export default function Look(props: Props) {
|
export default function Look(props: Props) {
|
||||||
const { fileData, setFileData, isLoading, handleUser, avatar } = props;
|
const { fileData, setFileData, isLoading, handleUser, avatar } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="flex-1 bg-textPrimary justify-between p-[2rem]">
|
<View style={[styles.container, { paddingBottom: insets.bottom, paddingTop: insets.top + 28 }]}>
|
||||||
<View className="flex-1 justify-center items-center">
|
<View style={styles.contentContainer}>
|
||||||
<ThemedText className="text-4xl font-bold !text-white mb-[2rem]">
|
<ThemedText style={styles.title}>
|
||||||
{t('auth.userMessage.look', { ns: 'login' })}
|
{t('auth.userMessage.look', { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<ThemedText className="text-base !text-white/80 text-center mb-[2rem]">
|
<ThemedText style={styles.subtitle}>
|
||||||
{t('auth.userMessage.avatarText', { ns: 'login' })}
|
{t('auth.userMessage.avatarText', { ns: 'login' })}
|
||||||
{"\n"}
|
{"\n"}
|
||||||
{t('auth.userMessage.avatorText2', { ns: 'login' })}
|
{t('auth.userMessage.avatorText2', { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
{
|
{fileData[0]?.preview || fileData[0]?.previewUrl ? (
|
||||||
fileData[0]?.preview || fileData[0]?.previewUrl
|
|
||||||
?
|
|
||||||
<Image
|
<Image
|
||||||
className='rounded-full w-[10rem] h-[10rem]'
|
style={styles.avatarImage}
|
||||||
source={{ uri: fileData[0].preview || fileData[0].previewUrl }}
|
source={{ uri: fileData[0].preview || fileData[0].previewUrl }}
|
||||||
/>
|
/>
|
||||||
:
|
) : avatar ? (
|
||||||
avatar
|
|
||||||
?
|
|
||||||
<Image
|
<Image
|
||||||
className='rounded-full w-[10rem] h-[10rem]'
|
style={styles.avatarImage}
|
||||||
source={{ uri: avatar }}
|
source={{ uri: avatar }}
|
||||||
/>
|
/>
|
||||||
:
|
) : (
|
||||||
<LookSvg />
|
<LookSvg />
|
||||||
}
|
)}
|
||||||
<FilesUploader
|
<FilesUploader
|
||||||
onUploadComplete={(fileData) => {
|
onUploadComplete={(fileData) => {
|
||||||
setFileData(fileData as FileUploadItem[]);
|
setFileData(fileData as FileUploadItem[]);
|
||||||
}}
|
}}
|
||||||
showPreview={false}
|
showPreview={false}
|
||||||
children={
|
children={
|
||||||
<View className="w-full rounded-full px-4 py-2 mt-4 items-center bg-inputBackground flex-row flex gap-2">
|
<View style={styles.uploadButton}>
|
||||||
<ChoicePhoto />
|
<ChoicePhoto />
|
||||||
<ThemedText className="text-textTertiary text-lg font-semibold">
|
<ThemedText style={styles.uploadButtonText}>
|
||||||
{t('auth.userMessage.choosePhoto', { ns: 'login' })}
|
{t('auth.userMessage.choosePhoto', { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
</View>
|
</View>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{/* <AutoUploadScreen /> */}
|
|
||||||
{/* <MediaStatsScreen /> */}
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View className="w-full">
|
<View style={styles.footer}>
|
||||||
<TouchableOpacity
|
<StepButton
|
||||||
className={`w-full bg-white rounded-full p-4 items-center ${isLoading ? 'opacity-70' : ''}`}
|
text={t('auth.userMessage.next', { ns: 'login' })}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (fileData[0]?.preview || fileData[0]?.previewUrl || avatar) {
|
if (fileData[0]?.preview || fileData[0]?.previewUrl || avatar) {
|
||||||
handleUser()
|
handleUser()
|
||||||
@ -77,17 +73,61 @@ export default function Look(props: Props) {
|
|||||||
Alert.alert(t('auth.userMessage.avatarRequired', { ns: 'login' }))
|
Alert.alert(t('auth.userMessage.avatarRequired', { ns: 'login' }))
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={isLoading}
|
isLoading={isLoading}
|
||||||
>
|
bg="#FFFFFF"
|
||||||
{isLoading ? (
|
color="#4C320C"
|
||||||
<ActivityIndicator color="#000" />
|
/>
|
||||||
) : (
|
|
||||||
<ThemedText className="text-textTertiary text-lg font-semibold">
|
|
||||||
{t('auth.userMessage.next', { ns: 'login' })}
|
|
||||||
</ThemedText>
|
|
||||||
)}
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#AC7E35',
|
||||||
|
paddingHorizontal: 24,
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
contentContainer: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 28
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 32,
|
||||||
|
lineHeight: 36,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#FFFFFF',
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
avatarImage: {
|
||||||
|
borderRadius: 150,
|
||||||
|
width: 215,
|
||||||
|
height: 215,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
uploadButton: {
|
||||||
|
width: '100%',
|
||||||
|
borderRadius: 999,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 13,
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#FFF8DE',
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: 8,
|
||||||
|
},
|
||||||
|
uploadButtonText: {
|
||||||
|
color: '#4C320C',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
width: '100%',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@ -2,7 +2,9 @@ import { Steps } from '@/app/(tabs)/user-message';
|
|||||||
import { ThemedText } from '@/components/ThemedText';
|
import { ThemedText } from '@/components/ThemedText';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ActivityIndicator, KeyboardAvoidingView, Platform, TextInput, TouchableOpacity, View } from 'react-native';
|
import { Dimensions, KeyboardAvoidingView, Platform, StyleSheet, TextInput, View } from 'react-native';
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
|
import StepButton from '../ui/button/stepButton';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
setSteps: (steps: Steps) => void;
|
setSteps: (steps: Steps) => void;
|
||||||
@ -14,6 +16,8 @@ export default function UserName(props: Props) {
|
|||||||
const { setSteps, username, setUsername } = props
|
const { setSteps, username, setUsername } = props
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const height = Dimensions.get('window').height;
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
const handleUserName = () => {
|
const handleUserName = () => {
|
||||||
if (!username) {
|
if (!username) {
|
||||||
@ -28,45 +32,101 @@ export default function UserName(props: Props) {
|
|||||||
return (
|
return (
|
||||||
<KeyboardAvoidingView
|
<KeyboardAvoidingView
|
||||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
style={{ flex: 1 }}
|
style={styles.keyboardAvoidingView}
|
||||||
>
|
>
|
||||||
<View className='bg-bgPrimary flex-1 h-full'>
|
<View style={[styles.container]}>
|
||||||
<View className="flex-1" />
|
<View style={styles.flex1} />
|
||||||
{/* Input container fixed at bottom */}
|
<View style={[styles.inputContainer, { paddingBottom: insets.bottom }]}>
|
||||||
<View className="w-full bg-white p-4 border-t border-gray-200 rounded-t-3xl">
|
<View style={styles.contentContainer}>
|
||||||
<View className="flex-col items-center justify-center w-full gap-[1rem]">
|
<View style={styles.titleContainer}>
|
||||||
<View className='w-full flex flex-row items-center justify-center'>
|
<ThemedText style={styles.titleText}>{t('auth.userMessage.title', { ns: 'login' })}</ThemedText>
|
||||||
<ThemedText className="text-textSecondary font-semibold">{t('auth.userMessage.title', { ns: 'login' })}</ThemedText>
|
|
||||||
</View>
|
</View>
|
||||||
<View className='w-full mb-[1rem]'>
|
<View style={styles.inputWrapper}>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
|
<View style={styles.labelContainer}>
|
||||||
<ThemedText className="!text-textPrimary ml-2 mb-2 font-semibold">{t('auth.userMessage.username', { ns: 'login' })}</ThemedText>
|
<ThemedText style={styles.labelText}>{t('auth.userMessage.username', { ns: 'login' })}</ThemedText>
|
||||||
<ThemedText style={{ color: "#E2793F", fontSize: 14 }}>{error}</ThemedText>
|
<ThemedText style={styles.errorText}>{error}</ThemedText>
|
||||||
</View>
|
</View>
|
||||||
<TextInput
|
<TextInput
|
||||||
className="bg-inputBackground rounded-2xl p-4 w-full"
|
style={[styles.textInput, { marginBottom: height * 0.2 }]}
|
||||||
placeholder={t('auth.userMessage.usernamePlaceholder', { ns: 'login' })}
|
placeholder={t('auth.userMessage.usernamePlaceholder', { ns: 'login' })}
|
||||||
placeholderTextColor="#9CA3AF"
|
placeholderTextColor="#9CA3AF"
|
||||||
value={username}
|
value={username}
|
||||||
onChangeText={setUsername}
|
onChangeText={setUsername}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity
|
<StepButton text={t('auth.userMessage.next', { ns: 'login' })} onPress={handleUserName} isLoading={isLoading} />
|
||||||
className={`w-full bg-[#E2793F] rounded-full text-[#fff] p-4 items-center mb-6 ${isLoading ? 'opacity-70' : ''} rounded-2xl`}
|
|
||||||
onPress={handleUserName}
|
|
||||||
disabled={isLoading}
|
|
||||||
>
|
|
||||||
{isLoading ? (
|
|
||||||
<ActivityIndicator color="#fff" />
|
|
||||||
) : (
|
|
||||||
<ThemedText className="!text-white font-semibold">
|
|
||||||
{t('auth.userMessage.next', { ns: 'login' })}
|
|
||||||
</ThemedText>
|
|
||||||
)}
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</KeyboardAvoidingView>
|
</KeyboardAvoidingView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
keyboardAvoidingView: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#FFB645',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
flex1: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
inputContainer: {
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
padding: 16,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderTopColor: '#E5E7EB',
|
||||||
|
borderTopLeftRadius: 50,
|
||||||
|
borderTopRightRadius: 50,
|
||||||
|
},
|
||||||
|
contentContainer: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: '100%',
|
||||||
|
gap: 16,
|
||||||
|
},
|
||||||
|
titleContainer: {
|
||||||
|
width: '100%',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
titleText: {
|
||||||
|
color: '#4C320C',
|
||||||
|
fontWeight: '600',
|
||||||
|
fontSize: 20,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
inputWrapper: {
|
||||||
|
width: '100%',
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
labelContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
labelText: {
|
||||||
|
color: '#AC7E35',
|
||||||
|
marginLeft: 8,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
errorText: {
|
||||||
|
color: '#E2793F',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
textInput: {
|
||||||
|
backgroundColor: '#FFF8DE',
|
||||||
|
borderRadius: 16,
|
||||||
|
padding: 20,
|
||||||
|
width: '100%',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user