diff --git a/src/components/Layout/Header.astro b/src/components/Layout/Header.astro index 1f74848..5b86756 100644 --- a/src/components/Layout/Header.astro +++ b/src/components/Layout/Header.astro @@ -21,6 +21,7 @@ const { title, description, schemaData } = Astro.props; rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.4.0/dist/duet/themes/default.css" /> + {schemaData && } \ No newline at end of file diff --git a/src/components/Search/App.tsx b/src/components/Search/App.tsx index a98d048..ff0eb0b 100644 --- a/src/components/Search/App.tsx +++ b/src/components/Search/App.tsx @@ -1,3 +1,4 @@ +import { algoliasearch } from "algoliasearch"; import React, { useState, useRef, useEffect } from "react"; import { Configure, @@ -12,9 +13,10 @@ import { ToggleRefinement, HitsPerPage, CurrentRefinements, - Stats, RangeInput + Stats, + } from 'react-instantsearch' - import { algoliasearch } from "algoliasearch"; + import { createBrowserHistory } from "history"; import HitTest from "@components/Search/Hit"; import "../../styles/App/App.css"; @@ -24,25 +26,21 @@ import "../../styles/App/App.mobile.css"; import "../../styles/App/Pagination.css"; import { Panel } from '@components/Search/Panel.tsx' - -import CustomRangeSlider from '@components/Search/DateRange.tsx' -import DateRangeSliderFilter from '@components/Search/DateRange.tsx' import DateRangeSlider from '@components/Search/DateRange.tsx' - +import { ClearFiltersMobile } from '@components/Search/ClearFiltersMobile.tsx' +import { SaveFiltersMobile } from '@components/Search/SaveFiltersMobile.tsx' const searchClient = algoliasearch("ZLPYTBTZ4R", "be46d26dfdb299f9bee9146b63c99c77"); + + +import { ResultsNumberMobile } from '@components/Search/ResultsNumberMobile.tsx' +import { ClearFilters } from '@components/Search/ClearFilters.tsx' +import { NoResultsBoundary } from '@components/Search/NoResultsBoundary.tsx' +import { NoResults } from '@components/Search/NoResults.tsx' +import { ScrollTo } from '@components/Search/ScrollTo.tsx' // Custom router setup const history = createBrowserHistory(); -const dateToTimestamp = (dateString) => { - const date = new Date(dateString); - return isNaN(date.getTime()) ? null : Math.floor(date.getTime() / 1000); -}; -const timestampToDate = (timestamp) => { - if (timestamp === null || timestamp === undefined) return ""; - const date = new Date(timestamp * 1000); - return date.toISOString().split('T')[0]; -}; function createURL(routeState) { const { q } = routeState; @@ -58,8 +56,6 @@ function getStateFromLocation(location) { q: searchParams.get("q") || "", }; } -const MIN_TIMESTAMP = -17987443200; // January 1, 1400 in UNIX timestamp -const MAX_TIMESTAMP = -2208988800; // January 1, 1900 in UNIX timestamp const routing = { router: { @@ -105,23 +101,42 @@ const routing = { function App() { const containerRef = useRef(null); + const headerRef = useRef(null); const searchParams = new URLSearchParams(window.location.search); const initialQuery = searchParams.get("q") || ""; function openFilters() { - document.body.classList.add("filtering"); + document.body.classList.add('filtering'); window.scrollTo(0, 0); + window.addEventListener('keyup', onKeyUp); + window.addEventListener('click', onClick); } + function closeFilters() { document.body.classList.remove("filtering"); containerRef.current?.scrollIntoView({ behavior: "smooth" }); } + function onKeyUp(event: { key: string }) { + if (event.key !== 'Escape') { + return; + } + + closeFilters(); + } + + function onClick(event: MouseEvent) { + if (event.target !== headerRef.current) { + return; + } + + closeFilters(); + } return (
-
+

Explore the Kaplan Collection

(
Loading
)} + submitIconComponent={SubmitIcon} />
- - + +

Filters

