117 lines
5.0 KiB
TypeScript
117 lines
5.0 KiB
TypeScript
import UserSvg from '@/assets/icons/svg/ataver.svg';
|
||
import SettingSvg from '@/assets/icons/svg/setting.svg';
|
||
import StarSvg from '@/assets/icons/svg/star.svg';
|
||
import { ThemedText } from '@/components/ThemedText';
|
||
import { UserInfoDetails } from '@/types/user';
|
||
import { useRouter } from 'expo-router';
|
||
import { useState } from 'react';
|
||
import { Image, ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native';
|
||
import CopyButton from '../copy';
|
||
|
||
export default function UserInfo({ userInfo }: { userInfo: UserInfoDetails }) {
|
||
// 添加状态来跟踪图片加载状态
|
||
const [imageError, setImageError] = useState(false);
|
||
const router = useRouter();
|
||
|
||
return (
|
||
<View className='flex flex-row justify-between items-center mt-[1rem] gap-[1rem] w-full'>
|
||
{/* 头像 */}
|
||
<View className='w-auto'>
|
||
{userInfo?.user_info?.avatar_file_url && !imageError ? (
|
||
<Image
|
||
source={{ uri: userInfo.user_info.avatar_file_url }}
|
||
style={{ width: 70, height: 70, borderRadius: 40 }}
|
||
onError={() => {
|
||
setImageError(true);
|
||
}}
|
||
/>
|
||
) : (
|
||
<UserSvg width={70} height={70} />
|
||
)}
|
||
</View>
|
||
{/* 用户名 */}
|
||
<View className='flex flex-col w-[75%] gap-1'>
|
||
<View className='flex flex-row items-center justify-between w-full'>
|
||
<View className='flex flex-row items-center gap-2 w-full'>
|
||
<ThemedText
|
||
className='max-w-[80%] !text-textSecondary !font-semibold !text-2xl'
|
||
numberOfLines={1} // 限制为1行
|
||
ellipsizeMode="tail"
|
||
>
|
||
{userInfo?.user_info?.nickname}
|
||
</ThemedText>
|
||
<ScrollView
|
||
className='max-w-[20%]'
|
||
horizontal // 水平滚动
|
||
showsHorizontalScrollIndicator={false} // 隐藏滚动条
|
||
contentContainerStyle={{
|
||
flexDirection: 'row',
|
||
gap: 8, // 间距,
|
||
alignItems: 'center',
|
||
}}
|
||
>
|
||
{
|
||
userInfo?.medal_infos?.map((item, index) => (
|
||
<Image
|
||
key={index}
|
||
source={{ uri: item.url }}
|
||
style={{ width: 24, height: 24 }}
|
||
/>
|
||
))
|
||
}
|
||
</ScrollView>
|
||
|
||
<View className='flex flex-row items-center gap-2 border border-bgPrimary px-2 py-1 rounded-full'>
|
||
<StarSvg />
|
||
<ThemedText style={{ color: 'bgPrimary', fontSize: 14, fontWeight: '700' }}>{userInfo?.remain_points}</ThemedText>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
<View className='flex flex-row items-center justify-between w-full'>
|
||
<View style={{ flex: 1, flexDirection: "row", alignItems: "center", gap: 2, maxWidth: '80%' }}>
|
||
<ThemedText
|
||
style={{
|
||
color: '#AC7E35',
|
||
fontSize: 12,
|
||
fontWeight: '600',
|
||
flexShrink: 1,
|
||
flexGrow: 0,
|
||
}}
|
||
numberOfLines={1}
|
||
ellipsizeMode="tail"
|
||
>
|
||
User ID:{userInfo?.user_info?.user_id}
|
||
</ThemedText>
|
||
<CopyButton textToCopy={userInfo?.user_info?.user_id || ""} />
|
||
</View>
|
||
<TouchableOpacity
|
||
onPress={() => {
|
||
router.push('/setting');
|
||
}}
|
||
activeOpacity={0.7}
|
||
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
||
style={styles.text}
|
||
>
|
||
<SettingSvg />
|
||
</TouchableOpacity>
|
||
</View>
|
||
</View>
|
||
</View >
|
||
);
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
text: {
|
||
fontSize: 12,
|
||
fontWeight: '700',
|
||
color: '#AC7E35',
|
||
borderColor: '#FFD18A',
|
||
borderWidth: 1,
|
||
borderRadius: 20,
|
||
padding: 4,
|
||
textAlign: "center",
|
||
alignItems: "center",
|
||
paddingVertical: 6,
|
||
paddingHorizontal: 12
|
||
}
|
||
}); |