Replaced card-based layout with tabbed interface for APK environments. Now displays APKs grouped by dev/product/sandbox/other tabs with counts. - Replaced ApkCard with ApkTable component - Added tab navigation with active state styling - Group APKs by environment using reduce - Show count badges for each environment tab Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
97 lines
2.5 KiB
TypeScript
97 lines
2.5 KiB
TypeScript
'use client';
|
||
|
||
import { useState } from 'react';
|
||
import useSWR from 'swr';
|
||
import { formatVersion } from '@/lib/utils';
|
||
import { type ApkEnvironment } from '@/lib/apk-parser';
|
||
import ApkTable from './ApkTable';
|
||
|
||
const fetcher = (url: string) => fetch(url).then((res) => res.json());
|
||
|
||
interface Apk {
|
||
name: string;
|
||
environment: ApkEnvironment;
|
||
commit: string | null;
|
||
size: number;
|
||
modifiedAt: string;
|
||
downloadUrl: string;
|
||
}
|
||
|
||
interface ApkListProps {
|
||
project: string;
|
||
version: string;
|
||
commitId: string;
|
||
}
|
||
|
||
const TABS: ApkEnvironment[] = ['dev', 'product', 'sandbox', 'other'];
|
||
|
||
export default function ApkList({ project, version, commitId }: ApkListProps) {
|
||
const [activeTab, setActiveTab] = useState<ApkEnvironment>('product');
|
||
|
||
const { data: apks, isLoading, error } = useSWR<Apk[]>(
|
||
`/api/apks?project=${project}&version=${version}&commit=${commitId}`,
|
||
fetcher
|
||
);
|
||
|
||
if (isLoading) {
|
||
return (
|
||
<div className="text-center py-8 text-gray-500">
|
||
加载中...
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (error) {
|
||
return (
|
||
<div className="text-center py-8 text-red-600">
|
||
加载失败,请重试
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (!apks || apks.length === 0) {
|
||
return (
|
||
<div className="bg-white rounded-lg shadow-md p-12 text-center">
|
||
<p className="text-gray-500">未找到匹配的 APK 文件</p>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// Group APKs by environment
|
||
const groupedApks = apks.reduce((acc, apk) => {
|
||
acc[apk.environment] = [...(acc[apk.environment] || []), apk];
|
||
return acc;
|
||
}, {} as Record<ApkEnvironment, Apk[]>);
|
||
|
||
return (
|
||
<div>
|
||
{/* Tab Navigation */}
|
||
<div className="bg-white rounded-t-lg border-b border-gray-200">
|
||
<nav className="flex space-x-8 px-6" aria-label="Tabs">
|
||
{TABS.map((tab) => {
|
||
const count = groupedApks[tab]?.length || 0;
|
||
return (
|
||
<button
|
||
key={tab}
|
||
onClick={() => setActiveTab(tab)}
|
||
className={`py-4 px-1 border-b-2 font-medium text-sm ${
|
||
activeTab === tab
|
||
? 'border-blue-500 text-blue-600'
|
||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||
}`}
|
||
>
|
||
{tab} ({count})
|
||
</button>
|
||
);
|
||
})}
|
||
</nav>
|
||
</div>
|
||
|
||
{/* Tab Content */}
|
||
<div className="mt-4">
|
||
<ApkTable apks={groupedApks[activeTab] || []} />
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|