Files
MineGeo/components/CatalogBrowser.tsx
pavel444-byte 0330c4072f
All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 8m58s
Improve responsive layouts and streamline page loading
2026-10-21 11:15:07 +05:00

84 lines
2.4 KiB
TypeScript

"use client";
import { useI18n } from "@/components/I18nProvider";
import { useState } from "react";
import { Search } from "lucide-react";
import { MapCard, type CardMap } from "./MapCard";
import { ImportMap } from "./MapTransfer";
export function CatalogBrowser({
maps,
signedIn = false,
}: {
maps: CardMap[];
signedIn?: boolean;
}) {
const { t } = useI18n();
const [query, setQuery] = useState(""),
[source, setSource] = useState("all");
const shown = maps.filter(
(m) =>
(source === "all" || m.source === source) &&
(m.name + " " + m.description + " " + (m.server?.name ?? ""))
.toLowerCase()
.includes(query.trim().toLowerCase()),
);
return (
<>
<div className="catalog-controls">
<div className="catalog-search">
<label className="search-field">
<Search size={17} />
<input
aria-label={t("Search worlds")}
placeholder={t("Search worlds or servers…")}
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
</label>
<ImportMap signedIn={signedIn} />
</div>
<div className="tabs" aria-label={t("Capture source")}>
{[
["all", t("All worlds")],
["plugin", t("Server exports")],
["fabric", t("Player captures")],
].map(([id, label]) => (
<button
key={id}
className={source === id ? "active" : ""}
aria-pressed={source === id}
onClick={() => setSource(id)}
>
{t(label)}
</button>
))}
</div>
</div>
<p className="muted catalog-count" role="status">
{t("Worlds to explore: {count}", { count: shown.length })}
</p>
<div className="cards-grid">
{shown.map((m, i) => (
<MapCard map={m} index={i} key={m.id} />
))}
</div>
{!shown.length && (
<div className="empty-state catalog-empty">
<Search size={28} aria-hidden="true" />
<p>{t("No worlds match that search.")}</p>
<button
type="button"
className="button secondary"
onClick={() => {
setQuery("");
setSource("all");
}}
>
{t("Clear filters")}
</button>
</div>
)}
</>
);
}