From ee9abf70057bd830bb532ed747d79ae5034cac83 Mon Sep 17 00:00:00 2001 From: axel7083 <42176370+axel7083@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:03:08 +0200 Subject: [PATCH] feat(frontend): allow presets to be explored in dedicated page (#1232) * feat(backend): allowing auth users to create presents * fix: linter&preset behaviour * fix: remove unused import * feat: improve presets exploration * fix: remove platform presets list * fix: export name field * fix: platform icon * fix: PR comments * fix: tailwindcss classes --- frontend/src/app/(navfooter)/preset/page.tsx | 12 +++ .../src/app/(navfooter)/preset/presets.tsx | 36 +++++++++ .../PlatformSelect/PlatformIcon.tsx | 20 ++++- .../PlatformSelect/PlatformSelect.tsx | 2 +- frontend/src/components/PresetList.tsx | 73 +++++++++++++++++++ 5 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 frontend/src/app/(navfooter)/preset/page.tsx create mode 100644 frontend/src/app/(navfooter)/preset/presets.tsx create mode 100644 frontend/src/components/PresetList.tsx diff --git a/frontend/src/app/(navfooter)/preset/page.tsx b/frontend/src/app/(navfooter)/preset/page.tsx new file mode 100644 index 000000000..f6dab82e7 --- /dev/null +++ b/frontend/src/app/(navfooter)/preset/page.tsx @@ -0,0 +1,12 @@ +import { Presets } from "@/app/(navfooter)/preset/presets" +import { get } from "@/lib/api/request" + +export default async function Page() { + const compilers = await get("/compiler") + + return ( +
+ +
+ ) +} diff --git a/frontend/src/app/(navfooter)/preset/presets.tsx b/frontend/src/app/(navfooter)/preset/presets.tsx new file mode 100644 index 000000000..53bb7dec3 --- /dev/null +++ b/frontend/src/app/(navfooter)/preset/presets.tsx @@ -0,0 +1,36 @@ +"use client" + +import { useState } from "react" + +import PlatformSelect from "@/components/PlatformSelect" +import { PresetList } from "@/components/PresetList" +import * as api from "@/lib/api" + +export function Presets({ serverCompilers }: { + serverCompilers: { + platforms: { + [id: string]: api.Platform + } + compilers: { + [id: string]: api.Compiler + } + } +}) { + + const platforms = Object.keys(serverCompilers.platforms) + + const [platform, setPlatform] = useState(platforms.length > 0 ? platforms[0] : "") + + return ( +
+

Platforms

+ +

Presets

+ +
+ ) +} diff --git a/frontend/src/components/PlatformSelect/PlatformIcon.tsx b/frontend/src/components/PlatformSelect/PlatformIcon.tsx index e600d47f2..b25f18f1c 100644 --- a/frontend/src/components/PlatformSelect/PlatformIcon.tsx +++ b/frontend/src/components/PlatformSelect/PlatformIcon.tsx @@ -1,3 +1,7 @@ +import Link from "next/link" + +import { platformUrl } from "@/lib/api/urls" + import LogoDreamcast from "./dreamcast.svg" import LogoGBA from "./gba.svg" import LogoGCWii from "./gc_wii.svg" @@ -39,6 +43,7 @@ export const PLATFORMS = Object.keys(ICONS) export type Props = { platform: string className?: string + clickable?: boolean size?: string | number } @@ -46,8 +51,19 @@ export function platformIcon(platform: string) { return ICONS[platform as keyof typeof ICONS] || UnknownIcon } -export function PlatformIcon({ platform, className, size }: Props) { +export function PlatformIcon({ platform, className, clickable, size }: Props) { const Icon = platformIcon(platform) + const url = platformUrl(platform) - return + if (clickable) { + return ( + + + + ) + } else { + return ( + + ) + } } diff --git a/frontend/src/components/PlatformSelect/PlatformSelect.tsx b/frontend/src/components/PlatformSelect/PlatformSelect.tsx index 85be5f391..1babdf177 100644 --- a/frontend/src/components/PlatformSelect/PlatformSelect.tsx +++ b/frontend/src/components/PlatformSelect/PlatformSelect.tsx @@ -25,7 +25,7 @@ export default function PlatformSelect({ platforms, value, onChange, className } className={classNames(styles.platform, { [styles.selected]: value === key })} onClick={() => onChange(key)} > - +
{platform.name}
{platform.description}
diff --git a/frontend/src/components/PresetList.tsx b/frontend/src/components/PresetList.tsx new file mode 100644 index 000000000..656c4f632 --- /dev/null +++ b/frontend/src/components/PresetList.tsx @@ -0,0 +1,73 @@ +"use client" + +import type { ReactNode, JSX } from "react" + +import Link from "next/link" + +import classNames from "classnames" + +import AsyncButton from "@/components/AsyncButton" +import Button from "@/components/Button" +import LoadingSpinner from "@/components/loading.svg" +import { PlatformIcon } from "@/components/PlatformSelect/PlatformIcon" +import { type Preset, usePaginated } from "@/lib/api" +import { presetUrl } from "@/lib/api/urls" +import useTranslation from "@/lib/i18n/translate" + +export interface Props { + url?: string + className?: string + item?: ({ preset }: { preset: Preset }) => JSX.Element + emptyButtonLabel?: ReactNode +} + +export function PresetList({ url, className, item, emptyButtonLabel }: Props): JSX.Element { + const { results, isLoading, hasNext, loadNext } = usePaginated(url || "/preset") + if (results.length === 0 && isLoading) { + return
+ + Just a moment... +
+ } + + const Item = item ?? PresetItem + + return ( +
    + {results.map(preset => ( + + ))} + {results.length === 0 && emptyButtonLabel &&
  • + + + + + +
  • } + {hasNext &&
  • + + Show more + +
  • } +
+ ) +} + +export function PresetItem({ preset, hideIcon }: { preset: Preset, hideIcon?: boolean }): JSX.Element { + const compilersTranslation = useTranslation("compilers") + const compilerName = compilersTranslation.t(preset.compiler) + + return ( +
+
+ {hideIcon && } + + {preset.name} + +
+

{compilerName}

+
+ ) +}