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

nextui
Guus van Meerveld 4 weeks 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 { Container } from "@/components/Container";
import { Search } from "@/components/Search";
import { SearchPageBody } from "./SearchPageBody";
import { SearchPageHeader } from "./SearchPageHeader";
export const SearchPage: FC = () => {
const searchParams = useSearchParams();
@ -16,7 +16,7 @@ export const SearchPage: FC = () => {
const query = useMemo(() => {
const param = searchParams.get("search_query");
if (param === null || param.length === null) return;
if (param === null || param.length === 0) return;
return param;
}, [searchParams]);
@ -34,7 +34,7 @@ export const SearchPage: FC = () => {
return (
<>
<Container>
<SearchPageHeader query={query} filter={filter} />
<Search query={query} filter={filter} />
{query && <SearchPageBody query={query} filter={filter} />}
</Container>
</>

@ -2,9 +2,9 @@ import { NextPage } from "next";
import { Suspense } from "react";
import { Container } from "@/components/Container";
import { Search } from "@/components/Search";
import { SearchPage } from "./SearchPage";
import { SearchPageHeader } from "./SearchPageHeader";
const Page: NextPage = () => {
return (
@ -12,7 +12,7 @@ const Page: NextPage = () => {
<Suspense
fallback={
<Container>
<SearchPageHeader />
<Search />
</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";
export const Search: FC<{
export const Input: FC<{
query?: string;
setQuery: (query: string) => void;
}> = ({ setQuery, query }) => {
@ -29,10 +29,6 @@ export const Search: FC<{
}
});
const submit = (query: string): void => {
setQuery(query);
};
const suggestions = useMemo(
() =>
data?.map((suggestion) => ({
@ -43,41 +39,39 @@ export const Search: FC<{
);
return (
<form onSubmit={() => submit(searchQuery)}>
<Autocomplete
isClearable={false}
name="search_query"
value={searchQuery}
isLoading={isLoading}
defaultInputValue={query}
onValueChange={setSearchQuery}
onKeyDown={(e) => {
if (e.key === "Enter") {
submit(searchQuery);
}
}}
startContent={<SearchIcon className="text-xl" />}
defaultItems={suggestions}
onSelectionChange={(key) => {
if (key === null) return;
<Autocomplete
isClearable={false}
name="search_query"
value={searchQuery}
isLoading={isLoading}
defaultInputValue={query}
onValueChange={setSearchQuery}
onKeyDown={(e) => {
if (e.key === "Enter") {
setQuery(searchQuery);
}
}}
startContent={<SearchIcon className="text-xl" />}
defaultItems={suggestions}
onSelectionChange={(key) => {
if (key === null) return;
setSearchQuery(key.toString());
submit(key.toString());
}}
errorMessage={error !== null ? error.toString() : ""}
isInvalid={error !== null}
required
type="text"
label="Search"
variant="bordered"
placeholder="Search for videos"
>
{(suggestion) => (
<AutocompleteItem key={suggestion.value}>
{suggestion.label}
</AutocompleteItem>
)}
</Autocomplete>
</form>
setSearchQuery(key.toString());
setQuery(key.toString());
}}
errorMessage={error !== null ? error.toString() : ""}
isInvalid={error !== null}
required
type="text"
label="Search"
variant="bordered"
placeholder="Search for videos"
>
{(suggestion) => (
<AutocompleteItem key={suggestion.value}>
{suggestion.label}
</AutocompleteItem>
)}
</Autocomplete>
);
};

@ -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";
export const useSearch = (): ((query: string, filter?: SearchType) => void) => {
export const useSearch = (): ((query: string, filter: SearchType) => void) => {
const router = useRouter();
return (query, filter = "all") => {
return (query, filter) => {
const params = new URLSearchParams();
params.set("search_query", query);

Loading…
Cancel
Save