Add feedback to search buttons
All checks were successful
Deploy Frontend / docker (17, 3.8.5) (push) Successful in 1m7s

This commit is contained in:
Braydon 2024-04-22 01:40:03 -04:00
parent 58a97708fd
commit 8b31904095
2 changed files with 60 additions and 16 deletions

@ -1,10 +1,14 @@
"use client";
import MinecraftButton from "@/components/button/minecraft-button"; import MinecraftButton from "@/components/button/minecraft-button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { redirect } from "next/navigation"; import { useRouter } from "next/navigation";
import { ReactElement } from "react"; import { FormEvent, ReactElement, useState } from "react";
import SimpleTooltip from "@/components/simple-tooltip"; import SimpleTooltip from "@/components/simple-tooltip";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { Loader2 } from "lucide-react";
/** /**
* Props for a player search. * Props for a player search.
@ -23,14 +27,25 @@ type PlayerSearchProps = {
* @returns the search component jsx * @returns the search component jsx
*/ */
const PlayerSearch = ({ query }: PlayerSearchProps): ReactElement => { const PlayerSearch = ({ query }: PlayerSearchProps): ReactElement => {
const handleRedirect = async (form: FormData): Promise<void> => { const router: AppRouterInstance = useRouter();
"use server"; const [loading, setLoading] = useState<boolean>(false); // If the search is loading
redirect(`/player/${form.get("query")}`);
const handleRedirect = async (
event: FormEvent<HTMLFormElement>
): Promise<void> => {
setLoading(true); // Start loading
event.preventDefault(); // Prevent the form from submitting
// Get the form data
const form: FormData = new FormData(event.currentTarget);
router.push(`/player/${form.get("query")}`);
}; };
// Render the search form
return ( return (
<form <form
className="flex flex-col gap-7 justify-center items-center" className="flex flex-col gap-7 justify-center items-center"
action={handleRedirect} onSubmit={handleRedirect}
> >
{/* Input */} {/* Input */}
<div className="w-full flex flex-col gap-3"> <div className="w-full flex flex-col gap-3">
@ -48,7 +63,12 @@ const PlayerSearch = ({ query }: PlayerSearchProps): ReactElement => {
{/* Search */} {/* Search */}
<SimpleTooltip content="Click to search"> <SimpleTooltip content="Click to search">
<MinecraftButton type="submit">Search</MinecraftButton> <MinecraftButton type="submit" disabled={loading}>
{loading && (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
)}
Search
</MinecraftButton>
</SimpleTooltip> </SimpleTooltip>
</form> </form>
); );

@ -1,3 +1,5 @@
"use client";
import MinecraftButton from "@/components/button/minecraft-button"; import MinecraftButton from "@/components/button/minecraft-button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
@ -10,10 +12,12 @@ import {
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { capitalize } from "@/app/common/string-utils"; import { capitalize } from "@/app/common/string-utils";
import { redirect } from "next/navigation"; import { useRouter } from "next/navigation";
import { ReactElement } from "react"; import { FormEvent, ReactElement, useState } from "react";
import { ServerPlatform } from "restfulmc-lib"; import { ServerPlatform } from "restfulmc-lib";
import SimpleTooltip from "@/components/simple-tooltip"; import SimpleTooltip from "@/components/simple-tooltip";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { Loader2 } from "lucide-react";
/** /**
* Props for a server search. * Props for a server search.
@ -22,7 +26,7 @@ type ServerSearchProps = {
/** /**
* The original platform to query for. * The original platform to query for.
*/ */
platform: ServerPlatform | undefined; platform: string | undefined;
/** /**
* The original hostname to query for. * The original hostname to query for.
@ -41,21 +45,36 @@ const ServerSearch = ({
platform, platform,
hostname, hostname,
}: ServerSearchProps): ReactElement => { }: ServerSearchProps): ReactElement => {
const handleRedirect = async (form: FormData): Promise<void> => { const router: AppRouterInstance = useRouter();
"use server"; const [loading, setLoading] = useState<boolean>(false); // If the search is loading
redirect(`/server/${form.get("platform")}/${form.get("hostname")}`);
const handleRedirect = async (
event: FormEvent<HTMLFormElement>
): Promise<void> => {
setLoading(true); // Start loading
event.preventDefault(); // Prevent the form from submitting
// Get the form data
const form: FormData = new FormData(event.currentTarget);
router.push(`/server/${form.get("platform")}/${form.get("hostname")}`);
}; };
// Render the search form
return ( return (
<form <form
className="flex flex-col gap-7 justify-center items-center" className="flex flex-col gap-7 justify-center items-center"
action={handleRedirect} onSubmit={handleRedirect}
> >
{/* Input */} {/* Input */}
<div className="w-full flex gap-2"> <div className="w-full flex gap-2">
{/* Platform Selection */} {/* Platform Selection */}
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
<Label htmlFor="platform">Platform</Label> <Label htmlFor="platform">Platform</Label>
<Select name="platform" defaultValue={platform} required> <Select
name="platform"
defaultValue={platform || "java"}
required
>
<SelectTrigger className="w-28"> <SelectTrigger className="w-28">
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
@ -91,7 +110,12 @@ const ServerSearch = ({
{/* Search */} {/* Search */}
<SimpleTooltip content="Click to search"> <SimpleTooltip content="Click to search">
<MinecraftButton type="submit">Search</MinecraftButton> <MinecraftButton type="submit" disabled={loading}>
{loading && (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
)}
Search
</MinecraftButton>
</SimpleTooltip> </SimpleTooltip>
</form> </form>
); );