mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-16 16:20:04 +00:00
Game details now link to search with filter
This commit is contained in:
@@ -73,7 +73,7 @@ export default function PluginDetailsModal({plugin, isOpen, onOpenChange}: Plugi
|
|||||||
if (!value) return;
|
if (!value) return;
|
||||||
return (
|
return (
|
||||||
<tr key={key}>
|
<tr key={key}>
|
||||||
<td className="text-foreground/60 w-0 min-w-20">{key}</td>
|
<td className="text-default-500 w-0 min-w-20">{key}</td>
|
||||||
<td className="flex flex-row gap-1">{value}</td>
|
<td className="flex flex-row gap-1">{value}</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
@@ -81,7 +81,7 @@ export default function PluginDetailsModal({plugin, isOpen, onOpenChange}: Plugi
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-foreground/60">Description</p>
|
<p className="text-default-500">Description</p>
|
||||||
<Markdown
|
<Markdown
|
||||||
remarkPlugins={[remarkBreaks]}
|
remarkPlugins={[remarkBreaks]}
|
||||||
components={{
|
components={{
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ import {useNavigate, useParams} from "react-router";
|
|||||||
import {GameCover} from "Frontend/components/general/covers/GameCover";
|
import {GameCover} from "Frontend/components/general/covers/GameCover";
|
||||||
import ComboButton, {ComboButtonOption} from "Frontend/components/general/input/ComboButton";
|
import ComboButton, {ComboButtonOption} from "Frontend/components/general/input/ComboButton";
|
||||||
import ImageCarousel from "Frontend/components/general/covers/ImageCarousel";
|
import ImageCarousel from "Frontend/components/general/covers/ImageCarousel";
|
||||||
import {Chip} from "@heroui/react";
|
import {Chip, Link, Tooltip} from "@heroui/react";
|
||||||
import {humanFileSize, toTitleCase} from "Frontend/util/utils";
|
import {humanFileSize, toTitleCase} from "Frontend/util/utils";
|
||||||
import {DownloadEndpoint} from "Frontend/endpoints/endpoints";
|
import {DownloadEndpoint} from "Frontend/endpoints/endpoints";
|
||||||
import {gameState, initializeGameState} from "Frontend/state/GameState";
|
import {gameState, initializeGameState} from "Frontend/state/GameState";
|
||||||
import {useSnapshot} from "valtio/react";
|
import {useSnapshot} from "valtio/react";
|
||||||
import GameDto from "Frontend/generated/de/grimsi/gameyfin/games/dto/GameDto";
|
import GameDto from "Frontend/generated/de/grimsi/gameyfin/games/dto/GameDto";
|
||||||
|
import {TriangleDashed} from "@phosphor-icons/react";
|
||||||
|
|
||||||
export default function GameView() {
|
export default function GameView() {
|
||||||
const {gameId} = useParams();
|
const {gameId} = useParams();
|
||||||
@@ -63,7 +64,8 @@ export default function GameView() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<p className="font-semibold text-3xl">{game.title}</p>
|
<p className="font-semibold text-3xl">{game.title}</p>
|
||||||
<p className="text-foreground/60">{game.release !== undefined ? new Date(game.release).getFullYear() : "unknown"}</p>
|
<p className="text-default-500">{game.release !== undefined ? new Date(game.release).getFullYear() :
|
||||||
|
<p className="text-default-500">no data</p>}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{downloadOptions && <ComboButton description={humanFileSize(game.metadata.fileSize)}
|
{downloadOptions && <ComboButton description={humanFileSize(game.metadata.fileSize)}
|
||||||
@@ -74,37 +76,95 @@ export default function GameView() {
|
|||||||
<div className="flex flex-col gap-8">
|
<div className="flex flex-col gap-8">
|
||||||
<div className="flex flex-row gap-12">
|
<div className="flex flex-row gap-12">
|
||||||
<div className="flex flex-col flex-1 gap-2">
|
<div className="flex flex-col flex-1 gap-2">
|
||||||
<p className="text-foreground/60">Summary</p>
|
<p className="text-default-500">Summary</p>
|
||||||
{game.summary ?
|
{game.summary ?
|
||||||
<div className="text-justify" dangerouslySetInnerHTML={{__html: game.summary}}/> :
|
<div className="text-justify" dangerouslySetInnerHTML={{__html: game.summary}}/> :
|
||||||
<p>No summary available</p>
|
<p>No summary available</p>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col flex-1 gap-2">
|
<div className="flex flex-col flex-1 gap-2">
|
||||||
<p className="text-foreground/60">Details</p>
|
<p className="text-default-500">Details</p>
|
||||||
<table className="text-left w-full table-auto">
|
<table className="text-left w-full table-auto">
|
||||||
<tbody>
|
<tbody>
|
||||||
{Object.entries({
|
<tr className="h-6">
|
||||||
"Developed by": game.developers ? [...game.developers].sort().join(" / ") : "unknown",
|
<td className="text-default-500 w-0 min-w-32">Developed by</td>
|
||||||
"Published by": game.publishers ? [...game.publishers].sort().join(" / ") : "unknown",
|
<td className="flex flex-row gap-1">
|
||||||
"Genres": game.genres ? [...game.genres].sort().map(p =>
|
{game.developers && game.developers.length > 0
|
||||||
<Chip radius="sm" key={p}>{toTitleCase(p)}</Chip>) : undefined,
|
? [...game.developers].sort().map(dev =>
|
||||||
"Themes": game.themes ? [...game.themes].sort().map(p =>
|
<Link key={dev} href={`/search?dev=${encodeURIComponent(dev)}`}
|
||||||
<Chip radius="sm" key={p}>{toTitleCase(p)}</Chip>) : undefined,
|
color="foreground" underline="hover">
|
||||||
"Features": game.features ? [...game.features].sort().map(p =>
|
{dev}
|
||||||
<Chip radius="sm" key={p}>{toTitleCase(p)}</Chip>) : undefined,
|
</Link>
|
||||||
}).map(([key, value]) => (
|
)
|
||||||
<tr key={key}>
|
: <Tooltip content="Missing data" color="foreground" placement="right">
|
||||||
<td className="text-foreground/60 w-0 min-w-32">{key}</td>
|
<TriangleDashed className="fill-default-500 h-6 bottom-0"/>
|
||||||
<td className="flex flex-row gap-1">{value}</td>
|
</Tooltip>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-6">
|
||||||
|
<td className="text-default-500 w-0 min-w-32">Published by</td>
|
||||||
|
<td className="flex flex-row gap-1">
|
||||||
|
{game.publishers && game.publishers.length > 0
|
||||||
|
? [...game.publishers].sort().join(" / ")
|
||||||
|
: <Tooltip content="Missing data" color="foreground" placement="right">
|
||||||
|
<TriangleDashed className="fill-default-500 h-6 bottom-0"/>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-6">
|
||||||
|
<td className="text-default-500 w-0 min-w-32">Genres</td>
|
||||||
|
<td className="flex flex-row gap-1">
|
||||||
|
{game.genres && game.genres.length > 0
|
||||||
|
? [...game.genres].sort().map(genre =>
|
||||||
|
<Link key={genre} href={`/search?genre=${encodeURIComponent(genre)}`}>
|
||||||
|
<Chip radius="sm">{toTitleCase(genre)}</Chip>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
: <Tooltip content="Missing data" color="foreground" placement="right">
|
||||||
|
<TriangleDashed className="fill-default-500 h-6 bottom-0"/>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-6">
|
||||||
|
<td className="text-default-500 w-0 min-w-32">Themes</td>
|
||||||
|
<td className="flex flex-row gap-1">
|
||||||
|
{game.themes && game.themes.length > 0
|
||||||
|
? [...game.themes].sort().map(theme =>
|
||||||
|
<Link key={theme} href={`/search?theme=${encodeURIComponent(theme)}`}>
|
||||||
|
<Chip radius="sm">{toTitleCase(theme)}</Chip>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
: <Tooltip content="Missing data" color="foreground" placement="right">
|
||||||
|
<TriangleDashed className="fill-default-500 h-6 bottom-0"/>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-6">
|
||||||
|
<td className="text-default-500 w-0 min-w-32">Features</td>
|
||||||
|
<td className="flex flex-row gap-1">
|
||||||
|
{game.features && game.features.length > 0
|
||||||
|
? [...game.features].sort().map(feature =>
|
||||||
|
<Link key={feature}
|
||||||
|
href={`/search?feature=${encodeURIComponent(feature)}`}>
|
||||||
|
<Chip radius="sm">{toTitleCase(feature)}</Chip>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
: <Tooltip content="Missing data" color="foreground" placement="right">
|
||||||
|
<TriangleDashed className="fill-default-500 h-6 bottom-0"/>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<p className="text-foreground/60">Media</p>
|
<p className="text-default-500">Media</p>
|
||||||
<ImageCarousel
|
<ImageCarousel
|
||||||
imageUrls={game.imageIds?.map(id => `/images/screenshot/${id}`)}
|
imageUrls={game.imageIds?.map(id => `/images/screenshot/${id}`)}
|
||||||
videosUrls={game.videoUrls}
|
videosUrls={game.videoUrls}
|
||||||
|
|||||||
Reference in New Issue
Block a user