mirror of
https://github.com/chenasraf/stimvisor.git
synced 2026-05-17 17:38:11 +00:00
feat: update games page ui
This commit is contained in:
59
frontend/src/components/ui/alert.tsx
Normal file
59
frontend/src/components/ui/alert.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const alertVariants = cva(
|
||||
"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-background text-foreground",
|
||||
destructive:
|
||||
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const Alert = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
|
||||
>(({ className, variant, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
role="alert"
|
||||
className={cn(alertVariants({ variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Alert.displayName = "Alert"
|
||||
|
||||
const AlertTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLHeadingElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<h5
|
||||
ref={ref}
|
||||
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertTitle.displayName = "AlertTitle"
|
||||
|
||||
const AlertDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("text-sm [&_p]:leading-relaxed", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AlertDescription.displayName = "AlertDescription"
|
||||
|
||||
export { Alert, AlertTitle, AlertDescription }
|
||||
@@ -1,8 +1,11 @@
|
||||
import { GetGames } from '$app'
|
||||
import { useApi } from '@/common/api'
|
||||
import { useAppContext } from '@/common/app_context'
|
||||
import { cn } from '@/common/utils'
|
||||
import { LoadingContainer } from '@/components/Loader/LoadingContainer'
|
||||
import { FaFileCircleExclamation } from 'react-icons/fa6'
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
|
||||
import { HtmlProps } from '@/common/types'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { FaGamepad } from 'react-icons/fa6'
|
||||
|
||||
function useGames() {
|
||||
return useApi(GetGames, ['games'], {
|
||||
@@ -12,29 +15,54 @@ function useGames() {
|
||||
}
|
||||
|
||||
export function GamesPage() {
|
||||
const { meta } = useAppContext()
|
||||
const { data, isFetching } = useGames()
|
||||
console.debug('GamesPage', meta)
|
||||
return (
|
||||
<div className={cn('p-4')}>
|
||||
<h1 className="text-2xl">Games</h1>
|
||||
|
||||
<div>
|
||||
<LoadingContainer loading={isFetching}>
|
||||
{data.games?.map((dir) => (
|
||||
<div key={dir.id}>
|
||||
<h2>{dir.name}</h2>
|
||||
</div>
|
||||
))}
|
||||
</LoadingContainer>
|
||||
<div>
|
||||
<div className="p-4 pb-3">
|
||||
<h1 className="text-2xl">Games</h1>
|
||||
</div>
|
||||
|
||||
<details>
|
||||
<summary>Meta</summary>
|
||||
<code>
|
||||
<pre>{JSON.stringify(meta, null, 2)}</pre>
|
||||
</code>
|
||||
</details>
|
||||
<div className="p-4 pt-0 flex flex-col gap-4">
|
||||
<Alert>
|
||||
<FaFileCircleExclamation />
|
||||
<AlertTitle>Only Showing Some Games</AlertTitle>
|
||||
<AlertDescription>
|
||||
This list only shows games that have been downloaded on this machine before, and not all
|
||||
of them might contain data.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<div>
|
||||
<LoadingContainer loading={isFetching}>
|
||||
{data.games?.map((dir) => (
|
||||
<ListItem key={dir.id} label={dir.name} to={`/games/${dir.id}`} />
|
||||
))}
|
||||
</LoadingContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function ListItem({
|
||||
children,
|
||||
label,
|
||||
to,
|
||||
...rest
|
||||
}: HtmlProps<'div'> & {
|
||||
label: React.ReactNode
|
||||
to: string
|
||||
}) {
|
||||
return (
|
||||
<Link to={to}>
|
||||
<div
|
||||
className="min-h-10 flex gap-4 items-center justify-start py-3 px-6 cursor-pointer transition-colors hover:bg-bg-800"
|
||||
{...rest}
|
||||
>
|
||||
<FaGamepad />
|
||||
{label}
|
||||
</div>
|
||||
{children ? <ul>{children}</ul> : null}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { FaAngleLeft } from 'react-icons/fa6'
|
||||
import { ScreenshotImg } from '@/components/ScreenshotImg/ScreenshotImg'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { ScreenshotsCarouselModal } from '@/components/ScreenshotsCarouselModal/ScreenshotsCarouselModal'
|
||||
import { screenshots } from '$models'
|
||||
import { Dialog } from '@/components/ui/dialog'
|
||||
|
||||
function useScreenshotsDir(gameId: string) {
|
||||
@@ -40,6 +39,7 @@ function ScreenshotsGamePage() {
|
||||
const closeScreenshotsModal = useCallback(() => {
|
||||
setModalIndex(null)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="sticky top-0 p-4 bg-background flex flex-col gap-2 z-10">
|
||||
@@ -52,7 +52,7 @@ function ScreenshotsGamePage() {
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 justify-between">
|
||||
<h1 className="text-2xl p-4 bg-background">
|
||||
<h1 className="text-2xl py-4 bg-background">
|
||||
Screenshots for <span className="text-black dark:text-white">{dir.gameName}</span>
|
||||
</h1>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
@@ -45,6 +45,7 @@ function ScreenshotsHome() {
|
||||
setModalIndex(null)
|
||||
setModalScreenshots([])
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<h1 className="sticky top-0 p-4 bg-background text-2xl z-10">Screenshots</h1>
|
||||
|
||||
Reference in New Issue
Block a user