ente/src/components/SearchBar.tsx

155 lines
5.3 KiB
TypeScript
Raw Normal View History

2021-05-18 07:47:03 +00:00
import { Formik } from 'formik';
2021-05-18 14:20:15 +00:00
import { SetCollections, SetFiles } from 'pages/gallery';
2021-05-20 08:00:02 +00:00
import React, { useEffect, useState } from 'react';
2021-05-18 07:47:03 +00:00
import { Form } from 'react-bootstrap';
2021-05-18 04:32:37 +00:00
import styled from 'styled-components';
2021-05-18 07:47:03 +00:00
import constants from 'utils/strings/constants';
import * as Yup from 'yup';
2021-05-20 08:00:02 +00:00
import { File, getLocalFiles } from 'services/fileService';
import {
Collection,
getLocalCollections,
getNonEmptyCollections,
} from 'services/collectionService';
2021-05-20 08:19:37 +00:00
import { parseHumanDate, searchLocation } from 'services/searchService';
import { getFilesWithCreationDay, getFilesInsideBbox } from 'utils/search';
2021-05-18 04:32:37 +00:00
const Wrapper = styled.div<{ open: boolean }>`
background-color: #111;
color: #fff;
min-height: 64px;
align-items: center;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.7);
margin-bottom: 10px;
position: fixed;
top: 0;
width: 100%;
2021-05-18 07:47:03 +00:00
display: flex;
align-items: center;
justify-content: center;
2021-05-18 06:52:11 +00:00
z-index: 200;
2021-05-18 07:47:03 +00:00
padding: 0 20%;
display: ${(props) => (props.open ? 'flex' : 'none')};
2021-05-18 04:32:37 +00:00
`;
2021-05-18 07:47:03 +00:00
interface formValues {
searchPhrase: string;
}
interface Props {
2021-05-18 14:20:15 +00:00
isOpen: boolean;
2021-05-18 07:47:03 +00:00
setOpen: (value) => void;
2021-05-18 14:20:15 +00:00
loadingBar: any;
setFiles: SetFiles;
setCollections: SetCollections;
2021-05-18 07:47:03 +00:00
}
export default function SearchBar(props: Props) {
2021-05-20 08:00:02 +00:00
const [allFiles, setAllFiles] = useState<File[]>([]);
const [allCollections, setAllCollections] = useState<Collection[]>([]);
useEffect(() => {
const main = async () => {
setAllFiles(await getLocalFiles());
setAllCollections(await getLocalCollections());
};
main();
}, []);
2021-05-18 14:20:15 +00:00
const searchFiles = async (values: formValues) => {
2021-05-20 08:00:02 +00:00
props.loadingBar.continuousStart();
2021-05-20 08:19:37 +00:00
2021-05-20 08:00:02 +00:00
let resultFiles: File[] = [];
2021-05-20 08:19:37 +00:00
const searchedDate = parseHumanDate(values.searchPhrase);
if (searchedDate != null) {
const filesWithSameDate = getFilesWithCreationDay(
allFiles,
searchedDate
2021-05-20 08:00:02 +00:00
);
2021-05-20 08:19:37 +00:00
resultFiles.push(...filesWithSameDate);
2021-05-20 08:00:02 +00:00
} else {
const bbox = await searchLocation(values.searchPhrase);
if (bbox) {
2021-05-20 08:19:37 +00:00
const filesTakenAtLocation = getFilesInsideBbox(allFiles, bbox);
resultFiles.push(...filesTakenAtLocation);
2021-05-18 14:20:15 +00:00
}
2021-05-20 08:00:02 +00:00
}
2021-05-20 08:19:37 +00:00
2021-05-20 08:00:02 +00:00
props.setFiles(resultFiles);
props.setCollections(
getNonEmptyCollections(allCollections, resultFiles)
);
await new Promise((resolve) =>
2021-05-20 08:19:37 +00:00
setTimeout(() => resolve(props.loadingBar.complete()), 5000)
2021-05-18 14:20:15 +00:00
);
};
2021-05-20 08:00:02 +00:00
const closeSearchBar = ({ resetForm }) => {
2021-05-18 14:20:15 +00:00
props.setOpen(false);
2021-05-20 08:00:02 +00:00
props.setFiles(allFiles);
props.setCollections(allCollections);
2021-05-18 14:20:15 +00:00
resetForm();
};
2021-05-18 07:47:03 +00:00
return (
2021-05-18 14:20:15 +00:00
<Wrapper open={props.isOpen}>
<Formik<formValues>
initialValues={{ searchPhrase: '' }}
onSubmit={searchFiles}
validationSchema={Yup.object().shape({
searchPhrase: Yup.string().required(constants.REQUIRED),
})}
validateOnChange={false}
validateOnBlur={false}
2021-05-18 07:47:03 +00:00
>
2021-05-18 14:20:15 +00:00
{({
values,
touched,
errors,
handleChange,
handleSubmit,
resetForm,
}) => (
<>
<div
style={{
flex: 1,
maxWidth: '700px',
margin: '10px',
}}
>
<Form noValidate onSubmit={handleSubmit}>
<Form.Control
type={'search'}
placeholder={'search your photos'}
value={values.searchPhrase}
onChange={handleChange('searchPhrase')}
isInvalid={Boolean(
touched.searchPhrase &&
errors.searchPhrase
)}
/>
</Form>
</div>
<div
style={{
margin: '0',
display: 'flex',
alignItems: 'center',
cursor: 'pointer',
}}
2021-05-20 08:00:02 +00:00
onClick={() => closeSearchBar({ resetForm })}
2021-05-18 14:20:15 +00:00
>
<svg
xmlns="http://www.w3.org/2000/svg"
height={25}
viewBox={`0 0 25 25`}
width={25}
>
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"></path>
</svg>
</div>
</>
)}
</Formik>
2021-05-18 07:47:03 +00:00
</Wrapper>
);
2021-05-18 04:32:37 +00:00
}