add motd to the server page
All checks were successful
Deploy App / docker (ubuntu-latest) (push) Successful in 56s
All checks were successful
Deploy App / docker (ubuntu-latest) (push) Successful in 56s
This commit is contained in:
parent
8ffd865c63
commit
f00d6d8ba4
@ -34,7 +34,7 @@ export default function RootLayout({
|
|||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<html className={Fonts.inter.className} lang="en" suppressHydrationWarning>
|
<html className={Fonts.inter.className} lang="en" suppressHydrationWarning>
|
||||||
|
@ -10,7 +10,7 @@ const buttons: Button[] = [
|
|||||||
{ title: "Documentation", url: "https://api.mcutils.xyz/swagger-ui.html" },
|
{ title: "Documentation", url: "https://api.mcutils.xyz/swagger-ui.html" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="text-center flex flex-col justify-center">
|
<div className="text-center flex flex-col justify-center">
|
||||||
<h1 className="text-4xl mb-2">Minecraft Utilities</h1>
|
<h1 className="text-4xl mb-2">Minecraft Utilities</h1>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import { Card } from "@/app/components/card";
|
||||||
import { NotFound } from "@/app/components/not-found";
|
import { NotFound } from "@/app/components/not-found";
|
||||||
import { LookupPlayer } from "@/app/components/player/lookup-player";
|
import { LookupPlayer } from "@/app/components/player/lookup-player";
|
||||||
import { Card } from "@/app/components/ui/card";
|
|
||||||
import { generateEmbed } from "@/common/embed";
|
import { generateEmbed } from "@/common/embed";
|
||||||
import { getPlayer } from "mcutils-library";
|
import { getPlayer } from "mcutils-library";
|
||||||
import { Player } from "mcutils-library/dist/types/player/player";
|
import { Player } from "mcutils-library/dist/types/player/player";
|
||||||
@ -42,7 +42,7 @@ async function getData(id: string): Promise<Player | null> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function Page({ params }: Params) {
|
export default async function Page({ params }: Params): Promise<JSX.Element> {
|
||||||
const player = await getData(params.id);
|
const player = await getData(params.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -57,7 +57,7 @@ export default async function Page({ params }: Params) {
|
|||||||
<Card>
|
<Card>
|
||||||
{player == null && <NotFound message="Invalid UUID / Username" />}
|
{player == null && <NotFound message="Invalid UUID / Username" />}
|
||||||
{player != null && (
|
{player != null && (
|
||||||
<div className="flex gap-2 flex-col md:flex-row">
|
<div className="flex gap-4 flex-col md:flex-row">
|
||||||
<div className="flex justify-center md:justify-start">
|
<div className="flex justify-center md:justify-start">
|
||||||
<Image
|
<Image
|
||||||
className="w-[96px] h-[96px]"
|
className="w-[96px] h-[96px]"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import { Card } from "@/app/components/card";
|
||||||
import { NotFound } from "@/app/components/not-found";
|
import { NotFound } from "@/app/components/not-found";
|
||||||
import { LookupServer } from "@/app/components/server/lookup-server";
|
import { LookupServer } from "@/app/components/server/lookup-server";
|
||||||
import { Card } from "@/app/components/ui/card";
|
|
||||||
import { generateEmbed } from "@/common/embed";
|
import { generateEmbed } from "@/common/embed";
|
||||||
import { capitalizeFirstLetter } from "@/common/string-utils";
|
import { capitalizeFirstLetter } from "@/common/string-utils";
|
||||||
import { getServer } from "mcutils-library";
|
import { getServer } from "mcutils-library";
|
||||||
@ -54,7 +54,7 @@ async function getData(platform: ServerPlatform, id: string): Promise<MinecraftS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function Page({ params: { platform, hostname } }: Params) {
|
export default async function Page({ params: { platform, hostname } }: Params): Promise<JSX.Element> {
|
||||||
const server = await getData(platform, hostname);
|
const server = await getData(platform, hostname);
|
||||||
|
|
||||||
let favicon = null; // Server favicon
|
let favicon = null; // Server favicon
|
||||||
@ -77,28 +77,36 @@ export default async function Page({ params: { platform, hostname } }: Params) {
|
|||||||
<Card>
|
<Card>
|
||||||
{server == null && <NotFound message="Server not responding" />}
|
{server == null && <NotFound message="Server not responding" />}
|
||||||
{server != null && (
|
{server != null && (
|
||||||
<div className="flex gap-2 flex-col md:flex-row">
|
<div className="flex gap-4 flex-col">
|
||||||
{favicon && (
|
<div className="flex gap-4 flex-col md:flex-row">
|
||||||
<div className="flex justify-center md:justify-start">
|
{favicon && (
|
||||||
<Image
|
<div className="flex justify-center md:justify-start">
|
||||||
className="w-[96px] h-[96px]"
|
<Image
|
||||||
src={favicon}
|
className="w-[64px] h-[64px]"
|
||||||
width={96}
|
src={favicon}
|
||||||
height={96}
|
width={64}
|
||||||
quality={100}
|
height={64}
|
||||||
alt="The server's favicon"
|
quality={100}
|
||||||
/>
|
alt="The server's favicon"
|
||||||
</div>
|
/>
|
||||||
)}
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h2 className="text-xl">{server.hostname}</h2>
|
<h2 className="text-xl">{server.hostname}</h2>
|
||||||
<div className="text-gray-300">
|
<div className="text-gray-300">
|
||||||
<p>
|
<p>
|
||||||
Players online: {server.players.online}/{server.players.max}
|
Players online: {server.players.online}/{server.players.max}
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-background rounded-lg p-2">
|
||||||
|
{server.motd.html.map((line, index) => {
|
||||||
|
return <p key={index} dangerouslySetInnerHTML={{ __html: line }}></p>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -2,6 +2,6 @@ export function Card({
|
|||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>): JSX.Element {
|
||||||
return <div className="bg-secondary rounded-lg p-4">{children}</div>;
|
return <div className="bg-secondary rounded-lg p-4">{children}</div>;
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ export default function Container({
|
|||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="z-[9999] m-auto flex h-screen min-h-full flex-col items-center opacity-90 md:max-w-[1200px]">
|
<div className="z-[9999] m-auto flex h-screen min-h-full flex-col items-center opacity-90 md:max-w-[1200px]">
|
||||||
<NavBar />
|
<NavBar />
|
||||||
|
11
src/app/components/icon/icon-props.ts
Normal file
11
src/app/components/icon/icon-props.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export type IconProps = {
|
||||||
|
/**
|
||||||
|
* The size of the icon
|
||||||
|
*/
|
||||||
|
size?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color of the icon
|
||||||
|
*/
|
||||||
|
color?: string;
|
||||||
|
};
|
9
src/app/components/icon/moon-icon.tsx
Normal file
9
src/app/components/icon/moon-icon.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { IconProps } from "./icon-props";
|
||||||
|
|
||||||
|
export function MoonIcon({ size = 24, color = "#fff" }: IconProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} fill={color} viewBox="0 -960 960 960">
|
||||||
|
<path d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
9
src/app/components/icon/sun-icon.tsx
Normal file
9
src/app/components/icon/sun-icon.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { IconProps } from "./icon-props";
|
||||||
|
|
||||||
|
export function SunIcon({ size = 24, color = "#fff" }: IconProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} fill={color} viewBox="0 -960 960 960">
|
||||||
|
<path d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
||||||
export default function Logo({ size = 30 }: Readonly<{ size?: number }>) {
|
export default function Logo({ size = 30 }: Readonly<{ size?: number }>): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
src="https://git.fascinated.cc/MinecraftUtilities/Assets/raw/branch/master/logo.png"
|
src="https://git.fascinated.cc/MinecraftUtilities/Assets/raw/branch/master/logo.png"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Logo from "./logo";
|
import Logo from "./logo";
|
||||||
import { RedirectButton } from "./rediect-button";
|
import { RedirectButton } from "./rediect-button";
|
||||||
|
import { ToggleThemeButton } from "./theme-toggle-button";
|
||||||
|
|
||||||
type Page = {
|
type Page = {
|
||||||
title: string;
|
title: string;
|
||||||
@ -12,7 +13,7 @@ const pages: Page[] = [
|
|||||||
{ title: "Server", url: "/server/java/hypixel.net" },
|
{ title: "Server", url: "/server/java/hypixel.net" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function NavBar() {
|
export default function NavBar(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="bg-secondary w-full rounded-lg flex items-center gap-3 mt-2 bg-opacity-85 h-12">
|
<div className="bg-secondary w-full rounded-lg flex items-center gap-3 mt-2 bg-opacity-85 h-12">
|
||||||
<div className="flex items-center gap-2 pl-3 pr-3">
|
<div className="flex items-center gap-2 pl-3 pr-3">
|
||||||
@ -27,8 +28,13 @@ export default function NavBar() {
|
|||||||
|
|
||||||
<div className="flex-grow"></div>
|
<div className="flex-grow"></div>
|
||||||
|
|
||||||
<div className="mr-4">
|
<div className="mr-4 flex items-center gap-2">
|
||||||
<RedirectButton title="Star us on Github!" url="https://github.com/RealFascinated/minecraft-helper" />
|
<RedirectButton
|
||||||
|
title="Star us on Github!"
|
||||||
|
url="https://github.com/RealFascinated/minecraft-helper"
|
||||||
|
openInNewTab
|
||||||
|
/>
|
||||||
|
<ToggleThemeButton />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ type NotFoundProps = {
|
|||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function NotFound({ message }: NotFoundProps) {
|
export function NotFound({ message }: NotFoundProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col justify-center text-center">
|
<div className="flex flex-col justify-center text-center">
|
||||||
<h1 className="text-xl text-red-400">Not Found</h1>
|
<h1 className="text-xl text-red-400">Not Found</h1>
|
||||||
|
@ -5,7 +5,7 @@ import { useState } from "react";
|
|||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
|
|
||||||
export function LookupPlayer() {
|
export function LookupPlayer(): JSX.Element {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [player, setPlayer] = useState("");
|
const [player, setPlayer] = useState("");
|
||||||
|
|
||||||
|
@ -3,12 +3,13 @@ import Link from "next/link";
|
|||||||
type ButtonProps = {
|
type ButtonProps = {
|
||||||
title: string;
|
title: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
openInNewTab?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function RedirectButton({ title, url }: ButtonProps) {
|
export function RedirectButton({ title, url, openInNewTab }: ButtonProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="w-fit rounded-lg">
|
<div className="w-fit rounded-lg">
|
||||||
<Link href={url} target="_blank">
|
<Link href={url} target={openInNewTab ? "_blank" : ""}>
|
||||||
<p className="hover:text-primary transition-all">{title}</p>
|
<p className="hover:text-primary transition-all">{title}</p>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,7 +6,7 @@ import { useState } from "react";
|
|||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
|
|
||||||
export function LookupServer() {
|
export function LookupServer(): JSX.Element {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [hostname, setHostname] = useState("");
|
const [hostname, setHostname] = useState("");
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
||||||
import { type ThemeProviderProps } from "next-themes/dist/types";
|
import { type ThemeProviderProps } from "next-themes/dist/types";
|
||||||
|
|
||||||
export default function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
export default function ThemeProvider({ children, ...props }: ThemeProviderProps): JSX.Element {
|
||||||
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
|
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
|
||||||
}
|
}
|
||||||
|
15
src/app/components/theme-toggle-button.tsx
Normal file
15
src/app/components/theme-toggle-button.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
import { MoonIcon } from "./icon/moon-icon";
|
||||||
|
import { SunIcon } from "./icon/sun-icon";
|
||||||
|
|
||||||
|
export function ToggleThemeButton(): JSX.Element {
|
||||||
|
const { theme, setTheme } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button className="p-2 rounded-lg" onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
|
||||||
|
{theme === "dark" ? <SunIcon /> : <MoonIcon color="#000" />}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user