start work on cleaning up types and add try a player and server to their pages
All checks were successful
Deploy App / docker (ubuntu-latest) (push) Successful in 1m29s

This commit is contained in:
Lee 2024-04-22 21:08:44 +01:00
parent 52fea3da68
commit c2790054db
11 changed files with 186 additions and 49 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -5,36 +5,9 @@ import { Button } from "../components/ui/button";
import { Separator } from "../components/ui/separator";
import { Tooltip, TooltipContent, TooltipTrigger } from "../components/ui/tooltip";
import { Title } from "@/app/components/title";
import { LandingButton } from "@/app/types/landing/landing-button";
type Button = {
/**
* The title of the button.
*/
title: string;
/**
* The tooltip to display for this statistic.
*/
tooltip: string;
/**
* The URL to go to.
*/
url: string;
/**
* Whether clicking the button will
* open the link in a new tab.
*/
openInNewTab?: boolean;
/**
* The class name to apply to the button.
*/
className?: string;
};
const buttons: Button[] = [
const buttons: LandingButton[] = [
{
title: "Get Started",
tooltip: "Click to get started with the API",

View File

@ -12,23 +12,23 @@ import { CachedPlayer, getPlayer, McUtilsAPIError } from "mcutils-library";
import { Metadata, Viewport } from "next";
import { ReactElement } from "react";
import { Title } from "@/app/components/title";
import { Card } from "@/app/components/card";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/app/components/ui/tooltip";
import Link from "next/link";
import Image from "next/image";
import { PlayerPageParams } from "@/app/types/player/page-params";
import { TryAPlayer } from "@/app/components/player/try-a-player";
export const revalidate = 60;
type Params = {
params: {
id: string;
};
};
export async function generateViewport({ params: { id } }: Params): Promise<Viewport> {
export async function generateViewport({ params: { id } }: PlayerPageParams): Promise<Viewport> {
const validPlayer = await isValidPlayer(id);
return {
themeColor: validPlayer ? Colors.green : Colors.red,
};
}
export async function generateMetadata({ params: { id } }: Params): Promise<Metadata> {
export async function generateMetadata({ params: { id } }: PlayerPageParams): Promise<Metadata> {
// No id provided
if (!id || id.length === 0) {
return generateEmbed({
@ -55,7 +55,7 @@ export async function generateMetadata({ params: { id } }: Params): Promise<Meta
}
}
export default async function Page({ params: { id } }: Params): Promise<ReactElement> {
export default async function Page({ params: { id } }: PlayerPageParams): Promise<ReactElement> {
let error: string | undefined = undefined; // The error to display
let player: CachedPlayer | undefined = undefined; // The player to display
@ -98,6 +98,9 @@ export default async function Page({ params: { id } }: Params): Promise<ReactEle
</ContextMenuContent>
</ContextMenu>
)}
{/* Try a Player */}
{player == null && !error && <TryAPlayer />}
</div>
);
}

View File

@ -5,7 +5,6 @@ import { ServerView } from "@/app/components/server/server-view";
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from "@/app/components/ui/context-menu";
import { Colors } from "@/app/common/colors";
import { generateEmbed } from "@/app/common/embed";
import { formatNumber } from "@/app/common/number-utils";
import { isValidServer } from "@/app/common/server";
import { capitalizeFirstLetter } from "@/app/common/string-utils";
import config from "@root/config.json";
@ -19,16 +18,16 @@ import {
import { Metadata, Viewport } from "next";
import { ReactElement } from "react";
import { Title } from "@/app/components/title";
import { Card } from "@/app/components/card";
import Link from "next/link";
import Image from "next/image";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/app/components/ui/tooltip";
import { TryMeServer } from "@/app/types/server/try-me-server";
import { ServerPageParams } from "@/app/types/server/page-params";
import { TryAServer } from "@/app/components/server/try-a-server";
export const revalidate = 60;
type Params = {
params: {
platform: ServerPlatform;
hostname: string;
};
};
/**
* Gets the favicon for a server
*
@ -57,14 +56,14 @@ function checkPlatform(platform: ServerPlatform): boolean {
return platform === ServerPlatform.Java || platform === ServerPlatform.Bedrock;
}
export async function generateViewport({ params: { platform, hostname } }: Params): Promise<Viewport> {
export async function generateViewport({ params: { platform, hostname } }: ServerPageParams): Promise<Viewport> {
const validPlayer = await isValidServer(platform, hostname);
return {
themeColor: validPlayer || !platform ? Colors.green : Colors.red,
};
}
export async function generateMetadata({ params: { platform, hostname } }: Params): Promise<Metadata> {
export async function generateMetadata({ params: { platform, hostname } }: ServerPageParams): Promise<Metadata> {
if (!checkPlatform(platform)) {
// Invalid platform
return generateEmbed({
@ -100,7 +99,7 @@ export async function generateMetadata({ params: { platform, hostname } }: Param
}
}
export default async function Page({ params: { platform, hostname } }: Params): Promise<ReactElement> {
export default async function Page({ params: { platform, hostname } }: ServerPageParams): Promise<ReactElement> {
let error: string | undefined = undefined; // The error to display
let server: CachedJavaMinecraftServer | CachedBedrockMinecraftServer | undefined = undefined; // The server to display
let invalidPlatform: boolean = !checkPlatform(platform); // Whether the platform is invalid
@ -129,7 +128,10 @@ export default async function Page({ params: { platform, hostname } }: Params):
<LookupServer currentPlatform={platform.toLowerCase()} currentServer={hostname && hostname[0]} />
</div>
{/* An errored occurred when looking up the server */}
{error && <ErrorCard message={error} />}
{/* The server */}
{server != null && (
<ContextMenu>
<ContextMenuTrigger asChild>
@ -147,6 +149,9 @@ export default async function Page({ params: { platform, hostname } }: Params):
</ContextMenuContent>
</ContextMenu>
)}
{/* Try a Server */}
{server == null && !error && <TryAServer />}
</div>
);
}

View File

@ -0,0 +1,49 @@
import { ReactElement } from "react";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/app/components/ui/tooltip";
import Image from "next/image";
import config from "@root/config.json";
import Link from "next/link";
import { Card } from "@/app/components/card";
/**
* The players to try out.
*/
const tryMePlayers: string[] = ["Notch", "jeb_", "Dinnerbone", "Grumm", "Mojang"];
export function TryAPlayer(): ReactElement {
return (
<Card>
<div className="flex flex-col items-center justify-center text-center">
<div>
<h2 className="text-lg font-semibold">Try a Player</h2>
<p className="text-muted-foreground">Try one of these players to see how the player view works.</p>
</div>
<div className="flex flex-wrap justify-center gap-2 max-w-2xl mt-4">
{tryMePlayers.map(playerName => (
<Tooltip key={playerName}>
<TooltipTrigger asChild>
<div className="flex items-center justify-center bg-background p-1.5 rounded-md gap-2">
<Image
src={`${config.apiEndpoint}/player/head/${playerName}`}
alt={"The player's head"}
width={32}
height={32}
/>
<Link href={`/player/${playerName}`} className="hover:opacity-85 transform-gpu transition-all">
{playerName}
</Link>
</div>
</TooltipTrigger>
<TooltipContent>
<p>
Click to try the player <b>{playerName}</b>.
</p>
</TooltipContent>
</Tooltip>
))}
</div>
</div>
</Card>
);
}

View File

@ -0,0 +1,54 @@
import { ReactElement } from "react";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/app/components/ui/tooltip";
import Image from "next/image";
import Link from "next/link";
import { capitalizeFirstLetter } from "@/app/common/string-utils";
import { Card } from "@/app/components/card";
import { ServerPlatform } from "mcutils-library";
import { TryMeServer } from "@/app/types/server/try-me-server";
/**
* The servers to try out.
*/
const tryMeServers: TryMeServer[] = [
{ platform: ServerPlatform.Java, hostname: "mc.hypixel.net" },
{ platform: ServerPlatform.Java, hostname: "wildprison.net" },
{ platform: ServerPlatform.Java, hostname: "cubecraft.net" },
{ platform: ServerPlatform.Bedrock, hostname: "geo.hivebedrock.network" },
];
export function TryAServer(): ReactElement {
return (
<Card>
<div className="flex flex-col items-center justify-center text-center">
<div>
<h2 className="text-lg font-semibold">Try a Server</h2>
<p className="text-muted-foreground">Try one of these servers to see how the server view works.</p>
</div>
<div className="flex flex-wrap justify-center gap-2 max-w-2xl mt-4">
{tryMeServers.map(({ platform, hostname }) => (
<Tooltip key={hostname}>
<TooltipTrigger asChild>
<div className="flex items-center justify-center bg-background p-1.5 rounded-md gap-2">
<Image src={`/media/platform/${platform}.png`} alt={"The server's platform"} width={28} height={28} />
<Link
href={`/server/${platform}/${hostname}`}
className="hover:opacity-85 transform-gpu transition-all"
>
{hostname}
</Link>
</div>
</TooltipTrigger>
<TooltipContent>
<p>
Click to try the <b>{capitalizeFirstLetter(platform)}</b> server: <b>{hostname}</b>
</p>
</TooltipContent>
</Tooltip>
))}
</div>
</div>
</Card>
);
}

View File

@ -0,0 +1,27 @@
export type LandingButton = {
/**
* The title of the button.
*/
title: string;
/**
* The tooltip to display for this statistic.
*/
tooltip: string;
/**
* The URL to go to.
*/
url: string;
/**
* Whether clicking the button will
* open the link in a new tab.
*/
openInNewTab?: boolean;
/**
* The class name to apply to the button.
*/
className?: string;
};

View File

@ -0,0 +1,5 @@
export type PlayerPageParams = {
params: {
id: string;
};
};

View File

@ -0,0 +1,8 @@
import { ServerPlatform } from "mcutils-library";
export type ServerPageParams = {
params: {
platform: ServerPlatform;
hostname: string;
};
};

View File

@ -0,0 +1,13 @@
import { ServerPlatform } from "mcutils-library";
export type TryMeServer = {
/**
* The platform of the server.
*/
platform: ServerPlatform;
/**
* The hostname of the server.
*/
hostname: string;
};