123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- import React, { useState } from 'react';
- import { ScrollView, View } from 'react-native';
- import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
- import { Formik } from 'formik';
- import * as yup from 'yup';
- import { CommonActions, useNavigation } from '@react-navigation/native';
- import { useQueryClient } from '@tanstack/react-query';
- import { Image } from 'expo-image';
- import {
- usePostGetProfileQuery,
- usePostSetProfileMutation,
- userQueryKeys,
- type PostSetProfileData
- } from '@api/user';
- import { useGetRegionsWithFlagQuery } from '@api/regions';
- import { API_HOST } from '../../../../constants';
- import {
- AvatarPicker,
- BigText,
- Header,
- Input,
- PageWrapper,
- Button,
- Loading,
- WarningModal
- } from '../../../../components';
- import { InputDatePicker } from '../../../../components/Calendar/InputDatePicker';
- import { ModalFlatList } from '../../../../components/FlatList/modal-flatlist';
- import { storage, StoreType } from '../../../../storage';
- import { Colors } from '../../../../theme';
- import FacebookIcon from '../../../../../assets/icons/facebook.svg';
- import InstagramIcon from '../../../../../assets/icons/instagram.svg';
- import XIcon from '../../../../../assets/icons/x(twitter).svg';
- import YoutubeIcon from '../../../../../assets/icons/youtube.svg';
- import GlobeIcon from '../../../../../assets/icons/bottom-navigation/globe.svg';
- import LinkIcon from '../../../../../assets/icons/link.svg';
- import { ButtonVariants } from 'src/types/components';
- import { NAVIGATION_PAGES } from 'src/types';
- import { useDeleteUserMutation } from '@api/app';
- import { useNotification } from 'src/contexts/NotificationContext';
- import { useMessagesStore } from 'src/stores/unreadMessagesStore';
- const ProfileSchema = yup.object({
- username: yup.string().optional(),
- email: yup.string().email().optional(),
- first_name: yup.string().optional(),
- last_name: yup.string().optional(),
- date_of_birth: yup.string().optional(),
- homebase: yup.number().optional(),
- homebase2: yup.number().nullable().optional(),
- bio: yup.string().optional(),
- f: yup.string().optional(),
- t: yup.string().optional(),
- i: yup.string().optional(),
- y: yup.string().optional(),
- www: yup.string().optional(),
- other: yup.string().optional()
- });
- export const EditPersonalInfo = () => {
- const token = storage.get('token', StoreType.STRING) as string;
- const uid = storage.get('uid', StoreType.STRING) as string;
- const { mutate: deleteUser } = useDeleteUserMutation();
- const { mutate: updateProfile, data: updateResponse, reset } = usePostSetProfileMutation();
- const navigation = useNavigation();
- const queryClient = useQueryClient();
- const { data, error } = usePostGetProfileQuery(String(token), true);
- const { updateNotificationStatus } = useNotification();
- const updateUnreadMessagesCount = useMessagesStore((state) => state.updateUnreadMessagesCount);
- const regions = useGetRegionsWithFlagQuery(true);
- const [modalInfo, setModalInfo] = useState({
- visible: false,
- type: 'confirm',
- message: '',
- action: () => {}
- });
- const openModal = (type: string, message: string, action: any) => {
- setModalInfo({
- visible: true,
- type,
- message,
- action
- });
- };
- const closeModal = () => {
- setModalInfo({ ...modalInfo, visible: false });
- };
- if (!data) return <Loading />;
- const originRegion = regions.data?.data.find((region) => region.id === data.homebase);
- const secondOrigin = regions.data?.data.find((region) => region.id === data.homebase2);
- const handleLogout = () => {
- storage.remove('token');
- storage.remove('uid');
- storage.remove('currentUserData');
- storage.remove('visitedTilesUrl');
- storage.remove('filterSettings');
- updateNotificationStatus();
- updateUnreadMessagesCount();
- navigation.dispatch(
- CommonActions.reset({
- index: 1,
- routes: [{ name: NAVIGATION_PAGES.WELCOME }]
- })
- );
- };
- const handleDeleteAccount = () => {
- deleteUser({ token }, { onSuccess: handleLogout });
- };
- return (
- <PageWrapper>
- <ScrollView showsVerticalScrollIndicator={false}>
- <Header label={'Edit Personal Info'} />
- <KeyboardAwareScrollView>
- <Formik
- validationSchema={ProfileSchema}
- initialValues={{
- username: data.username,
- email: data.email,
- first_name: data.first_name,
- last_name: data.last_name,
- date_of_birth: data.date_of_birth,
- homebase: data.homebase,
- homebase2: data.homebase2,
- bio: data.bio.toString(),
- f: data.links.f!.link,
- i: data.links.i!.link,
- t: data.links.t!.link,
- y: data.links.y!.link,
- www: data.links.www!.link,
- other: data.links.other!.link,
- photo: {
- type: '',
- uri: '',
- name: ''
- }
- }}
- onSubmit={async (values) => {
- const profileData: PostSetProfileData = {
- token: String(token),
- user: {
- username: values.username,
- email: values.email,
- first_name: values.first_name,
- last_name: values.last_name,
- date_of_birth: values.date_of_birth,
- homebase: values.homebase,
- bio: values.bio,
- f: values.f,
- i: values.i,
- t: values.t,
- y: values.y,
- www: values.www,
- other: values.other
- }
- };
- if (values.homebase2) {
- profileData.user!.homebase2 = values.homebase2;
- }
- if (values.photo.uri) {
- profileData.photo = {
- type: values.photo.type,
- uri: values.photo.uri,
- name: values.photo.uri.split('/').pop()!
- };
- }
- updateProfile(profileData, {
- onSuccess: () => {
- queryClient.invalidateQueries({
- queryKey: userQueryKeys.getProfileData(),
- refetchType: 'all'
- });
- queryClient.invalidateQueries({
- queryKey: userQueryKeys.getProfileInfoData(+uid),
- refetchType: 'all'
- });
- Image.clearDiskCache();
- Image.clearMemoryCache();
- navigation.goBack();
- }
- });
- }}
- >
- {(props) => (
- <View style={{ gap: 10 }}>
- <View style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
- <AvatarPicker
- defaultAvatar={API_HOST + '/img/avatars/' + data.avatar}
- selectedAvatar={(asset) => props.setFieldValue('photo', asset)}
- />
- </View>
- <BigText>Account</BigText>
- <Input
- editable={false}
- header={"Username (can't edit)"}
- placeholder={'Text'}
- inputMode={'text'}
- onChange={props.handleChange('username')}
- value={props.values.username}
- onBlur={props.handleBlur('username')}
- formikError={props.touched.username && props.errors.username}
- />
- <Input
- editable={false}
- header={"Email address (can't edit)"}
- placeholder={'Email'}
- inputMode={'email'}
- onChange={props.handleChange('email')}
- value={props.values.email}
- onBlur={props.handleBlur('email')}
- formikError={props.touched.email && props.errors.email}
- />
- <BigText>General Info</BigText>
- <Input
- header={'First name'}
- placeholder={'Text'}
- inputMode={'text'}
- onChange={props.handleChange('first_name')}
- value={props.values.first_name}
- onBlur={props.handleBlur('first_name')}
- formikError={props.touched.first_name && props.errors.first_name}
- />
- <Input
- header={'Last name'}
- placeholder={'Text'}
- inputMode={'text'}
- onChange={props.handleChange('last_name')}
- value={props.values.last_name}
- onBlur={props.handleBlur('last_name')}
- formikError={props.touched.last_name && props.errors.last_name}
- />
- <InputDatePicker
- headerTitle={'Date of birth'}
- defaultDate={new Date(data.date_of_birth)}
- selectedDate={(date) => props.setFieldValue('date_of_birth', date)}
- formikError={props.touched.date_of_birth && props.errors.date_of_birth}
- />
- <ModalFlatList
- headerTitle={'Region of origin'}
- defaultObject={{ name: originRegion?.name }}
- selectedObject={(data) => props.setFieldValue('homebase', data.id)}
- />
- <ModalFlatList
- headerTitle={'Second region'}
- defaultObject={{ name: secondOrigin?.name }}
- selectedObject={(data) => props.setFieldValue('homebase2', data.id)}
- />
- <Input
- multiline={true}
- header={'Bio'}
- placeholder={'Text'}
- inputMode={'text'}
- onChange={props.handleChange('bio')}
- value={props.values.bio}
- onBlur={props.handleBlur('bio')}
- formikError={props.touched.bio && props.errors.bio}
- />
- <BigText>Links</BigText>
- <Input
- icon={<FacebookIcon fill={Colors.LIGHT_GRAY} />}
- placeholder={'https://www.facebook.com'}
- inputMode={'text'}
- onChange={props.handleChange('f')}
- value={props.values.f as unknown as string}
- onBlur={props.handleBlur('f')}
- formikError={props.touched.f && props.errors.f}
- />
- <Input
- icon={<InstagramIcon fill={Colors.LIGHT_GRAY} />}
- placeholder={'https://www.instagram.com'}
- inputMode={'text'}
- onChange={props.handleChange('i')}
- value={props.values.i as unknown as string}
- onBlur={props.handleBlur('i')}
- formikError={props.touched.i && props.errors.i}
- />
- <Input
- icon={<XIcon fill={Colors.LIGHT_GRAY} />}
- placeholder={'https://www.twitter.com'}
- inputMode={'text'}
- onChange={props.handleChange('t')}
- value={props.values.t as unknown as string}
- onBlur={props.handleBlur('t')}
- formikError={props.touched.t && props.errors.t}
- />
- <Input
- icon={<YoutubeIcon fill={Colors.LIGHT_GRAY} />}
- placeholder={'https://www.youtube.com'}
- inputMode={'text'}
- onChange={props.handleChange('y')}
- value={props.values.y as unknown as string}
- onBlur={props.handleBlur('y')}
- formikError={props.touched.y && props.errors.y}
- />
- <Input
- icon={<GlobeIcon fill={Colors.LIGHT_GRAY} />}
- placeholder={'My Website'}
- inputMode={'text'}
- onChange={props.handleChange('www')}
- value={props.values.www as unknown as string}
- onBlur={props.handleBlur('www')}
- formikError={props.touched.www && props.errors.www}
- />
- <Input
- icon={<LinkIcon fill={Colors.LIGHT_GRAY} />}
- placeholder={'Other link'}
- inputMode={'text'}
- onChange={props.handleChange('other')}
- value={props.values.other as unknown as string}
- onBlur={props.handleBlur('other')}
- formikError={props.touched.other && props.errors.other}
- />
- <View style={{ marginTop: 15, marginBottom: 15, gap: 8 }}>
- <Button onPress={props.handleSubmit}>Save</Button>
- <Button
- variant={ButtonVariants.OPACITY}
- containerStyles={{ backgroundColor: Colors.WHITE, borderColor: Colors.RED }}
- textStyles={{ color: Colors.RED }}
- onPress={() =>
- openModal('confirm', 'Are you sure you want to logout?', handleLogout)
- }
- >
- Log out
- </Button>
- <Button
- variant={ButtonVariants.FILL}
- containerStyles={{ backgroundColor: Colors.RED }}
- onPress={() =>
- openModal(
- 'confirm',
- 'Are you sure you want to delete your account?',
- handleDeleteAccount
- )
- }
- >
- Delete account
- </Button>
- </View>
- </View>
- )}
- </Formik>
- </KeyboardAwareScrollView>
- </ScrollView>
- <WarningModal
- isVisible={modalInfo.visible}
- onClose={closeModal}
- type={modalInfo.type}
- message={modalInfo.message}
- action={() => {
- modalInfo.action();
- closeModal();
- }}
- />
- </PageWrapper>
- );
- };
|