version/0.5 #3
|
@ -0,0 +1,58 @@
|
||||||
|
import { Box, Button, Card, Flex, Icon, Spacer } from '@chakra-ui/react';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { IoShareSocialOutline } from 'react-icons/io5';
|
||||||
|
import MediaQuery from 'react-responsive';
|
||||||
|
import { MEDIA_QUERY_DESKTOP_STARTS, MEDIA_QUERY_MOBILE_ENDS } from '../constants/mediaquery';
|
||||||
|
|
||||||
|
export interface IProps {
|
||||||
|
show: boolean
|
||||||
|
onClick(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const CopyToClipboardButton: React.FC<IProps> = (props) => {
|
||||||
|
|
||||||
|
const { show, onClick } = props
|
||||||
|
|
||||||
|
const [showSuccess, setShowSuccess] = useState<boolean>(false)
|
||||||
|
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
onClick()
|
||||||
|
setShowSuccess(true)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setShowSuccess(false)
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MediaQuery minWidth={MEDIA_QUERY_DESKTOP_STARTS}>
|
||||||
|
{show &&
|
||||||
|
<Card backgroundColor={'transparent'} mt={{ base: 0, md: 4 }} mb={{ base: 0, md: 4 }} mx={{ base: 4, md: 4 }}>
|
||||||
|
<Box p='4'>
|
||||||
|
<Flex alignItems={'center'}>
|
||||||
|
<Button bgColor={showSuccess ? 'green.400' : ''} onClick={handleClick}>
|
||||||
|
{showSuccess ? t('search.copy_success'): t('search.copy_search_link')} <Icon as={IoShareSocialOutline} />
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
</Card>}
|
||||||
|
</MediaQuery>
|
||||||
|
<MediaQuery maxWidth={MEDIA_QUERY_MOBILE_ENDS}>
|
||||||
|
{show &&
|
||||||
|
<Box p='4'>
|
||||||
|
<Flex alignItems={'center'}>
|
||||||
|
<Button bgColor={showSuccess ? 'green.400' : ''} onClick={handleClick}>
|
||||||
|
{showSuccess ? t('search.copy_success') : t('search.copy_search_link')} <Icon as={IoShareSocialOutline} />
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Box>}
|
||||||
|
</MediaQuery>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CopyToClipboardButton;
|
|
@ -1,5 +1,6 @@
|
||||||
import { GridItem, Icon, SimpleGrid } from '@chakra-ui/react';
|
import { Button, GridItem, Icon, SimpleGrid, Flex, Box, Card } from '@chakra-ui/react';
|
||||||
import React, { useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import MediaQuery from 'react-responsive'
|
||||||
import {
|
import {
|
||||||
TbBook2,
|
TbBook2,
|
||||||
TbBuilding,
|
TbBuilding,
|
||||||
|
@ -11,10 +12,13 @@ import {
|
||||||
import search, { Book } from '../scripts/searcher';
|
import search, { Book } from '../scripts/searcher';
|
||||||
|
|
||||||
import { IoLanguage } from 'react-icons/io5';
|
import { IoLanguage } from 'react-icons/io5';
|
||||||
|
import { IoShareSocialOutline } from 'react-icons/io5';
|
||||||
import SearchInput from './SearchInput';
|
import SearchInput from './SearchInput';
|
||||||
import { useDebounceEffect } from 'ahooks';
|
import { useDebounceEffect } from 'ahooks';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import SearchLanguage from './SearchLanguage';
|
import SearchLanguage from './SearchLanguage';
|
||||||
|
import { MEDIA_QUERY_DESKTOP_STARTS, MEDIA_QUERY_MOBILE_ENDS } from '../constants/mediaquery';
|
||||||
|
import CopyToClipboardButton from './CopyToClipboardButton';
|
||||||
|
|
||||||
function constructQuery(parts: Record<string, string>): string {
|
function constructQuery(parts: Record<string, string>): string {
|
||||||
return Object.keys(parts)
|
return Object.keys(parts)
|
||||||
|
@ -44,6 +48,27 @@ const Search: React.FC<SearchProps> = ({ setBooks }) => {
|
||||||
const [complexQuery, setComplexQuery] = useState<string>('');
|
const [complexQuery, setComplexQuery] = useState<string>('');
|
||||||
const [showLanguageDropdown, setShowLanguageDropdown] = useState<boolean>(true)
|
const [showLanguageDropdown, setShowLanguageDropdown] = useState<boolean>(true)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const params = new Proxy(new URLSearchParams(window.location.search), {
|
||||||
|
//@ts-ignore
|
||||||
|
get: (searchParams, prop) => searchParams.get(prop),
|
||||||
|
});
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
params.title && setTitle(String(params.title))
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
params.author && setAuthor(String(params.author))
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
if (params.language) {
|
||||||
|
//@ts-ignore
|
||||||
|
setLanguage(String(params.language))
|
||||||
|
setShowLanguageDropdown(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [])
|
||||||
|
|
||||||
const handleLanguageChange = (language: string) => {
|
const handleLanguageChange = (language: string) => {
|
||||||
if (language == 'input') {
|
if (language == 'input') {
|
||||||
setShowLanguageDropdown(false)
|
setShowLanguageDropdown(false)
|
||||||
|
@ -57,6 +82,27 @@ const Search: React.FC<SearchProps> = ({ setBooks }) => {
|
||||||
setLanguage('')
|
setLanguage('')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasAnySearchBeenMade = () => {
|
||||||
|
return (
|
||||||
|
title !== ''
|
||||||
|
|| author !== ''
|
||||||
|
|| language !== ''
|
||||||
|
|| publisher !== ''
|
||||||
|
|| extension !== ''
|
||||||
|
|| isbn !== ''
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyToClipboard = () => {
|
||||||
|
const searchQuery = `${window.location.host}?title=${title}&author=${author}&language=${language}&publisher=${publisher}&isbn=${isbn}&extension=${extension}`;
|
||||||
|
|
||||||
|
navigator.clipboard.writeText(searchQuery).then(() => {
|
||||||
|
//console.log('Async: Copying to clipboard was successful!');
|
||||||
|
}, (err) => {
|
||||||
|
//console.error('Async: Could not copy text: ', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
useDebounceEffect(
|
useDebounceEffect(
|
||||||
() => {
|
() => {
|
||||||
const query = complexQuery
|
const query = complexQuery
|
||||||
|
@ -72,66 +118,71 @@ const Search: React.FC<SearchProps> = ({ setBooks }) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SimpleGrid
|
<>
|
||||||
columns={{ sm: 1, md: 2, lg: 3 }}
|
<SimpleGrid
|
||||||
spacing={{ base: 2, md: 4 }}
|
columns={{ sm: 1, md: 2, lg: 3 }}
|
||||||
px={{ base: 4, md: 8 }}
|
spacing={{ base: 2, md: 4 }}
|
||||||
>
|
px={{ base: 4, md: 8 }}
|
||||||
<SearchInput
|
>
|
||||||
icon={<Icon as={TbBook2} />}
|
|
||||||
placeholder={t('book.title')}
|
|
||||||
value={title}
|
|
||||||
onChange={setTitle}
|
|
||||||
/>
|
|
||||||
<SearchInput
|
|
||||||
icon={<Icon as={TbUserCircle} />}
|
|
||||||
placeholder={t('book.author')}
|
|
||||||
value={author}
|
|
||||||
onChange={setAuthor}
|
|
||||||
/>
|
|
||||||
<SearchInput
|
|
||||||
icon={<Icon as={TbBuilding} />}
|
|
||||||
placeholder={t('book.publisher')}
|
|
||||||
value={publisher}
|
|
||||||
onChange={setPublisher}
|
|
||||||
/>
|
|
||||||
<SearchInput
|
|
||||||
icon={<Icon as={TbFileDescription} />}
|
|
||||||
placeholder={t('book.extension')}
|
|
||||||
value={extension}
|
|
||||||
onChange={setExtension}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{!showLanguageDropdown && (<SearchInput
|
|
||||||
icon={<Icon as={IoLanguage} />}
|
|
||||||
placeholder={t('input.select_language')}
|
|
||||||
value={language}
|
|
||||||
onChange={handleLanguageChange}
|
|
||||||
onClear={handleLanguageReset}
|
|
||||||
/>)}
|
|
||||||
|
|
||||||
{showLanguageDropdown && (<SearchLanguage
|
|
||||||
icon={<Icon as={IoLanguage} />}
|
|
||||||
placeholder={t('input.select_language')}
|
|
||||||
value={language}
|
|
||||||
onChange={handleLanguageChange}
|
|
||||||
/>)}
|
|
||||||
|
|
||||||
<SearchInput
|
|
||||||
icon={<Icon as={TbHash} />}
|
|
||||||
placeholder={t('book.isbn')}
|
|
||||||
value={isbn}
|
|
||||||
onChange={setISBN}
|
|
||||||
/>
|
|
||||||
<GridItem colSpan={{ sm: 1, md: 2, lg: 3 }}>
|
|
||||||
<SearchInput
|
<SearchInput
|
||||||
icon={<Icon as={TbReportSearch} />}
|
icon={<Icon as={TbBook2} />}
|
||||||
placeholder={t('search.complex')}
|
placeholder={t('book.title')}
|
||||||
value={complexQuery}
|
value={title}
|
||||||
onChange={setComplexQuery}
|
onChange={setTitle}
|
||||||
/>
|
/>
|
||||||
</GridItem>
|
<SearchInput
|
||||||
</SimpleGrid>
|
icon={<Icon as={TbUserCircle} />}
|
||||||
|
placeholder={t('book.author')}
|
||||||
|
value={author}
|
||||||
|
onChange={setAuthor}
|
||||||
|
/>
|
||||||
|
<SearchInput
|
||||||
|
icon={<Icon as={TbBuilding} />}
|
||||||
|
placeholder={t('book.publisher')}
|
||||||
|
value={publisher}
|
||||||
|
onChange={setPublisher}
|
||||||
|
/>
|
||||||
|
<SearchInput
|
||||||
|
icon={<Icon as={TbFileDescription} />}
|
||||||
|
placeholder={t('book.extension')}
|
||||||
|
value={extension}
|
||||||
|
onChange={setExtension}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{!showLanguageDropdown && (<SearchInput
|
||||||
|
icon={<Icon as={IoLanguage} />}
|
||||||
|
placeholder={t('input.select_language')}
|
||||||
|
value={language}
|
||||||
|
onChange={handleLanguageChange}
|
||||||
|
onClear={handleLanguageReset}
|
||||||
|
/>)}
|
||||||
|
|
||||||
|
{showLanguageDropdown && (<SearchLanguage
|
||||||
|
icon={<Icon as={IoLanguage} />}
|
||||||
|
placeholder={t('input.select_language')}
|
||||||
|
value={language}
|
||||||
|
onChange={handleLanguageChange}
|
||||||
|
/>)}
|
||||||
|
|
||||||
|
<SearchInput
|
||||||
|
icon={<Icon as={TbHash} />}
|
||||||
|
placeholder={t('book.isbn')}
|
||||||
|
value={isbn}
|
||||||
|
onChange={setISBN}
|
||||||
|
/>
|
||||||
|
<GridItem colSpan={{ sm: 1, md: 2, lg: 3 }}>
|
||||||
|
<SearchInput
|
||||||
|
icon={<Icon as={TbReportSearch} />}
|
||||||
|
placeholder={t('search.complex')}
|
||||||
|
value={complexQuery}
|
||||||
|
onChange={setComplexQuery}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
</SimpleGrid>
|
||||||
|
<CopyToClipboardButton
|
||||||
|
show={hasAnySearchBeenMade()}
|
||||||
|
onClick={copyToClipboard} />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,9 @@
|
||||||
"collapse": "Collapse"
|
"collapse": "Collapse"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"complex": "Complex search"
|
"complex": "Complex search",
|
||||||
|
"copy_search_link": "Copy to clipboard",
|
||||||
|
"copy_success": "Copied!"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"title": "Settings",
|
"title": "Settings",
|
||||||
|
@ -205,7 +207,9 @@
|
||||||
"collapse": "Richiudi"
|
"collapse": "Richiudi"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"complex": "Ricerca dettagliata"
|
"complex": "Ricerca dettagliata",
|
||||||
|
"copy_search_link": "Copia link ricerca",
|
||||||
|
"copy_success": "Copiato negli appunti!"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"title": "Impostazioni",
|
"title": "Impostazioni",
|
||||||
|
|
Loading…
Reference in New Issue