restructured youtube paths, added search modal
continuous-integration/drone/push Build is passing Details

nextui
Guus van Meerveld 8 months ago
parent d2cef1f072
commit 189c651941

@ -0,0 +1,54 @@
"use client";
import { Button } from "@nextui-org/react";
import { FC, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import {
Modal,
ModalBody,
ModalContent,
ModalFooter,
ModalHeader
} from "@nextui-org/modal";
import { Search } from "@/components/Search";
export const SearchModal: FC = () => {
const [isOpen, setOpen] = useState(false);
useHotkeys(
"ctrl+k",
() => {
setOpen(true);
},
{ preventDefault: true }
);
return (
<Modal
isOpen={isOpen}
onOpenChange={(isOpen) => {
setOpen(isOpen);
}}
size="2xl"
>
<ModalContent>
{(onClose) => (
<>
<ModalHeader className="flex flex-col gap-1">Search</ModalHeader>
<ModalBody>
<Search onSearch={() => onClose()} />
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary">Search</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
);
};

@ -0,0 +1,14 @@
import { SearchModal } from "./SearchModal";
import { Component } from "@/typings/component";
const YoutubeLayout: Component = ({ children }) => {
return (
<>
{children}
<SearchModal />
</>
);
};
export default YoutubeLayout;

@ -6,9 +6,9 @@ import { FC, useMemo } from "react";
import { SearchType, SearchTypeModel } from "@/client/typings/search/options"; import { SearchType, SearchTypeModel } from "@/client/typings/search/options";
import { Container } from "@/components/Container"; import { Container } from "@/components/Container";
import { Search } from "@/components/Search";
import { SearchPageBody } from "./SearchPageBody"; import { SearchPageBody } from "./SearchPageBody";
import { SearchPageHeader } from "./SearchPageHeader";
export const SearchPage: FC = () => { export const SearchPage: FC = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
@ -16,7 +16,7 @@ export const SearchPage: FC = () => {
const query = useMemo(() => { const query = useMemo(() => {
const param = searchParams.get("search_query"); const param = searchParams.get("search_query");
if (param === null || param.length === null) return; if (param === null || param.length === 0) return;
return param; return param;
}, [searchParams]); }, [searchParams]);
@ -34,7 +34,7 @@ export const SearchPage: FC = () => {
return ( return (
<> <>
<Container> <Container>
<SearchPageHeader query={query} filter={filter} /> <Search query={query} filter={filter} />
{query && <SearchPageBody query={query} filter={filter} />} {query && <SearchPageBody query={query} filter={filter} />}
</Container> </Container>
</> </>

@ -2,9 +2,9 @@ import { NextPage } from "next";
import { Suspense } from "react"; import { Suspense } from "react";
import { Container } from "@/components/Container"; import { Container } from "@/components/Container";
import { Search } from "@/components/Search";
import { SearchPage } from "./SearchPage"; import { SearchPage } from "./SearchPage";
import { SearchPageHeader } from "./SearchPageHeader";
const Page: NextPage = () => { const Page: NextPage = () => {
return ( return (
@ -12,7 +12,7 @@ const Page: NextPage = () => {
<Suspense <Suspense
fallback={ fallback={
<Container> <Container>
<SearchPageHeader /> <Search />
</Container> </Container>
} }
> >

@ -1,37 +0,0 @@
"use client";
import { FC } from "react";
import { useSearch } from "@/hooks/useSearch";
import { SearchType } from "@/client/typings/search/options";
import { Search as SearchInput } from "@/components/Search";
import { Filter } from "./Filter";
export const SearchPageHeader: FC<{
query?: string;
filter?: SearchType;
}> = ({ query, filter }) => {
const searchFor = useSearch();
const searchForQuery = (query: string): void => {
searchFor(query, filter);
};
const searchWithFilter = (filter: SearchType): void => {
if (query) searchFor(query, filter);
};
return (
<div className="flex flex-row gap-2">
<div className="flex-1">
<SearchInput query={query} setQuery={searchForQuery} />
</div>
<div>
<Filter filter={filter ?? "all"} setFilter={searchWithFilter} />
</div>
</div>
);
};

@ -10,7 +10,7 @@ import { Autocomplete, AutocompleteItem } from "@nextui-org/autocomplete";
import { useClient } from "@/hooks/useClient"; import { useClient } from "@/hooks/useClient";
export const Search: FC<{ export const Input: FC<{
query?: string; query?: string;
setQuery: (query: string) => void; setQuery: (query: string) => void;
}> = ({ setQuery, query }) => { }> = ({ setQuery, query }) => {
@ -29,10 +29,6 @@ export const Search: FC<{
} }
}); });
const submit = (query: string): void => {
setQuery(query);
};
const suggestions = useMemo( const suggestions = useMemo(
() => () =>
data?.map((suggestion) => ({ data?.map((suggestion) => ({
@ -43,7 +39,6 @@ export const Search: FC<{
); );
return ( return (
<form onSubmit={() => submit(searchQuery)}>
<Autocomplete <Autocomplete
isClearable={false} isClearable={false}
name="search_query" name="search_query"
@ -53,7 +48,7 @@ export const Search: FC<{
onValueChange={setSearchQuery} onValueChange={setSearchQuery}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === "Enter") { if (e.key === "Enter") {
submit(searchQuery); setQuery(searchQuery);
} }
}} }}
startContent={<SearchIcon className="text-xl" />} startContent={<SearchIcon className="text-xl" />}
@ -62,7 +57,7 @@ export const Search: FC<{
if (key === null) return; if (key === null) return;
setSearchQuery(key.toString()); setSearchQuery(key.toString());
submit(key.toString()); setQuery(key.toString());
}} }}
errorMessage={error !== null ? error.toString() : ""} errorMessage={error !== null ? error.toString() : ""}
isInvalid={error !== null} isInvalid={error !== null}
@ -78,6 +73,5 @@ export const Search: FC<{
</AutocompleteItem> </AutocompleteItem>
)} )}
</Autocomplete> </Autocomplete>
</form>
); );
}; };

@ -0,0 +1,41 @@
"use client";
import { FC } from "react";
import { useSearch } from "@/hooks/useSearch";
import { SearchType } from "@/client/typings/search/options";
import { Filter } from "./Filter";
import { Input } from "./Input";
export const Search: FC<{
query?: string;
filter?: SearchType;
onSearch?: (query: string, filter: SearchType) => void;
}> = ({ query = "", filter = "all", onSearch }) => {
const searchFor = useSearch();
const searchForQuery = (query: string): void => {
searchFor(query, filter);
if (onSearch) onSearch(query, filter);
};
const searchWithFilter = (filter: SearchType): void => {
searchFor(query, filter);
if (onSearch) onSearch(query, filter);
};
return (
<form>
<div className="flex flex-row gap-2">
<div className="flex-1">
<Input query={query} setQuery={searchForQuery} />
</div>
<div>
<Filter filter={filter} setFilter={searchWithFilter} />
</div>
</div>
</form>
);
};

@ -4,10 +4,10 @@ import { SearchType } from "@/client/typings/search/options";
const searchPathname = "/results"; const searchPathname = "/results";
export const useSearch = (): ((query: string, filter?: SearchType) => void) => { export const useSearch = (): ((query: string, filter: SearchType) => void) => {
const router = useRouter(); const router = useRouter();
return (query, filter = "all") => { return (query, filter) => {
const params = new URLSearchParams(); const params = new URLSearchParams();
params.set("search_query", query); params.set("search_query", query);

Loading…
Cancel
Save