This commit is contained in:
Braydon 2024-04-16 16:40:25 -04:00
parent 3588b5f93c
commit c6259e3c8d
15 changed files with 242 additions and 76 deletions

Binary file not shown.

@ -31,7 +31,7 @@
}, },
"navbarLinks": { "navbarLinks": {
"Player": "/player", "Player": "/player",
"Server": "/player", "Server": "/server",
"Mojang": "/mojang", "Mojang": "/mojang",
"Docs": "/docs" "Docs": "/docs"
}, },

@ -12,6 +12,8 @@
}, },
"dependencies": { "dependencies": {
"@heroicons/react": "^2.1.3", "@heroicons/react": "^2.1.3",
"@hookform/resolvers": "^3.3.4",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tooltip": "^1.0.7", "@radix-ui/react-tooltip": "^1.0.7",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
@ -22,7 +24,8 @@
"next-themes": "^0.3.0", "next-themes": "^0.3.0",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"restfulmc-lib": "^1.0.7", "react-hook-form": "^7.51.3",
"restfulmc-lib": "^1.0.9",
"tailwind-merge": "^2.2.2", "tailwind-merge": "^2.2.2",
"tailwindcss-animate": "^1.0.7" "tailwindcss-animate": "^1.0.7"
}, },

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@ -11,13 +11,16 @@ import Link from "next/link";
const DocsPage = (): JSX.Element => ( const DocsPage = (): JSX.Element => (
<main className="h-[64vh] flex flex-col gap-3 justify-center items-center"> <main className="h-[64vh] flex flex-col gap-3 justify-center items-center">
{/* Creeper */} {/* Creeper */}
<div className="absolute left-28 bottom-16"> <div className="absolute left-28 bottom-16 pointer-events-none">
<Creeper /> <Creeper />
</div> </div>
{/* Header */} {/* Header */}
<h1 <h1
className={cn("text-6xl text-minecraft-green-3", minecrafter.className)} className={cn(
"text-6xl text-minecraft-green-3 pointer-events-none",
minecrafter.className
)}
> >
Documentation Documentation
</h1> </h1>

@ -0,0 +1,72 @@
import PlayerSearch from "@/components/player/player-search";
import { minecrafter } from "@/font/fonts";
import { cn } from "@/lib/utils";
import { PageProps } from "@/types/page";
import { Metadata } from "next";
import Image from "next/image";
import { CachedPlayer, getPlayer, type RestfulMCAPIError } from "restfulmc-lib";
/**
* The page to lookup a player.
*
* @returns the page jsx
*/
const PlayerPage = async ({ params }: PageProps): Promise<JSX.Element> => {
let error: string | undefined = undefined; // The error to display
let result: CachedPlayer | undefined = undefined; // The player to display
const query: string | undefined = params.slug; // The query to search for
try {
result = params.slug ? await getPlayer(query) : undefined; // Get the player to display
} catch (err) {
error = (err as RestfulMCAPIError).message; // Set the error message
}
// Render the page
return (
<main className="h-screen flex flex-col justify-center items-center">
<div className="flex gap-32">
{/* Header */}
<Image
className="pointer-events-none"
src="/media/players.webp"
alt="Minecraft Players"
width={632}
height={632}
/>
<div className="flex flex-col gap-7">
<h1
className={cn(
"mt-20 text-6xl text-minecraft-green-3 pointer-events-none",
minecrafter.className
)}
>
Player Lookup
</h1>
{/* Error */}
{error && <p className="text-red-500">{error}</p>}
{/* Search */}
<PlayerSearch query={query} />
</div>
</div>
</main>
);
};
/**
* Generate metadata for this page.
*
* @param params the route params
* @param searchParams the search params
* @returns the generated metadata
*/
const generateMetadata = async ({ params }: PageProps): Promise<Metadata> => {
console.log("params", params);
return {
title: "bob ross",
};
};
export default PlayerPage;

@ -32,11 +32,11 @@ const FeaturedItem = ({
href, href,
}: FeaturedItemProps): JSX.Element => ( }: FeaturedItemProps): JSX.Element => (
<Link <Link
className={cn( className="pt-28 w-[19rem] h-80 flex flex-col gap-1 items-center bg-center bg-cover bg-no-repeat rounded-3xl text-center backdrop-blur-md hover:scale-[1.01] transition-all transform-gpu"
"pt-28 w-[19rem] h-80 flex flex-col gap-1 items-center rounded-3xl text-center backdrop-blur-md hover:scale-[1.01] transition-all transform-gpu",
"bg-[url('" + image + "')] bg-center bg-cover bg-no-repeat" // Couldn't do inline variable interpolation, it threw an error
)}
href={href} href={href}
style={{
backgroundImage: `url(${image})`,
}}
> >
<h1 <h1
className={cn("text-3xl font-semibold text-white", minecrafter.className)} className={cn("text-3xl font-semibold text-white", minecrafter.className)}

@ -1,6 +1,21 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
/**
* Props for this button.
*/
type MinecraftButtonProps = {
/**
* The class name to apply to this button.
*/
className?: string;
/**
* The children of this button.
*/
children: React.ReactNode;
};
/** /**
* A Minecraft styled button. * A Minecraft styled button.
* *
@ -10,10 +25,8 @@ const MinecraftButton = ({
className, className,
children, children,
...props ...props
}: Readonly<{ }: React.ButtonHTMLAttributes<HTMLButtonElement> &
className?: string; MinecraftButtonProps): JSX.Element => (
children: React.ReactNode;
}>): JSX.Element => (
<Button <Button
className={cn( className={cn(
"before:absolute before:-inset-x-5 before:rotate-90 before:w-9 before:h-1 before:bg-minecraft-green-1", // Left Green Bar "before:absolute before:-inset-x-5 before:rotate-90 before:w-9 before:h-1 before:bg-minecraft-green-1", // Left Green Bar

@ -1,3 +1,5 @@
"use client";
import GitHubStarCount from "@/components/github-star-count"; import GitHubStarCount from "@/components/github-star-count";
import MinecraftButton from "@/components/minecraft-button"; import MinecraftButton from "@/components/minecraft-button";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
@ -7,6 +9,7 @@ import { cn } from "@/lib/utils";
import { StarIcon } from "@heroicons/react/24/outline"; import { StarIcon } from "@heroicons/react/24/outline";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { usePathname } from "next/navigation";
import { Suspense } from "react"; import { Suspense } from "react";
/** /**
@ -14,7 +17,9 @@ import { Suspense } from "react";
* *
* @returns the navbar jsx * @returns the navbar jsx
*/ */
const Navbar = (): JSX.Element => ( const Navbar = (): JSX.Element => {
const path: string = usePathname(); // Get the current path
return (
<nav className="fixed inset-x-0 flex h-16 px-12 justify-center sm:justify-between items-center bg-navbar-background z-50"> <nav className="fixed inset-x-0 flex h-16 px-12 justify-center sm:justify-between items-center bg-navbar-background z-50">
{/* Left */} {/* Left */}
<div className="flex gap-7 lg:gap-12 items-center transition-all transform-gpu"> <div className="flex gap-7 lg:gap-12 items-center transition-all transform-gpu">
@ -41,15 +46,22 @@ const Navbar = (): JSX.Element => (
{/* Links */} {/* Links */}
<div className="flex gap-7"> <div className="flex gap-7">
{Object.entries(config.navbarLinks).map((link, index) => ( {Object.entries(config.navbarLinks).map((link, index) => {
const url: string = link[1]; // The href of the link
let active: boolean = path.startsWith(url); // Is this the active link?
return (
<Link <Link
key={index} key={index}
className="font-semibold uppercase hover:text-minecraft-green-4 transition-all transform-gpu" className={cn(
href={link[1]} "font-semibold uppercase hover:text-minecraft-green-4 transition-all transform-gpu",
active && "text-minecraft-green-4"
)}
href={url}
> >
{link[0]} {link[0]}
</Link> </Link>
))} );
})}
</div> </div>
</div> </div>
@ -78,5 +90,6 @@ const Navbar = (): JSX.Element => (
</MinecraftButton> </MinecraftButton>
</div> </div>
</nav> </nav>
); );
};
export default Navbar; export default Navbar;

@ -0,0 +1,31 @@
import MinecraftButton from "@/components/minecraft-button";
import { Input } from "@/components/ui/input";
import { redirect } from "next/navigation";
/**
* A component for searching for a player.
*
* @param query the query to search for
* @returns the search component jsx
*/
const PlayerSearch = ({
query,
}: {
query: string | undefined;
}): JSX.Element => {
const handleRedirect = async (form: FormData) => {
"use server";
redirect(`/player/${form.get("query")}`);
};
return (
<form
className="flex flex-col gap-7 justify-center items-center"
action={handleRedirect}
>
<Input name="query" placeholder="Username / UUID" defaultValue={query} />
<MinecraftButton type="submit">Search</MinecraftButton>
</form>
);
};
export default PlayerSearch;

@ -0,0 +1,25 @@
import * as React from "react"
import { cn } from "@/app/lib/utils"
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
{...props}
/>
)
}
)
Input.displayName = "Input"
export { Input }

@ -8,7 +8,7 @@ import { cn } from "@/lib/utils";
* @returns the page jsx * @returns the page jsx
*/ */
const NotFoundPage = (): JSX.Element => ( const NotFoundPage = (): JSX.Element => (
<main className="h-[84vh] flex flex-col gap-3 justify-center items-center"> <main className="h-[84vh] flex flex-col gap-3 justify-center items-center pointer-events-none">
{/* Creeper */} {/* Creeper */}
<Creeper /> <Creeper />

7
Frontend/src/app/types/page.d.ts vendored Normal file

@ -0,0 +1,7 @@
/**
* Props for a page.
*/
export type PageProps = {
params: { slug: string };
searchParams: { [key: string]: string | string[] | undefined };
};

@ -1 +0,0 @@
//registry.npmjs.org/:_authToken=${NPM_TOKEN}

@ -1,6 +1,6 @@
{ {
"name": "restfulmc-lib", "name": "restfulmc-lib",
"version": "1.0.8", "version": "1.0.9",
"author": "Braydon (Rainnny) <braydonrainnny@gmail.com>", "author": "Braydon (Rainnny) <braydonrainnny@gmail.com>",
"description": "A simple, yet useful RESTful API for Minecraft utilizing Springboot.", "description": "A simple, yet useful RESTful API for Minecraft utilizing Springboot.",
"keywords": [ "keywords": [