Untitled
unknown
plain_text
2 years ago
17 kB
20
Indexable
import React, { useEffect, useState, useRef, useMemo } from 'react';
import {
ActivityIndicator,
Dimensions,
Keyboard,
KeyboardAvoidingView,
Platform,
StatusBar,
StyleSheet,
useWindowDimensions,
} from 'react-native';
import { useTranslation } from 'react-i18next';
import { View } from 'react-native-ui-lib';
import { uniq } from 'lodash';
import { CommonActions, useNavigation, useRoute } from '@react-navigation/native';
import { observer } from 'mobx-react-lite';
import { FlatList } from 'react-native-gesture-handler';
import { BottomSheetModal, BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import { UseQueryResult } from '@tanstack/react-query';
import _ = require('lodash');
import { hasNotch } from 'react-native-device-info';
import { useColors } from '../../hooks';
import { useEtrader } from '../../context';
import { BaseScreen, Button, Checkbox, Modal, SearchInput, StockIcon, TextField } from '../../components/ui';
import { Tabbar } from '../../components/business';
import { WatchlistSelectedSymbols } from '../../components/business/EditWatchlist/WatchlistSelectedSymbols';
import { FilterChip } from '../../components/ui/FilterChip';
import { filterList } from '../../utils/constants';
import { WatchlistPredefinedList } from '../../components/business/EditWatchlist/WatchlistPredefinedList';
import { NoResult } from '../../components/ui/NoResult';
import { FilterSearchSymbolList, GetSearchSymbolList } from '../../api/matriks';
import { UpdateWatchlist } from '../../api/user';
import { GetStoredUserRefs } from '../../api/storage';
import ModalController from '../../components/Modal/ModalController';
const ITEM_HEIGHT = 64;
const getItemLayout = (data, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index });
export const CreateWatchlistScreen = observer(() => {
const { t } = useTranslation();
const { colors } = useColors() as any;
const {
store: { theme },
} = useEtrader();
const {
params: { userWatchlist, isLogin },
}: any = useRoute();
const lastScrollPositionRef = useRef(0);
const flatListRef = useRef(null);
const navigation = useNavigation();
const { width, height } = useWindowDimensions();
const screenWidth = width - 48;
const [selectedSymbolList, setSelectedSymbolList] = useState<string[]>([]);
const [buttonLabel, setButtonLabel] = useState(t('saveName'));
const [filterText, setFilterText] = useState('');
const [preListVisible, setPreListVisible] = useState<boolean>(false);
const [filterOptions, setFilterOptions] = useState([]);
const [successVisible, setSuccessVisible] = useState(false);
const [errorVisible, setErrorVisible] = useState(false);
const [watchlistName, setWatchlistName] = useState('');
const [selectedTab, setSelectedTab] = useState(0);
const [isKeyboardVisible, setKeyboardVisible] = useState(false);
const [isValid, setIsValid] = useState(false);
const [isSelectSymbolScreen, setIsSelectSymbolScreen] = useState(false);
const [isSaveButtonVisible, setIsSaveButtonVisible] = useState(true);
const [loading, setLoading] = useState(true);
const { data: symbols, isLoading: isSearchSymbolListLoading }: UseQueryResult<any> = GetSearchSymbolList();
const { data: userInfo }: UseQueryResult<any> = GetStoredUserRefs();
const { mutate: updateWatchlist, data: updateWatchlistData, isLoading: isLoadingUpdateWatchlist } = UpdateWatchlist();
const {
data: filteredSymbols,
isLoading: isFilterSearchLoading,
refetch,
}: UseQueryResult<any> = FilterSearchSymbolList({
filterText,
filterOptions,
symbols,
});
useEffect(() => {
if (filteredSymbols) {
setLoading(false);
}
}, [filteredSymbols]);
useEffect(() => {
if (symbols) {
refetch();
}
}, [filterText, filterOptions, symbols]);
useEffect(() => {
const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
setKeyboardVisible(true);
});
const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
setKeyboardVisible(false);
});
return () => {
keyboardDidHideListener.remove();
keyboardDidShowListener.remove();
};
}, []);
// liste oluşturma sonucu
useEffect(() => {
let closeTimer: string | number | NodeJS.Timeout | undefined;
if (updateWatchlistData) {
setSuccessVisible(true);
closeTimer = setTimeout(() => {
closeSuccess();
}, 3000);
setSelectedSymbolList([]);
}
return () => clearTimeout(closeTimer);
}, [updateWatchlistData]);
const isNameUnique = (value: string) => {
return !userWatchlist?.some((watchlistItem: any) => watchlistItem.listName === value);
};
const onCreateButtonPress = async () => {
if (isValid) {
if (buttonLabel === t('saveName')) {
setButtonLabel(t('createWatchlist'));
setIsSelectSymbolScreen(true);
} else if (buttonLabel === t('createWatchlist')) {
setLoading(true);
handleCreate();
}
}
};
const handleCreate = () => {
if (watchlistName !== '' && selectedSymbolList.length > 0) {
const newList = { listName: watchlistName.trim(), symbolList: selectedSymbolList };
updateWatchlist({
userRefText: userInfo?.userRefText,
userId: userInfo?.userId,
userWatchLists: [...userWatchlist, newList],
});
}
};
const closeFunc = () => {
const navigateScreen = isLogin ? 'dashboard' : 'loginDashboard';
navigation.navigate(navigateScreen as never);
setSelectedSymbolList([]);
};
useEffect(() => {
console.log(selectedSymbolList.length, 'Selectedsymbol');
if (selectedSymbolList.length > 4) {
ModalController.showModal({
type: 'error',
props: {
title: t('Üzgünüm,maksimum 150 sembol ekleyebilirsiniz.'),
icon: 'unsuccess',
},
});
}
}, [selectedSymbolList]);
const onChangeSymbolCheckedStatus = (symbolCode: string, checked: boolean) => {
console.log(selectedSymbolList, 'girdi2Selectedsymbol');
console.log(checked, 'checked');
if (checked) {
console.log('girdigirdi');
// uniq([symbolCode, ...selectedSymbols]);
setSelectedSymbolList(prevState => [...prevState, symbolCode]);
} else {
setSelectedSymbolList(prevState => prevState.filter(symbol => symbol !== symbolCode));
}
};
const renderContent = ({ item, index }: any) => {
const isSelected = selectedSymbolList.findIndex(symbolCode => symbolCode === item?.symbolCode) >= 0;
return (
<Checkbox
index={index}
bottomsheet
value={isSelected}
type="description"
description={item?.symbolDesc}
label={item?.symbolCode}
secondIcon={<StockIcon name={item?.symbolCode} size={32} />}
size={24}
outline={true}
onValueChange={(checked: boolean) => {
onChangeSymbolCheckedStatus(item?.symbolCode, checked);
}}
filterText={filterText}
/>
);
};
const renderAllSymbolsTab = () => (
<View backgroundColor={colors.watchlistListBg}>
<View
width={screenWidth}
minHeight={hasNotch() ? height - 140 : height - 120}
style={{ alignSelf: 'center', flex: 1 }}>
<SearchInput
onFocus={() => bottomSheetModalRef.current?.snapToIndex(1)}
onChangeText={(e: string) => {
if (!_.isEmpty(e)) {
setLoading(true);
}
setFilterText(e);
}}
// value={filterText}
textLength={filterText?.length}
placeholder={t('searchSymbols')}
upperCase
/>
<FilterChip
bottomSheet
data={filterList}
filterValue={filterOptions}
setFilterValue={filters => {
setLoading(true);
setFilterOptions(filters);
}}
/>
{loading || isSearchSymbolListLoading || isFilterSearchLoading || isLoadingUpdateWatchlist ? (
<View marginT-50 center>
<ActivityIndicator color={colors.action} animating size="large" />
</View>
) : (
<FlatList
keyboardShouldPersistTaps={'always'}
ref={flatListRef}
onScroll={e => {
lastScrollPositionRef.current = e?.nativeEvent?.contentOffset?.y;
// if (e?.nativeEvent?.contentOffset?.y > 0) {
// bottomSheetModalRef.current?.snapToIndex(1);
// }
}}
style={{ alignSelf: 'center', paddingBottom: 98 }}
contentContainerStyle={styles.flatListContainer}
removeClippedSubviews
showsVerticalScrollIndicator={false}
data={filteredSymbols}
windowSize={11}
horizontal={false}
maxToRenderPerBatch={11}
initialNumToRender={10}
decelerationRate={0.8}
ListEmptyComponent={() => (
<View center>
<NoResult />
</View>
)}
// getItemLayout={getItemLayout}
renderItem={(item: any) => renderContent(item)}
keyExtractor={(item: any) => item.symbolCode}
/>
)}
</View>
</View>
);
const showAllListHandle = () => {
navigation.navigate(
'selectedWatchlist' as never,
{ watchlistName, selectedSymbolList, methods: { setSelectedSymbolList } } as never,
);
};
const closeSuccess = () => {
navigation.dispatch(() =>
CommonActions.reset({
routes: [
{
name: 'home',
},
],
} as never),
);
setSuccessVisible(false);
};
const backAction = () => {
if (selectedSymbolList.length) {
setIsSaveButtonVisible(false);
ModalController.showModal({
type: 'unsavedChanges',
externalHeight: height / 1.7,
props: {
title: t('unsavedChanges'),
leftButton: {
label: `${t('yes')}, ${t('exit')}`,
onPress: () => {
setSelectedSymbolList([]);
ModalController.hideModal();
navigation.goBack();
},
},
rightButton: {
label: t('cancel'),
onPress: () => {
setIsSaveButtonVisible(true);
ModalController.hideModal();
},
},
},
});
} else {
setSelectedSymbolList([]);
navigation.goBack();
}
};
useEffect(() => {
if (bottomSheetModalRef && buttonLabel === t('createWatchlist')) {
bottomSheetModalRef?.current?.present();
}
}, [buttonLabel, bottomSheetModalRef]);
// ref
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
// variables
const snapPoints = useMemo(() => Platform.select({ ios: ['56%', '87%'], android: ['58%', '90%'] }), []);
const animatedContentView = () => {
const BottomSheetBackground = ({ style }) => {
const { colors } = useColors();
return (
<View
style={[
{
backgroundColor: colors.background,
},
{ ...style },
]}
/>
);
};
const getTabComponent = () => {
let component = renderAllSymbolsTab();
if (selectedTab === 1) {
component = (
<WatchlistPredefinedList
onSnapIndex={(index: number) => bottomSheetModalRef.current?.snapToIndex(index)}
setPreListVisible={setPreListVisible}
preListVisible={preListVisible}
currentSymbolList={selectedSymbolList}
setCurrentSymbolList={setSelectedSymbolList}
/>
);
}
return component;
};
return (
<BottomSheetModal
onChange={() => {
flatListRef?.current?.scrollToOffset({ offset: lastScrollPositionRef.current + 1 });
}}
backgroundComponent={props => <BottomSheetBackground {...props} />}
handleComponent={() => {}}
enablePanDownToClose={false}
enableDismissOnClose={false}
ref={bottomSheetModalRef}
index={0}
snapPoints={snapPoints}>
<View>
<Tabbar
bottomsheet
customIndicatorWidth
center
data={[{ label: t('allSymbols') }, { label: t('predefinedList') }]}
setSelectedTab={setSelectedTab}
selectedTab={selectedTab}
/>
{getTabComponent()}
</View>
</BottomSheetModal>
);
};
useEffect(() => {
const controlWatchlistName = (value: string) => {
let isValid = true;
const formatValue = value.trim();
if (formatValue === '' || formatValue.length < 3 || !isNameUnique(formatValue)) {
isValid = false;
}
setIsValid(isValid);
};
controlWatchlistName(watchlistName);
}, [watchlistName]);
return (
<>
<BottomSheetModalProvider>
<KeyboardAvoidingView
keyboardVerticalOffset={!isKeyboardVisible ? 24 : 0}
enabled
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.container}>
<BaseScreen
header={{
title: t('createNewWatchlist'),
secondaryHeader: true,
firstIconName: 'cross',
firstIconPress: closeFunc,
backAction,
}}>
<StatusBar
backgroundColor={colors.secondaryBgStart}
barStyle={theme === 'dark' ? 'light-content' : 'dark-content'}
/>
<View flex>
<View paddingH-24>
<TextField
label={t('watchlistName')}
placeholderl={t('watchlistName')}
onChangeText={(value: string) => setWatchlistName(value.trimStart())}
validate={['required', (value: string | any[]) => value.length > 2, isNameUnique]}
validationMessage={[t('required'), t('validationToShort'), t('validationDuplicated')]}
showCharCounter
maxLength={20}
value={watchlistName}
autoFocus={true}
onChangeValidity={(validStatus: boolean) => {
setIsValid(validStatus);
}}
readonly={isSelectSymbolScreen}
upperCase
onBlur={() => setWatchlistName(watchlistName.trim())}
/>
</View>
{buttonLabel === t('createWatchlist') && (
<View>
<View marginH-24>
<WatchlistSelectedSymbols
showAllOpen={() => showAllListHandle()}
data={selectedSymbolList}
deleteItem={item => setSelectedSymbolList(prevList => prevList.filter(symbol => symbol !== item))}
/>
</View>
{animatedContentView()}
</View>
)}
</View>
{successVisible ? (
<Modal
type="success"
visible={successVisible}
setOpenModal={() => closeSuccess()}
title={t('newWatchlistCreated')}
isBtn={false}
secondBtn={false}
/>
) : null}
{errorVisible ? (
<Modal
type="unsuccess"
visible={errorVisible}
setOpenModal={setErrorVisible}
title={t('dontCreate')}
isBtn={false}
secondBtn={false}
/>
) : null}
</BaseScreen>
{isSaveButtonVisible && (
<View style={styles.buttonContainer} backgroundColor={colors.background}>
<Button
marginH-24
marginV-16
button1
label={buttonLabel}
disabled={!isValid}
onPress={() => onCreateButtonPress()}
/>
</View>
)}
</KeyboardAvoidingView>
</BottomSheetModalProvider>
</>
);
});
const styles = StyleSheet.create({
container: {
flex: 1,
},
padding: {
paddingHorizontal: 24,
},
linear: {
flex: 1,
paddingHorizontal: 24,
paddingTop: 24,
},
flex: {
flex: 1,
},
animatedView: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
zIndex: 0,
},
blurStyles: {
zIndex: -10,
// width,
position: 'absolute',
},
buttonContainer: {
position: 'absolute',
bottom: 0,
zIndex: 100,
width: Dimensions.get('window').width,
},
flatListContainer: { paddingBottom: 110 },
});
Editor is loading...