Untitled

mail@pastecode.io avatar
unknown
plain_text
5 months ago
7.1 kB
1
Indexable
import {CommonText} from 'components/commons/CommonText';
import {mainRoutes} from 'navigation/mainRoutes';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View, FlatList} from 'react-native';
import {navigate} from 'utils/navigation';
import CardItem from './components/CardItem';

import {t} from 'languages/translation';
import HeaderHome from './components/HeaderHome';
import {useListCredentialOfferQuery} from 'app/services/credentialService';
import SortModal from './components/SortModal';
import {Modalize} from 'react-native-modalize';
import useTheme from 'themes/useTheme';
import {ColorProps} from 'themes/ThemeProvider';
import {CredentialData} from 'app/models/credential.model';
import {ScaledSheet} from 'react-native-size-matters';
import ModalController from 'components/modals/ModalController';
import {EdgeInsets, useSafeAreaInsets} from 'react-native-safe-area-context';
import {useGetInfoCurrentUserQuery} from 'app/services/authService';
import {useAppDispatch, useAppSelector} from 'app/hooks';
import {setCurrentUser} from 'futures/auth/authSlice';

function HomeScreen() {
  const modalizeRef = useRef<Modalize>(null);
  const [selectedSort, setSelectedSort] = useState<string>('DESC');
  const [pageNumber, setPageNumber] = useState<number>(1);
  const [listCredential, setListCredential] = useState<CredentialData[]>([]);
  const [itemDetail, setItemDetail] = useState<CredentialData>();
  const [indexDetail, setIndexDetail] = useState<number>(0);
  const dispatch = useAppDispatch();
  const currentUser = useAppSelector(state => state.auth.currentUser);
  const [showSearch, setShowSearch] = useState(false);
  const [keySearch, setKeySearch] = useState('');

  const {data: currentUserData} = useGetInfoCurrentUserQuery(undefined, {
    skip: currentUser !== null,
  });

  useEffect(() => {
    if (currentUserData) {
      dispatch(setCurrentUser(currentUserData.data));
    }
  }, [currentUserData, dispatch]);
  let limit = 10;
  const options = [
    {label: '発行順(新)', value: 'DESC'},
    {label: '発行順(旧)', value: 'ASC'},
  ];
  const {data, isSuccess, isFetching} = useListCredentialOfferQuery({
    page: pageNumber,
    limit: limit,
    sortBy: 'createdAt',
    sortDirection: selectedSort,
    keyword: keySearch,
  });
  const theme = useTheme();
  const inserts = useSafeAreaInsets();
  const styles = createStyles(inserts, theme.colors);

  useEffect(() => {
    if (data?.data && isSuccess) {
      const newListCredential =
        pageNumber !== 1 ? [...listCredential, ...data.data] : data.data;
      setListCredential(newListCredential);
    } else {
      setListCredential([]);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data, isSuccess]);

  const clearModalData = () => {
    setItemDetail(undefined);
    setIndexDetail(0);
    ModalController.hideCustomModal();
  };

  useEffect(() => {
    if (itemDetail) {
      const isBackground = {
        hideModal: true,
        isCallback: () => {
          setItemDetail(undefined);
          setIndexDetail(0);
        },
      };
      ModalController.showCustomModal(
        <View style={styles.modalCredential}>
          <CardItem
            data={itemDetail}
            index={indexDetail}
            showModal={true}
            handlePressCard={() => {
              navigate(mainRoutes.CredentialDetailScreen, {
                itemDetail: itemDetail,
              });
              clearModalData();
            }}
            clearModalData={clearModalData}
          />
        </View>,
        isBackground,
      );
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [itemDetail, indexDetail]);

  const handlePressCard = useCallback((index: number, item: CredentialData) => {
    setItemDetail(item);
    setIndexDetail(index);
  }, []);

  const renderItem = useCallback(
    ({item, index}: {item: CredentialData; index: number}) => {
      return (
        <CardItem
          key={index}
          data={item}
          index={index}
          handlePressCard={() => handlePressCard(index, item)}
        />
      );
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [],
  );

  const onEndReached = () => {
    if (isFetching && listCredential.length === limit * pageNumber) {
      setPageNumber(preState => preState + 1);
    }
  };

  const headerList = useMemo(() => {
    return (
      <View>
        <HeaderHome
          showSearch={showSearch}
          setShowSearch={setShowSearch}
          handleOpenSort={() => modalizeRef.current?.open()}
          setKeySearch={setKeySearch}
        />
        <CommonText variant="typography16" style={styles.titleList}>
          {t('HomeScreen.TitleListCard')}
        </CommonText>
      </View>
    );
  }, [showSearch, styles.titleList]);

  const footerList = () => {
    return (
      <View style={styles.bottomList}>
        {isFetching ? (
          <CommonText variant={'typography12'}>Loading...</CommonText>
        ) : null}
      </View>
    );
  };
  const keyExtractor = useCallback(
    (_: any, index: {toString: () => any}) => index.toString(),
    [],
  );

  return (
    <View style={styles.container}>
      <View style={styles.root}>
        <FlatList
          nestedScrollEnabled
          data={listCredential}
          style={styles.listCredential}
          renderItem={renderItem}
          onEndReachedThreshold={0.4}
          onEndReached={onEndReached}
          ListHeaderComponent={headerList}
          ListFooterComponent={footerList}
          keyExtractor={keyExtractor}
          initialNumToRender={10}
          maxToRenderPerBatch={5}
          windowSize={5}
          initialScrollIndex={0}
          removeClippedSubviews={false}
        />
      </View>
      <SortModal
        modalizeRef={modalizeRef}
        onClose={() => modalizeRef?.current?.close()}
        selectedOption={selectedSort}
        setSelectedOption={setSelectedSort}
        options={options}
      />
    </View>
  );
}

const createStyles = (insets: EdgeInsets, colors: ColorProps) =>
  ScaledSheet.create({
    container: {
      flex: 1,
    },
    root: {
      flex: 1,
      backgroundColor: colors.background,
      marginTop: -insets.top,
    },
    titleList: {
      marginTop: '12@vs',
      marginBottom: '21@vs',
    },
    itemDetail: {
      marginBottom: '20@vs',
    },
    listCredential: {
      paddingHorizontal: '40@ms',
      flexGrow: 1,
    },
    bottomList: {
      height: '40@ms',
    },
    modalCredential: {
      paddingHorizontal: '40@ms',
    },
    itemContainer: {
      backgroundColor: colors.background,
      borderRadius: '20@ms',
      paddingHorizontal: '14@ms',
      gap: '14@ms',
      borderColor: colors.input.borderColor,
      borderWidth: '1@ms',
    },
  });

export default HomeScreen;
Leave a Comment