Untitled
unknown
plain_text
2 years ago
17 kB
6
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...