54 lines
1.6 KiB
TypeScript
54 lines
1.6 KiB
TypeScript
import Image from "next/image";
|
||
import Link from "next/link";
|
||
import { ArrowUpRight, MapPin } from "lucide-react";
|
||
export type CardMap = {
|
||
id: string;
|
||
name: string;
|
||
description: string;
|
||
source: string;
|
||
panorama_count: number;
|
||
image?: string | null;
|
||
credit?: string;
|
||
server?: { name: string } | undefined;
|
||
bounds: { minX: number; minZ: number; maxX: number; maxZ: number };
|
||
};
|
||
export function MapCard({ map, index = 0 }: { map: CardMap; index?: number }) {
|
||
return (
|
||
<Link className="map-card" href={`/servers/${map.id}`}>
|
||
<div className="card-image">
|
||
<Image
|
||
src={map.image || "/images/example-map.webp"}
|
||
alt={`${map.name} terrain`}
|
||
fill
|
||
loading={index < 3 ? "eager" : "lazy"}
|
||
unoptimized
|
||
sizes="(max-width: 640px) 100vw, 33vw"
|
||
/>
|
||
<span className="card-type">
|
||
{map.source === "plugin" ? "SERVER EXPORT" : "PLAYER CAPTURE"}
|
||
</span>
|
||
<span className="card-number">0{index + 1}</span>
|
||
</div>
|
||
<div className="card-body">
|
||
<span className="eyebrow">{map.server?.name || "Overworld"}</span>
|
||
<h3>
|
||
{map.name}
|
||
<ArrowUpRight size={20} />
|
||
</h3>
|
||
<p>{map.description}</p>
|
||
{map.credit && <p className="map-credit">By {map.credit}</p>}
|
||
<div className="card-meta">
|
||
<span>
|
||
<MapPin size={13} />
|
||
{map.panorama_count} locations
|
||
</span>
|
||
<span>
|
||
{map.bounds.maxX - map.bounds.minX} ×{" "}
|
||
{map.bounds.maxZ - map.bounds.minZ} blocks
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</Link>
|
||
);
|
||
}
|