- Phase 1-5: UI framework, auth, weapon schemes, color filters, system optimization - Industrial/tech design style with Chinese localization - Points to gch3n.online/delta backend API - Hardware monitor, filter editor, and all module pages
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import React from 'react';
|
|
import SchemeCard from './SchemeCard';
|
|
import type { SchemeData } from './SchemeCard';
|
|
|
|
interface SchemeListProps {
|
|
schemes: SchemeData[];
|
|
loading?: boolean;
|
|
favoritedIds?: Set<string>;
|
|
page: number;
|
|
totalPages: number;
|
|
onPageChange: (page: number) => void;
|
|
onFavorite: (id: string) => void;
|
|
onUse: (id: string) => void;
|
|
onClick: (id: string) => void;
|
|
className?: string;
|
|
}
|
|
|
|
export default function SchemeList({
|
|
schemes, loading, favoritedIds = new Set(),
|
|
page, totalPages, onPageChange,
|
|
onFavorite, onUse, onClick, className = ''
|
|
}: SchemeListProps) {
|
|
if (loading) {
|
|
return (
|
|
<div className={`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-1.5 ${className}`}>
|
|
{Array.from({ length: 6 }).map((_, i) => (
|
|
<div key={i} className="border border-[#333] bg-[#1a1a1a] p-3 animate-pulse">
|
|
<div className="h-3 bg-[#222] w-3/4 mb-2" />
|
|
<div className="h-2.5 bg-[#222] w-1/2 mb-3" />
|
|
<div className="h-6 bg-[#222] w-full" />
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!schemes.length) {
|
|
return (
|
|
<div className="flex flex-col items-center justify-center py-12 gap-2 border border-[#333]">
|
|
<span className="text-[24px] text-[#444]">📭</span>
|
|
<p className="text-[10px] font-mono text-[#555]">暂无方案数据</p>
|
|
<span className="tech-sn">EMPTY / 404</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className={`flex flex-col gap-3 ${className}`}>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-1.5">
|
|
{schemes.map(s => (
|
|
<SchemeCard
|
|
key={s.id}
|
|
scheme={s}
|
|
isFavorited={favoritedIds.has(s.id)}
|
|
onFavorite={onFavorite}
|
|
onUse={onUse}
|
|
onClick={onClick}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
{/* 分页 */}
|
|
{totalPages > 1 && (
|
|
<div className="flex items-center justify-center gap-1 border-t border-[#333] pt-2">
|
|
<button
|
|
disabled={page <= 1}
|
|
onClick={() => onPageChange(page - 1)}
|
|
className="px-2 py-1 text-[8px] font-mono text-[#555] border border-[#333] disabled:opacity-30 hover:border-[#555]"
|
|
>
|
|
◀
|
|
</button>
|
|
{Array.from({ length: totalPages }).map((_, i) => (
|
|
<button
|
|
key={i}
|
|
onClick={() => onPageChange(i + 1)}
|
|
className={`px-2 py-1 text-[8px] font-mono border transition-colors duration-75
|
|
${page === i + 1
|
|
? 'border-[#ff4500] text-[#ff4500] bg-[#ff4500]/10'
|
|
: 'border-[#333] text-[#555] hover:border-[#555]'}`}
|
|
>
|
|
{i + 1}
|
|
</button>
|
|
))}
|
|
<button
|
|
disabled={page >= totalPages}
|
|
onClick={() => onPageChange(page + 1)}
|
|
className="px-2 py-1 text-[8px] font-mono text-[#555] border border-[#333] disabled:opacity-30 hover:border-[#555]"
|
|
>
|
|
▶
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|