import { Search, SearchStats } from 'pages/gallery';
import React, { useEffect, useRef } from 'react';
import styled from 'styled-components';
import AsyncSelect from 'react-select/async';
import { components } from 'react-select';
import debounce from 'debounce-promise';
import {
Bbox,
getHolidaySuggestion,
getYearSuggestion,
parseHumanDate,
searchCollection,
searchLocation,
} from 'services/searchService';
import { getFormattedDate } from 'utils/search';
import constants from 'utils/strings/constants';
import LocationIcon from './icons/LocationIcon';
import DateIcon from './icons/DateIcon';
import SearchIcon from './icons/SearchIcon';
import CrossIcon from './icons/CrossIcon';
import { Collection } from 'services/collectionService';
import CollectionIcon from './icons/CollectionIcon';
const Wrapper = styled.div<{ isDisabled: boolean; isOpen: boolean }>`
position: fixed;
top: 0;
z-index: 1000;
display: ${({ isOpen }) => (isOpen ? 'flex' : 'none')};
width: 100%;
background: #111;
@media (min-width: 625px) {
display: flex;
width: calc(100vw - 140px);
margin: 0 70px;
}
align-items: center;
min-height: 64px;
transition: opacity 1s ease;
opacity: ${(props) => (props.isDisabled ? 0 : 1)};
margin-bottom: 10px;
`;
const SearchButton = styled.div<{ isOpen: boolean }>`
display: none;
@media (max-width: 624px) {
display: ${({ isOpen }) => (!isOpen ? 'flex' : 'none')};
right: 80px;
cursor: pointer;
position: fixed;
top: 0;
z-index: 1000;
align-items: center;
min-height: 64px;
}
`;
const SearchStatsContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
color: #979797;
margin-bottom: 8px;
`;
const SearchInput = styled.div`
width: 100%;
display: flex;
align-items: center;
max-width: 484px;
margin: auto;
`;
export enum SuggestionType {
DATE,
LOCATION,
COLLECTION,
}
export interface DateValue {
date?: number;
month?: number;
year?: number;
}
export interface Suggestion {
type: SuggestionType;
label: string;
value: Bbox | DateValue | number;
}
interface Props {
isOpen: boolean;
isFirstFetch: boolean;
setOpen: (value) => void;
loadingBar: any;
setSearch: (search: Search) => void;
searchStats: SearchStats;
collections: Collection[];
setActiveCollection: (id: number) => void;
}
export default function SearchBar(props: Props) {
const selectRef = useRef(null);
useEffect(() => {
if (props.isOpen) {
setTimeout(() => {
selectRef.current?.focus();
}, 250);
}
}, [props.isOpen]);
// = =========================
// Functionality
// = =========================
const getAutoCompleteSuggestions = async (searchPhrase: string) => {
searchPhrase = searchPhrase.trim();
if (!searchPhrase?.length) {
return [];
}
const option = [
...getHolidaySuggestion(searchPhrase),
...getYearSuggestion(searchPhrase),
];
const searchedDates = parseHumanDate(searchPhrase);
option.push(
...searchedDates.map((searchedDate) => ({
type: SuggestionType.DATE,
value: searchedDate,
label: getFormattedDate(searchedDate),
}))
);
const collectionResults = searchCollection(
searchPhrase,
props.collections
);
option.push(
...collectionResults.map(
(searchResult) =>
({
type: SuggestionType.COLLECTION,
value: searchResult.id,
label: searchResult.name,
} as Suggestion)
)
);
const locationResults = await searchLocation(searchPhrase);
option.push(
...locationResults.map(
(searchResult) =>
({
type: SuggestionType.LOCATION,
value: searchResult.bbox,
label: searchResult.place,
} as Suggestion)
)
);
return option;
};
const getOptions = debounce(getAutoCompleteSuggestions, 250);
const filterFiles = (selectedOption: Suggestion) => {
if (!selectedOption) {
return;
}
// const startTime = Date.now();
props.setOpen(true);
switch (selectedOption.type) {
case SuggestionType.DATE:
props.setSearch({
date: selectedOption.value as DateValue,
});
break;
case SuggestionType.LOCATION:
props.setSearch({
location: selectedOption.value as Bbox,
});
break;
case SuggestionType.COLLECTION:
props.setActiveCollection(selectedOption.value as number);
break;
}
};
const resetSearch = () => {
if (props.isOpen) {
selectRef.current.select.state.value = null;
props.loadingBar.current?.continuousStart();
// props.setFiles(allFiles);
props.setSearch({});
setTimeout(() => {
props.loadingBar.current?.complete();
}, 10);
props.setOpen(false);
}
};
// = =========================
// UI
// = =========================
const getIconByType = (type: SuggestionType) => {
switch (type) {
case SuggestionType.DATE:
return