Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 42 additions & 11 deletions frontend/src/pages/search/SearchLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@
import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons";
import cx from "classnames";
import { debounce } from "lodash-es";
import { type FC, useCallback, useEffect, useMemo, useRef } from "react";
import {
type FC,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { Badge, Form, Nav } from "react-bootstrap";
import {
NavLink,
Outlet,
useLocation,
useNavigate,
useSearchParams,
} from "react-router-dom";

import { Icon } from "src/components/fragments";
import Title from "src/components/title";
import { ROUTE_SEARCH } from "src/constants/route";
import { useSearchAll } from "src/graphql";

const CLASSNAME = "SearchPage";
const CLASSNAME_INPUT = `${CLASSNAME}-input`;

export interface SearchLayoutOutletContext {
setPerformerCount: (count: number | undefined) => void;
setSceneCount: (count: number | undefined) => void;
}

export const SearchLayout: FC = () => {
const { pathname } = useLocation();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const term = searchParams.get("q") ?? "";
const query = term ? `?q=${encodeURIComponent(term)}` : "";
const isAllTab = pathname === ROUTE_SEARCH;
const [performerCount, setPerformerCount] = useState<number>();
const [sceneCount, setSceneCount] = useState<number>();

const inputRef = useRef<HTMLInputElement>(null);
const inputValueRef = useRef(term);
Expand All @@ -45,15 +63,28 @@ export const SearchLayout: FC = () => {
const handleSearch = useCallback(
(searchTerm: string) => {
inputValueRef.current = searchTerm;
debouncedSearch(searchTerm, location.pathname);
debouncedSearch(searchTerm, pathname);
},
[debouncedSearch],
[debouncedSearch, pathname],
);

const { data: searchData } = useSearchAll({ term, limit: 10 }, !term);
const { data: searchData } = useSearchAll(
{ term, limit: 10 },
!term || !isAllTab,
);

useEffect(() => {
if (isAllTab) return;
setPerformerCount(undefined);
setSceneCount(undefined);
}, [isAllTab]);

const performerCount = searchData?.searchPerformers.count;
const sceneCount = searchData?.searchScenes.count;
const displayedPerformerCount = isAllTab
? searchData?.searchPerformers.count
: performerCount;
const displayedSceneCount = isAllTab
? searchData?.searchScenes.count
: sceneCount;

return (
<div className={CLASSNAME}>
Expand All @@ -78,26 +109,26 @@ export const SearchLayout: FC = () => {
<Nav.Item>
<Nav.Link as={NavLink} to={`/search/performers${query}`}>
Performers
{performerCount !== undefined && (
{displayedPerformerCount !== undefined && (
<Badge bg="secondary" className="ms-2">
{performerCount}
{displayedPerformerCount}
</Badge>
)}
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link as={NavLink} to={`/search/scenes${query}`}>
Scenes
{sceneCount !== undefined && (
{displayedSceneCount !== undefined && (
<Badge bg="secondary" className="ms-2">
{sceneCount}
{displayedSceneCount}
</Badge>
)}
</Nav.Link>
</Nav.Item>
</Nav>

<Outlet />
<Outlet context={{ setPerformerCount, setSceneCount }} />
</div>
);
};
10 changes: 8 additions & 2 deletions frontend/src/pages/search/SearchPerformersTab.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { type FC, useState } from "react";
import { useSearchParams } from "react-router-dom";
import { type FC, useEffect, useState } from "react";
import { useOutletContext, useSearchParams } from "react-router-dom";
import { LoadingIndicator } from "src/components/fragments";
import { List } from "src/components/list";
import { type GenderEnum, useSearchPerformers } from "src/graphql";
import { usePagination } from "src/hooks";
import { GenderFacet } from "./GenderFacet";
import { PerformerCard } from "./PerformerCard";
import type { SearchLayoutOutletContext } from "./SearchLayout";

const PER_PAGE = 20;

Expand All @@ -14,6 +15,7 @@ export const SearchPerformersTab: FC = () => {
const term = searchParams.get("q") ?? "";
const { page, setPage } = usePagination();
const [selectedGender, setSelectedGender] = useState<GenderEnum | null>(null);
const { setPerformerCount } = useOutletContext<SearchLayoutOutletContext>();

const { loading, data } = useSearchPerformers(
{
Expand All @@ -32,6 +34,10 @@ export const SearchPerformersTab: FC = () => {
setPage(1);
};

useEffect(() => {
setPerformerCount(data?.searchPerformers.count);
}, [data?.searchPerformers.count, setPerformerCount]);

if (!term) {
return null;
}
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/pages/search/SearchScenesTab.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import type { FC } from "react";
import { useSearchParams } from "react-router-dom";
import { type FC, useEffect } from "react";
import { useOutletContext, useSearchParams } from "react-router-dom";
import { LoadingIndicator } from "src/components/fragments";
import { List } from "src/components/list";
import { useSearchScenes } from "src/graphql";
import { usePagination } from "src/hooks";

import { SceneCard } from "./SceneCard";
import type { SearchLayoutOutletContext } from "./SearchLayout";

const PER_PAGE = 20;

export const SearchScenesTab: FC = () => {
const [searchParams] = useSearchParams();
const term = searchParams.get("q") ?? "";
const { page, setPage } = usePagination();
const { setSceneCount } = useOutletContext<SearchLayoutOutletContext>();

const { loading, data } = useSearchScenes(
{
Expand All @@ -23,6 +25,10 @@ export const SearchScenesTab: FC = () => {
!term,
);

useEffect(() => {
setSceneCount(data?.searchScenes.count);
}, [data?.searchScenes.count, setSceneCount]);

if (!term) {
return null;
}
Expand Down
Loading