Merge branch 'rewrite' of https://github.com/Sendouc/sendou.ink into rewrite

This commit is contained in:
Kalle
2022-10-22 12:50:28 +03:00
14 changed files with 83 additions and 61 deletions

View File

@@ -1,7 +1,8 @@
import { Link, useLocation } from "@remix-run/react";
import { Link, useMatches } from "@remix-run/react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import type { RootLoaderData } from "~/root";
import { type SendouRouteHandle } from "~/utils/remix";
import { LOGO_PATH, navIconUrl } from "~/utils/urls";
import { Image } from "../Image";
import { ColorModeToggle } from "./ColorModeToggle";
@@ -12,6 +13,25 @@ import { Menu } from "./Menu";
import navItems from "./nav-items.json";
import { UserItem } from "./UserItem";
function useActiveNavItem() {
const matches = useMatches();
return React.useMemo(() => {
let activeItem: { name: string; url: string } | undefined = undefined;
for (const match of matches.reverse()) {
const handle = match.handle as SendouRouteHandle | undefined;
if (handle?.navItemName) {
activeItem = navItems.find(({ name }) => name === handle.navItemName);
break;
}
}
return activeItem;
}, [matches]);
}
export const Layout = React.memo(function Layout({
children,
patrons,
@@ -22,12 +42,8 @@ export const Layout = React.memo(function Layout({
isCatchBoundary?: boolean;
}) {
const { t } = useTranslation();
const location = useLocation();
const [menuOpen, setMenuOpen] = React.useState(false);
const currentPagesNavItem = navItems.find((navItem) =>
location.pathname.includes(navItem.name)
);
const activeNavItem = useActiveNavItem();
return (
<div className="layout__container">
@@ -51,15 +67,15 @@ export const Layout = React.memo(function Layout({
</div>
</header>
<Menu expanded={menuOpen} closeMenu={() => setMenuOpen(false)} />
{currentPagesNavItem && (
{activeNavItem && (
<div className="layout__page-title-header">
<Image
path={navIconUrl(currentPagesNavItem.name)}
path={navIconUrl(activeNavItem.name)}
width={28}
height={28}
alt=""
/>
{t(`pages.${currentPagesNavItem.name}` as any)}
{t(`pages.${activeNavItem.name}` as any)}
</div>
)}
{children}

View File

@@ -18,7 +18,11 @@ import { Main } from "~/components/Main";
import { requireUser } from "~/modules/auth";
import { getUser, isImpersonating } from "~/modules/auth/user.server";
import { canPerformAdminActions } from "~/permissions";
import { parseRequestFormData, validate } from "~/utils/remix";
import {
parseRequestFormData,
type SendouRouteHandle,
validate,
} from "~/utils/remix";
import { makeTitle } from "~/utils/strings";
import { impersonateUrl, SEED_URL, STOP_IMPERSONATING_URL } from "~/utils/urls";
import { db } from "~/db";
@@ -69,6 +73,10 @@ export const loader: LoaderFunction = async ({ request }) => {
});
};
export const handle: SendouRouteHandle = {
navItemName: "admin",
};
export default function AdminPage() {
return (
<Main className="stack lg">

View File

@@ -52,6 +52,7 @@ export const links: LinksFunction = () => {
export const handle: SendouRouteHandle = {
i18n: ["weapons", "analyzer"],
navItemName: "analyzer",
};
export default function BuildAnalyzerPage() {

View File

@@ -21,6 +21,7 @@ export interface BadgesLoaderData {
export const handle: SendouRouteHandle = {
i18n: "badges",
navItemName: "badges",
};
export const loader: LoaderFunction = () => {

View File

@@ -16,6 +16,7 @@ export const links: LinksFunction = () => {
export const handle: SendouRouteHandle = {
i18n: ["weapons", "builds"],
breadcrumb: ({ t }) => t("pages.builds"),
navItemName: "builds",
};
export default function BuildsLayoutPage() {

View File

@@ -48,6 +48,7 @@ export const meta: MetaFunction = (args) => {
export const handle: SendouRouteHandle = {
i18n: "calendar",
navItemName: "calendar",
};
const loaderSearchParamsSchema = z.object({

View File

@@ -66,6 +66,7 @@ export const meta: MetaFunction = (args) => {
export const handle: SendouRouteHandle = {
i18n: "game-misc",
navItemName: "maps",
};
export const loader = async ({ request }: LoaderArgs) => {

View File

@@ -3,11 +3,16 @@ import { Outlet } from "@remix-run/react";
import { Main } from "~/components/Main";
import { SubNav, SubNavLink } from "~/components/SubNav";
import styles from "~/styles/plus.css";
import { type SendouRouteHandle } from "~/utils/remix";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
};
export const handle: SendouRouteHandle = {
navItemName: "plus",
};
export default function PlusPageLayout() {
return (
<>

View File

@@ -1,6 +1,7 @@
import { z } from "zod";
import { type TFunction, type Namespace } from "react-i18next";
import { type RouteMatch } from "@remix-run/react";
import type navItems from "~/components/layout/nav-items.json";
export function notFoundIfFalsy<T>(value: T | null | undefined): T {
if (!value) throw new Response(null, { status: 404 });
@@ -102,6 +103,7 @@ export function validate(condition: any, status = 400): asserts condition {
export type SendouRouteHandle = {
/** The i18n translation files used for this route, via remix-i18next */
i18n?: Namespace;
/**
* A function that returns the breadcrumb text that should be displayed in
* the <Breadcrumb> component
@@ -110,4 +112,7 @@ export type SendouRouteHandle = {
match: RouteMatch;
t: TFunction<"common", undefined>;
}) => string | undefined;
/** The name of a navItem that is active on this route. See nav-items.json */
navItemName?: typeof navItems[number]["name"];
};

View File

@@ -1,6 +1,6 @@
{
"inYourTimeZone": " Alle Zeiten sind konvertiert zur lokalen Zeitzone:",
"addNew": "Turnier hinzufügen",
"inYourTimeZone": "Alle Zeiten sind konvertiert zur lokalen Zeitzone:",
"addNew": "Event hinzufügen",
"noEvents": "Keine Events in dieser Woche",
"reportResults": "Ergebnisse können eingetragen werden für:",
"day": "Tag {{number}}",
@@ -8,19 +8,21 @@
"participatedCount": "{{count}} teilnehmende Teams",
"members": "Mitglieder",
"results": "Resultate",
"createMapList": "Arenen-Liste erstellen",
"forms.dates": "Datum",
"forms.bracketUrl": "Turnierbaum URL",
"forms.discordInvite": "Discord server Einladung URL",
"forms.bracketUrl": "Turnierbaum-URL",
"forms.discordInvite": "Discord-Server Einladungs-URL",
"forms.tags": "Tags",
"forms.tags.placeholder": "Wähle einen Tag",
"forms.tags.info": "\"Abzeichen-Preis\" tag wird automatisch hinzugefügt (falls anwendbar)",
"forms.tags.info": "\"Abzeichen-Preis\"-Tag wird automatisch hinzugefügt (falls anwendbar)",
"forms.badges": "Abzeichen-Preis",
"forms.badges.placeholder": "Wähle ein Abzeichen für das Event",
"forms.mapPool": "Arenen-Pool",
"forms.participantCount": "Anzahl Teilnehmer",
"forms.reportResultsHeader": "Berichten der Ergebnisse von {{eventName}}",
"forms.reportResultsInfo": "Die Anzahl der eintragbaren Resultate ist frei wählbar. Es kann nur das erste Team sein, die Top 3 oder mehr.",
"forms.reportResultsInfo": "Die Anzahl der eintragbaren Ergebnisse ist frei wählbar. Es kann nur das erste Team sein, die Top 3 oder mehr.",
"forms.team.add": "Team hinzufügen",
"forms.team.remove": "Team löschen",
"forms.team.name": "Name des Teams",

View File

@@ -8,11 +8,17 @@
"pages.faq": "FAQ",
"pages.builds": "Ausrüstungen",
"pages.analyzer": "Ausrüstungs-Analyse",
"pages.maps": "Arenen-Listen",
"header.profile": "Profil",
"header.logout": "Ausloggen",
"header.login": "Einloggen",
"auth.errors.aborted": "Einloggen abgebrochen",
"auth.errors.failed": "Einloggen fehlgeschlagen",
"auth.errors.discordPermissions": "Für dein sendou.ink-Profil benötigt die Seite Zugriff auf den Namen, Avatar und verbundene Social-Media-Accounts in deinem Discord-Profil.",
"auth.errors.unknown": "Das Einloggen via Discord ist aus unbekannten Gründen fehlgeschlagen. Falls dies wiederholt auftritt, kontaktiere uns bitte.",
"footer.github.subtitle": "Sourcecode",
"footer.twitter.subtitle": "Updates",
"footer.discord.subtitle": "Hilfe & Feedback",
@@ -29,6 +35,11 @@
"actions.loadMore": "Mehr laden",
"actions.close": "Schließen",
"maps.createMapList": "Arenen-Liste erstellen",
"maps.halfSz": "50% Herrschaft",
"maps.mapPool": "Arenen-Pool",
"maps.tournamentMaplist": "Arenen-Liste für Turnier erstellen (maps.iplabs.ink)",
"results": "Ergebnisse",
"forms.name": "Name",
@@ -55,10 +66,5 @@
"weapon.category.DUALIES": "Doppler",
"weapon.category.BRELLAS": "Pluviatoren",
"weapon.category.STRINGERS": "Stringer",
"weapon.category.SPLATANAS": "Splatanas",
"auth.errors.aborted": "Login Abgebrochen",
"auth.errors.failed": "Login Fehlgeschlagen",
"auth.errors.discordPermissions": "Für dein sendou.ink Profil braucht die Seite die Erlaubnis deinen Discord-Namen, Avatar, und verbundene Social Accounts auszulesen.",
"auth.errors.unknown": "Der Login via Discord ist aus unbekannten Gründen fehlgeschlagen. Falls dies wiederholt auftritt, kontaktiere uns bitte."
"weapon.category.SPLATANAS": "Splatanas"
}

View File

@@ -6,6 +6,7 @@
"plus.description": "Sieh vergangene Plus Server Abstimmungen und mehr",
"badges.description": "Liste aller Abzeichen, die du für dein Profil verdienen kannst",
"analyzer.description": "Analysiere, was deine Ausrüstungen wirklich bewirken",
"maps.description": "Erstelle aus einem Arenen-Pool die Liste für dein Spiel",
"recentWinners": "Aktuelle Gewinner",
"upcomingEvents": "Bevorstehende Events",
"articleBy": "von {{author}}"

View File

@@ -10,5 +10,10 @@
"STAGE_8": "Perlmutt-Akademie",
"STAGE_9": "Störwerft",
"STAGE_10": "Cetacea-Markt",
"STAGE_11": "Flunder-Funpark"
"STAGE_11": "Flunder-Funpark",
"MODE_SHORT_TW": "RK",
"MODE_SHORT_SZ": "HS",
"MODE_SHORT_TC": "TK",
"MODE_SHORT_RM": "OG",
"MODE_SHORT_CB": "MC"
}

View File

@@ -80,31 +80,18 @@
**11/11**
### 🟡 calendar.json
### 🟢 calendar.json
**44/46**
<details>
<summary>Missing</summary>
- createMapList
- forms.mapPool
</details>
**46/46**
### 🟡 common.json
**54/60**
**59/60**
<details>
<summary>Missing</summary>
- pages.maps
- actions.copyToClipboard
- maps.createMapList
- maps.halfSz
- maps.mapPool
- maps.tournamentMaplist
</details>
@@ -116,31 +103,13 @@
**6/6**
### 🟡 front.json
### 🟢 front.json
**10/11**
**11/11**
<details>
<summary>Missing</summary>
### 🟢 game-misc.json
- maps.description
</details>
### 🟡 game-misc.json
**12/17**
<details>
<summary>Missing</summary>
- MODE_SHORT_TW
- MODE_SHORT_SZ
- MODE_SHORT_TC
- MODE_SHORT_RM
- MODE_SHORT_CB
</details>
**17/17**
### 🟢 user.json