134 lines
4.7 KiB
TypeScript
134 lines
4.7 KiB
TypeScript
import ModCard from "./ModCard";
|
||
import { Skeleton } from "@/components/ui/skeleton";
|
||
import { Button } from "@/components/ui/button";
|
||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||
import { LayoutGrid, List, Monitor, Smartphone } from "lucide-react";
|
||
import { useState } from "react";
|
||
|
||
interface Mod {
|
||
id: string;
|
||
slug: string;
|
||
title: string;
|
||
description: string;
|
||
icon_url?: string;
|
||
downloads: number;
|
||
followers: number;
|
||
categories: string[];
|
||
project_type: string;
|
||
source?: "modrinth" | "curseforge";
|
||
}
|
||
|
||
interface ModGridProps {
|
||
mods: Mod[];
|
||
isLoading?: boolean;
|
||
title?: string;
|
||
showViewToggle?: boolean;
|
||
showPlatformFilter?: boolean;
|
||
onPlatformChange?: (platform: string) => void;
|
||
selectedPlatform?: string;
|
||
}
|
||
|
||
const ModGrid = ({
|
||
mods,
|
||
isLoading,
|
||
title,
|
||
showViewToggle = true,
|
||
showPlatformFilter = false,
|
||
onPlatformChange,
|
||
selectedPlatform = "all",
|
||
}: ModGridProps) => {
|
||
const [viewMode, setViewMode] = useState<"grid" | "list">("grid");
|
||
|
||
return (
|
||
<section className="py-6 sm:py-8">
|
||
<div className="mb-4 flex flex-col gap-3 sm:mb-6 sm:flex-row sm:items-center sm:justify-between">
|
||
{title && (
|
||
<h2 className="text-xl font-bold sm:text-2xl">{title}</h2>
|
||
)}
|
||
<div className="flex flex-wrap items-center gap-2">
|
||
{showPlatformFilter && (
|
||
<ToggleGroup
|
||
type="single"
|
||
value={selectedPlatform}
|
||
onValueChange={(val) => val && onPlatformChange?.(val)}
|
||
className="rounded-lg border border-border bg-secondary/50 p-0.5"
|
||
>
|
||
<ToggleGroupItem value="all" className="h-8 px-3 text-xs data-[state=on]:bg-primary data-[state=on]:text-primary-foreground">
|
||
الكل
|
||
</ToggleGroupItem>
|
||
<ToggleGroupItem value="java" className="h-8 px-3 text-xs data-[state=on]:bg-primary data-[state=on]:text-primary-foreground">
|
||
<Monitor className="ml-1 h-3 w-3" />
|
||
جافا
|
||
</ToggleGroupItem>
|
||
<ToggleGroupItem value="bedrock" className="h-8 px-3 text-xs data-[state=on]:bg-primary data-[state=on]:text-primary-foreground">
|
||
<Smartphone className="ml-1 h-3 w-3" />
|
||
بيدروك
|
||
</ToggleGroupItem>
|
||
</ToggleGroup>
|
||
)}
|
||
{showViewToggle && (
|
||
<ToggleGroup
|
||
type="single"
|
||
value={viewMode}
|
||
onValueChange={(val) => val && setViewMode(val as "grid" | "list")}
|
||
className="rounded-lg border border-border bg-secondary/50 p-0.5"
|
||
>
|
||
<ToggleGroupItem value="grid" className="h-8 w-8 p-0 data-[state=on]:bg-primary data-[state=on]:text-primary-foreground">
|
||
<LayoutGrid className="h-4 w-4" />
|
||
</ToggleGroupItem>
|
||
<ToggleGroupItem value="list" className="h-8 w-8 p-0 data-[state=on]:bg-primary data-[state=on]:text-primary-foreground">
|
||
<List className="h-4 w-4" />
|
||
</ToggleGroupItem>
|
||
</ToggleGroup>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
{isLoading ? (
|
||
<div className={viewMode === "grid"
|
||
? "grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
||
: "flex flex-col gap-2"
|
||
}>
|
||
{Array.from({ length: 6 }).map((_, i) => (
|
||
<div key={i} className="flex gap-3 rounded-lg border border-border bg-card p-3 sm:gap-4 sm:p-4">
|
||
<Skeleton className="h-12 w-12 shrink-0 rounded-lg sm:h-16 sm:w-16" />
|
||
<div className="flex-1 space-y-2">
|
||
<Skeleton className="h-4 w-3/4 sm:h-5" />
|
||
<Skeleton className="h-3 w-full sm:h-4" />
|
||
<Skeleton className="h-3 w-1/2" />
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
) : mods.length === 0 ? (
|
||
<div className="py-12 text-center text-muted-foreground">
|
||
لا توجد إضافات حالياً
|
||
</div>
|
||
) : (
|
||
<div className={viewMode === "grid"
|
||
? "grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
||
: "flex flex-col gap-2"
|
||
}>
|
||
{mods.map((mod) => (
|
||
<ModCard
|
||
key={mod.id}
|
||
id={mod.id}
|
||
slug={mod.slug}
|
||
title={mod.title}
|
||
description={mod.description}
|
||
iconUrl={mod.icon_url}
|
||
downloads={mod.downloads}
|
||
followers={mod.followers}
|
||
categories={mod.categories || []}
|
||
projectType={mod.project_type}
|
||
viewMode={viewMode}
|
||
/>
|
||
))}
|
||
</div>
|
||
)}
|
||
</section>
|
||
);
|
||
};
|
||
|
||
export default ModGrid;
|