- +
+ +
+ +
+ +
+ +
+ - + - - + + @@ -157,17 +188,17 @@ function App() {
-
+
+
+ +
+ +
+ +
+
- + + +
- + }> + +
+
+
+ +
+ +
+ +
+
+
+ +
- ); -} + ); + } + + function SubmitIcon() { + return ( + + ); + } export default App; \ No newline at end of file diff --git a/src/components/Search/ClearFiltersMobile.tsx b/src/components/Search/ClearFiltersMobile.tsx new file mode 100644 index 0000000..933bfb6 --- /dev/null +++ b/src/components/Search/ClearFiltersMobile.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { useClearRefinements } from 'react-instantsearch'; + +export function ClearFiltersMobile({ + containerRef, + }: { + containerRef: React.RefObject; +}) { + const { refine } = useClearRefinements(); + + function onClick() { + refine(); + document.body.classList.remove('filtering'); + containerRef.current!.scrollIntoView(); + } + + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/src/components/Search/DateConnect.tsx b/src/components/Search/DateConnect.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/Search/Hit.tsx b/src/components/Search/Hit.tsx index 01209e5..b7e7140 100644 --- a/src/components/Search/Hit.tsx +++ b/src/components/Search/Hit.tsx @@ -5,7 +5,8 @@ type HitProps = { hit: AlgoliaHit<{ name: string; type: string[]; - date: string; + subtype: string[]; + dateC: string; description: string; title: string; geography: string[]; @@ -23,25 +24,26 @@ type HitProps = { export function HitTest({ hit }: HitProps) { return ( -); + ); } export default HitTest; \ No newline at end of file diff --git a/src/components/Search/NoResults.tsx b/src/components/Search/NoResults.tsx index c553b2a..04a2d8e 100644 --- a/src/components/Search/NoResults.tsx +++ b/src/components/Search/NoResults.tsx @@ -1,100 +1,100 @@ -import React from "react"; -import { useInstantSearch } from "react-instantsearch"; +import React from 'react'; +import { useInstantSearch } from 'react-instantsearch'; -import { ClearFilters } from "./ClearFilters"; +import { ClearFilters } from './ClearFilters'; export function NoResults() { - const { results } = useInstantSearch(); + const { results } = useInstantSearch(); - const hasRefinements = results.getRefinements().length > 0; - const description = hasRefinements - ? "Try to reset your applied filters." - : "Please try another query."; + const hasRefinements = results.getRefinements().length > 0; + const description = hasRefinements + ? 'Try to reset your applied filters.' + : 'Please try another query.'; - return ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + -

- Sorry, we can't find any matches to your query! -

-

{description}

+

+ Sorry, we can't find any matches to your query! +

+

{description}

- -
- ); -} + +
+ ); +} \ No newline at end of file diff --git a/src/components/Search/NoResultsBoundary.tsx b/src/components/Search/NoResultsBoundary.tsx new file mode 100644 index 0000000..4335d6e --- /dev/null +++ b/src/components/Search/NoResultsBoundary.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { useInstantSearch } from 'react-instantsearch'; + +export function NoResultsBoundary({ + children, + fallback, + }: { + children: React.ReactNode; + fallback: React.ReactNode; +}) { + const { results } = useInstantSearch(); + + // The `__isArtificial` flag makes sure to not display the No Results message + // when no hits have been returned yet. + if (!results.__isArtificial && results.nbHits === 0) { + return ( + <> + {fallback} + + + ); + } + + return <>{children}; +} \ No newline at end of file diff --git a/src/components/Search/ResultsNumberMobile.tsx b/src/components/Search/ResultsNumberMobile.tsx index 361b438..1c51d07 100644 --- a/src/components/Search/ResultsNumberMobile.tsx +++ b/src/components/Search/ResultsNumberMobile.tsx @@ -1,5 +1,7 @@ -import React from "react"; -import { useInstantSearch } from "react-instantsearch"; +import React from 'react'; +import { useInstantSearch } from 'react-instantsearch'; + +import { formatNumber } from '../../utils'; export function ResultsNumberMobile() { const { @@ -8,7 +10,7 @@ export function ResultsNumberMobile() { return (
- {nbHits} results + {formatNumber(nbHits)} results
); -} +} \ No newline at end of file diff --git a/src/components/Search/SaveFiltersMobile.tsx b/src/components/Search/SaveFiltersMobile.tsx new file mode 100644 index 0000000..2f05c66 --- /dev/null +++ b/src/components/Search/SaveFiltersMobile.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { useInstantSearch } from 'react-instantsearch'; + +import { formatNumber } from '../../utils'; + +export function SaveFiltersMobile({ onClick }: { onClick: () => void }) { + const { + results: { nbHits }, + } = useInstantSearch(); + + return ( + + ); +} \ No newline at end of file diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 0000000..c438747 --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,9 @@ + +export * from './Search/ClearFilters'; +export * from './Search/ClearFiltersMobile'; +export * from './Search/NoResults'; +export * from './Search/NoResultsBoundary'; +export * from './Search/Panel'; + +export * from './Search/ResultsNumberMobile'; +export * from './Search/SaveFiltersMobile'; \ No newline at end of file diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 8fa5a52..251fd9e 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -4,7 +4,7 @@ import Footer from '../components/Layout/Footer.astro'; import Header from '../components/Layout/Header.astro'; // Corrected Header import --- - +
diff --git a/src/pages/search.astro b/src/pages/search.astro index 2fcae01..05760b3 100644 --- a/src/pages/search.astro +++ b/src/pages/search.astro @@ -4,9 +4,10 @@ import BaseLayout from '../layouts/BaseLayout.astro'; import App from '../components/Search/App' import NavAutocomplete from "../components/Search/NavAutocomplete"; +const description = "Search the Arnold and Deanne Kaplan collection of Early American Judaica"; --- - + diff --git a/src/utils/index.ts b/src/utils/index.ts index 3d88969..b9606ca 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -5,5 +5,5 @@ export function formatNumber(number: string | number): string { export function cx( ...classNames: Array ) { - return classNames.filter(Boolean).join(" "); -} + return classNames.filter(Boolean).join(' '); +} \ No newline at end of file