/* * Copyright (c) 2019 - 2020 Arnaud Vergnet. * * This file is part of Campus INSAT. * * Campus INSAT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Campus INSAT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Campus INSAT. If not, see . */ import React, { useLayoutEffect, useRef, useState } from 'react'; import { Platform } from 'react-native'; import { Searchbar } from 'react-native-paper'; import i18n from 'i18n-js'; import ClubListItem from '../../../components/Lists/Clubs/ClubListItem'; import { isItemInCategoryFilter, stringMatchQuery, } from '../../../utils/Search'; import ClubListHeader from '../../../components/Lists/Clubs/ClubListHeader'; import MaterialHeaderButtons, { Item, } from '../../../components/Overrides/CustomHeaderButton'; import WebSectionList from '../../../components/Screens/WebSectionList'; import { useNavigation } from '@react-navigation/native'; import { useAuthenticatedRequest } from '../../../context/loginContext'; export type ClubCategoryType = { id: number; name: string; }; export type ClubType = { id: number; name: string; description: string; logo: string; email: string | null; category: Array; responsibles: Array; }; type ResponseType = { categories: Array; clubs: Array; }; const LIST_ITEM_HEIGHT = 96; function ClubListScreen() { const navigation = useNavigation(); const request = useAuthenticatedRequest('clubs/list'); const [ currentlySelectedCategories, setCurrentlySelectedCategories, ] = useState>([]); const [currentSearchString, setCurrentSearchString] = useState(''); const categories = useRef>([]); useLayoutEffect(() => { const getSearchBar = () => { return ( // @ts-ignore ); }; const getHeaderButtons = () => { return ( navigation.navigate('club-about')} /> ); }; navigation.setOptions({ headerTitle: getSearchBar, headerRight: getHeaderButtons, headerBackTitleVisible: false, headerTitleContainerStyle: Platform.OS === 'ios' ? { marginHorizontal: 0, width: '70%' } : { marginHorizontal: 0, right: 50, left: 50 }, }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [navigation]); const onSearchStringChange = (str: string) => { updateFilteredData(str, null); }; /** * Callback used when clicking an article in the list. * It opens the modal to show detailed information about the article * * @param item The article pressed */ const onListItemPress = (item: ClubType) => { navigation.navigate('club-information', { data: item, categories: categories.current, }); }; const onChipSelect = (id: number) => { updateFilteredData(null, id); }; const createDataset = (data: ResponseType | undefined) => { if (data) { categories.current = data.categories; return [{ title: '', data: data.clubs }]; } else { return []; } }; /** * Gets the list header, with controls to change the categories filter * * @returns {*} */ const getListHeader = (data: ResponseType | undefined) => { if (data) { return ( ); } else { return null; } }; const getCategoryOfId = (id: number): ClubCategoryType | null => { let cat = null; categories.current.forEach((item: ClubCategoryType) => { if (id === item.id) { cat = item; } }); return cat; }; const getRenderItem = ({ item }: { item: ClubType }) => { const onPress = () => { onListItemPress(item); }; if (shouldRenderItem(item)) { return ( ); } return null; }; const keyExtractor = (item: ClubType): string => item.id.toString(); /** * Updates the search string and category filter, saving them to the State. * * If the given category is already in the filter, it removes it. * Otherwise it adds it to the filter. * * @param filterStr The new filter string to use * @param categoryId The category to add/remove from the filter */ const updateFilteredData = ( filterStr: string | null, categoryId: number | null ) => { const newCategoriesState = [...currentlySelectedCategories]; let newStrState = currentSearchString; if (filterStr !== null) { newStrState = filterStr; } if (categoryId !== null) { const index = newCategoriesState.indexOf(categoryId); if (index === -1) { newCategoriesState.push(categoryId); } else { newCategoriesState.splice(index, 1); } } if (filterStr !== null || categoryId !== null) { setCurrentSearchString(newStrState); setCurrentlySelectedCategories(newCategoriesState); } }; /** * Checks if the given item should be rendered according to current name and category filters * * @param item The club to check * @returns {boolean} */ const shouldRenderItem = (item: ClubType): boolean => { let shouldRender = currentlySelectedCategories.length === 0 || isItemInCategoryFilter(currentlySelectedCategories, item.category); if (shouldRender) { shouldRender = stringMatchQuery(item.name, currentSearchString); } return shouldRender; }; return ( ); } export default ClubListScreen;