Untitled

mail@pastecode.io avatar
unknown
plain_text
7 months ago
17 kB
2
Indexable
Never
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 },
});