import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import { DevTechnology, Technology } from '../technologies/technology'; import last from 'lodash/last'; import { useDebouncedValue } from '../../hooks/use_debounced_value'; import { TechnologiesPickerContext } from '../technologies_picker_context'; import cn from 'classnames'; import { Card, Checkbox, TextField, Typography } from '../../index'; import InfiniteScroll from 'react-infinite-scroll-component'; const technoCardsSizes = { mobile: { width: 56 + 2 * 1 * 8, height: 80 + 2 * 1 * 8, }, other: { width: 80 + 2 * 1.5 * 8, height: 120 + 2 * 1.5 * 8, }, } as const; const TechnologyItem = ({ item, selectedItems = [], onAdd, onDelete, isMobile, }: { selectedItems: Array; item: Technology; onAdd: (name: string) => void; onDelete: (name: string) => void; isMobile?: boolean; }) => { const { technologies } = useContext(TechnologiesPickerContext); const selectedItem = useMemo(() => selectedItems.find(({ name }) => name === item.name), [selectedItems, item]); const onClick = useCallback(() => { if (!selectedItem) { onAdd(item.name); return; } onDelete(selectedItem.name); }, [selectedItem, onAdd, onDelete]); const imgUrl = useMemo(() => { const matchingItem = technologies.find((techno) => techno.name === item.name); if (matchingItem?.handle) { return `https://process.filestackapi.com/auto_image/${matchingItem?.handle ?? '4A5N89okRPW50jRcmkuM'}`; } const handle = last(matchingItem?.url.split('/')); return `https://process.filestackapi.com/auto_image/${handle ?? '4A5N89okRPW50jRcmkuM'}`; }, [item, technologies]); return ( ); }; interface Props { technologies: Technology[]; onDelete: (name: string) => void; classes?: { container?: string; technologiesList?: string; }; onAdd: (name: string) => void; selectedItems: Array; isMobile?: boolean; noResultsElement?: React.ReactElement | null; additionalInformations?: React.ReactElement | null; } const DISPLAYED_ITEMS = 30; export const AllTechnologiesPicker = ({ selectedItems, onAdd, onDelete, classes = {}, isMobile, noResultsElement = null, additionalInformations = null, }: Props) => { const [onlySelected, setOnlySelected] = useState(); const containerRef = useRef(null); const [query, setQuery] = useState(''); const debouncedQuery = useDebouncedValue(query, 200); const { technologies, translations } = useContext(TechnologiesPickerContext); const [shownItems, setShownItems] = useState(DISPLAYED_ITEMS); const displayedItems = useMemo( () => technologies .filter(({ name }) => { if (!onlySelected) { return true; } return selectedItems.some(({ name: selectedName }) => selectedName === name); }) .filter(({ name, tags }) => [...(tags ?? []), name].some((value) => value.toLowerCase().includes(debouncedQuery.toLowerCase())) ) .sort(({ name: a }, { name: b }) => a.localeCompare(b)), [technologies, debouncedQuery, onlySelected] ); const slicedItems = useMemo(() => displayedItems.slice(0, shownItems), [displayedItems, shownItems]); const handleTextFieldChange = useCallback((event: any) => setQuery(event.target.value), []); useEffect(() => { const { clientWidth: width, clientHeight: height } = containerRef?.current || {}; if (!width || !height) { return; } const sizes = isMobile ? technoCardsSizes['mobile'] : technoCardsSizes['other']; const itemsPerRow = Math.floor(width / sizes.width); const rowsCount = Math.ceil(height / sizes.height); let itemsCount = Math.round(itemsPerRow * rowsCount); setShownItems(itemsCount); }, [containerRef.current]); const toggleOtherPerk = useCallback(() => { setOnlySelected(!onlySelected); }, [onlySelected]); return (
{isMobile && additionalInformations} {!displayedItems.length && noResultsElement}
{ setShownItems(shownItems + DISPLAYED_ITEMS); }} hasMore={displayedItems.length > shownItems} loader={null} scrollableTarget="allTechnologiesPicker" > {slicedItems.map((item, index) => ( ))}
); };