Files
cpost-mobile/src/screens/profile/myProfile/ui/ProfileHeader.tsx
Samandar Turgunboyev 684d09e6b5 added login modal
2025-11-24 10:52:21 +05:00

339 lines
8.7 KiB
TypeScript

import { useQuery } from '@tanstack/react-query';
import { authApi } from 'api/auth';
import AppText from 'components/AppText';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
Image,
Linking,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native';
import ImagePicker from 'react-native-image-crop-picker';
import Modal from 'react-native-modal';
import SendIntentAndroid from 'react-native-send-intent';
import GalleryEdit from 'svg/GalleryEdit';
import Instagram from 'svg/Instagram';
import Plus from 'svg/Plus';
import Telegram from 'svg/Telegram';
import Trash from 'svg/Trash';
const ProfileHeader = ({ userName = 'Samandar' }: { userName?: string }) => {
const [imageError, setImageError] = useState(true);
const { t } = useTranslation();
const [selectedImage, setSelectedImage] = useState<string>(
'https://static.vecteezy.com/system/resources/previews/019/879/186/non_2x/user-icon-on-transparent-background-free-png.png',
);
const getStatusMeta = (status?: string) => {
const key = (status || '').toLowerCase();
switch (key) {
case 'active':
return { label: t('Faol'), bg: '#E6F7EE', fg: '#1F9254' };
case 'pending':
return { label: t('Kutilmoqda'), bg: '#FFF7E6', fg: '#B26A00' };
case 'inactive':
case 'blocked':
return { label: t('Faol emas'), bg: '#FDECEF', fg: '#A61D24' };
default:
return { label: t('Faol emas'), bg: '#EDF2F7', fg: '#A61D24' };
}
};
const { data: getMe } = useQuery({
queryKey: ['getMe'],
queryFn: authApi.getMe,
});
const [isModalVisible, setModalVisible] = useState(false);
const openGallery = async () => {
try {
const image = await ImagePicker.openPicker({
width: 0,
height: 0,
cropping: true,
cropperCircleOverlay: true,
freeStyleCropEnabled: true,
hideBottomControls: false,
cropperToolbarTitle: 'Edit Image',
cropperToolbarColor: '#28A7E8',
cropperToolbarWidgetColor: '#ffffff',
cropperStatusBarColor: '#28A7E8',
cropperActiveWidgetColor: '#28A7E8',
compressImageQuality: 0.8,
mediaType: 'photo',
forceJpg: true,
});
if (image?.path) {
setSelectedImage(image.path);
setImageError(false);
setModalVisible(false);
}
} catch (error) {}
};
const handleImagePress = () => {
if (!imageError) {
setModalVisible(true);
} else {
openGallery();
}
};
const removePhoto = () => {
setSelectedImage('');
setImageError(true);
setModalVisible(false);
};
const openTelegram = async () => {
const telegramUri = 'tg://resolve?domain=cpostuz';
try {
const success = await SendIntentAndroid.openAppWithUri(telegramUri);
if (!success) Linking.openURL('https://t.me/cpostuz');
} catch (error) {
Linking.openURL('https://t.me/cpostuz');
}
};
const openInstagram = async () => {
const instagramUri = 'instagram://user?username=cpost_cargo';
try {
const success = await SendIntentAndroid.openAppWithUri(instagramUri);
if (!success) Linking.openURL('https://instagram.com/cpost_cargo');
} catch (error) {
Linking.openURL('https://instagram.com/cpost_cargo');
}
};
const openFacebook = () => {
SendIntentAndroid.openAppWithData(
'com.facebook.katana',
'fb://page/PAGE_ID',
).catch(() => Linking.openURL('https://facebook.com/'));
};
const capitalizeWords = (str: string) => {
if (!str) return '';
return str
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(' ');
};
const formatPhone = (value: string) => {
const digits = value.replace(/\D/g, '');
if (digits.length === 0) return '';
const prefix = '+998 ';
let formattedNumber = prefix;
if (digits.length > 3) {
formattedNumber += `(${digits.slice(3, 5)}) `;
}
if (digits.length > 5) {
formattedNumber += digits.slice(5, 8);
}
if (digits.length > 8) {
formattedNumber += '-' + digits.slice(8, 10);
}
if (digits.length > 10) {
formattedNumber += '-' + digits.slice(10, 12);
}
return formattedNumber.trim();
};
return (
<View style={styles.container}>
<View style={styles.imageWrapper}>
{imageError ? (
<AppText style={styles.fallbackText}>
{getMe?.fullName.charAt(0).toUpperCase()}
</AppText>
) : (
<Image
source={{ uri: selectedImage }}
style={styles.image}
onError={() => setImageError(true)}
/>
)}
<TouchableOpacity style={styles.circle} onPress={handleImagePress}>
<Plus color="#FFFFFF" />
</TouchableOpacity>
</View>
<View style={styles.infoUser}>
<AppText style={styles.name}>
{capitalizeWords(getMe?.fullName || '')}
</AppText>
{getMe?.status && (
<View
style={[
styles.statusBadge,
{ backgroundColor: getStatusMeta(getMe.status).bg },
]}
>
<AppText
style={[
styles.statusText,
{ color: getStatusMeta(getMe.status).fg },
]}
>
{getStatusMeta(getMe.status).label}
</AppText>
</View>
)}
<AppText style={styles.userId}>ID: {getMe?.aviaCargoId}</AppText>
<AppText style={styles.telUser}>
{getMe?.phone ? formatPhone(getMe.phone) : ''}
</AppText>
</View>
<View style={styles.links}>
<TouchableOpacity onPress={openTelegram}>
<Telegram color="#28A7E8" width={24} height={24} />
</TouchableOpacity>
<TouchableOpacity onPress={openInstagram}>
<Instagram color="#28A7E8" width={24} height={24} />
</TouchableOpacity>
{/* <TouchableOpacity onPress={openFacebook}>
<MaterialIcons
name="facebook"
color="#28A7E8"
size={isSmallScreen ? 22 : 26}
/>
</TouchableOpacity> */}
</View>
<Modal
isVisible={isModalVisible}
onBackdropPress={() => setModalVisible(false)}
style={styles.modal}
>
<View style={styles.modalContent}>
<TouchableOpacity style={styles.modalBtn} onPress={openGallery}>
<GalleryEdit fill="#28A7E8" width={26} height={26} />
<AppText style={styles.modalText}>
{t("Rasmni o'zgartirish")}
</AppText>
</TouchableOpacity>
<TouchableOpacity style={styles.modalBtn} onPress={removePhoto}>
<Trash color="red" width={26} height={26} />
<AppText style={[styles.modalText, { color: 'red' }]}>
{t("Rasmni o'chirish")}
</AppText>
</TouchableOpacity>
</View>
</Modal>
</View>
);
};
const styles = StyleSheet.create({
container: {
marginTop: 10,
alignItems: 'center',
},
imageWrapper: {
width: 100,
height: 100,
borderRadius: 50,
backgroundColor: '#D3D6DA',
justifyContent: 'center',
alignItems: 'center',
},
image: {
width: 100,
height: 100,
resizeMode: 'cover',
borderRadius: 50,
},
fallbackText: {
fontSize: 50,
fontWeight: 'bold',
color: '#555',
},
circle: {
position: 'absolute',
bottom: -5,
right: 0,
backgroundColor: '#28A7E8',
zIndex: 10,
borderRadius: 50,
borderColor: '#FFFFFF',
borderWidth: 2,
padding: 5,
},
statusBadge: {
alignSelf: 'center',
marginTop: 5,
marginBottom: 10,
paddingHorizontal: 14,
paddingVertical: 4,
borderRadius: 20,
},
statusText: {
fontSize: 13,
fontFamily: 'GolosText-Bold',
},
infoUser: {
marginTop: 10,
},
name: {
fontSize: 18,
fontWeight: '500',
},
userId: {
textAlign: 'center',
fontFamily: 'GolosText-Bold',
fontSize: 30,
color: '#28A7E8',
},
telUser: {
color: '#373737',
fontWeight: '400',
fontSize: 16,
textAlign: 'center',
},
links: {
flexDirection: 'row',
alignItems: 'center',
gap: 10,
marginTop: 10,
},
modal: {
justifyContent: 'flex-end',
margin: 0,
},
modalContent: {
backgroundColor: 'white',
padding: 20,
borderTopLeftRadius: 12,
borderTopRightRadius: 12,
},
modalBtn: {
paddingVertical: 15,
borderBottomWidth: 1,
borderBottomColor: '#eee',
flexDirection: 'row',
justifyContent: 'center',
gap: 8,
alignItems: 'center',
},
modalText: {
fontSize: 16,
fontWeight: '500',
color: '#28A7E8',
textAlign: 'center',
},
});
export default ProfileHeader;