Rename `AppType` to `AppId` across the entire frontend codebase to better reflect its purpose as an application identifier rather than a type category. This aligns frontend naming with backend command parameter conventions. Changes: - Rename type `AppType` to `AppId` in src/lib/api/types.ts - Remove `AppType` export from src/lib/api/index.ts - Update all component props from `appType` to `appId` (43 files) - Update all variable names from `appType` to `appId` - Synchronize documentation (CHANGELOG, refactoring plans) - Update test files and MSW mocks BREAKING CHANGE: `AppType` type is no longer exported. Use `AppId` instead. All component props have been renamed from `appType` to `appId`.
161 lines
3.9 KiB
TypeScript
161 lines
3.9 KiB
TypeScript
import { CSS } from "@dnd-kit/utilities";
|
|
import { DndContext, closestCenter } from "@dnd-kit/core";
|
|
import {
|
|
SortableContext,
|
|
useSortable,
|
|
verticalListSortingStrategy,
|
|
} from "@dnd-kit/sortable";
|
|
import type { CSSProperties } from "react";
|
|
import type { Provider } from "@/types";
|
|
import type { AppId } from "@/lib/api";
|
|
import { useDragSort } from "@/hooks/useDragSort";
|
|
import { ProviderCard } from "@/components/providers/ProviderCard";
|
|
import { ProviderEmptyState } from "@/components/providers/ProviderEmptyState";
|
|
|
|
interface ProviderListProps {
|
|
providers: Record<string, Provider>;
|
|
currentProviderId: string;
|
|
appId: AppId;
|
|
isEditMode?: boolean;
|
|
onSwitch: (provider: Provider) => void;
|
|
onEdit: (provider: Provider) => void;
|
|
onDelete: (provider: Provider) => void;
|
|
onDuplicate: (provider: Provider) => void;
|
|
onConfigureUsage?: (provider: Provider) => void;
|
|
onOpenWebsite: (url: string) => void;
|
|
onCreate?: () => void;
|
|
isLoading?: boolean;
|
|
}
|
|
|
|
export function ProviderList({
|
|
providers,
|
|
currentProviderId,
|
|
appId,
|
|
isEditMode = false,
|
|
onSwitch,
|
|
onEdit,
|
|
onDelete,
|
|
onDuplicate,
|
|
onConfigureUsage,
|
|
onOpenWebsite,
|
|
onCreate,
|
|
isLoading = false,
|
|
}: ProviderListProps) {
|
|
const { sortedProviders, sensors, handleDragEnd } = useDragSort(
|
|
providers,
|
|
appId,
|
|
);
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="space-y-3">
|
|
{[0, 1, 2].map((index) => (
|
|
<div
|
|
key={index}
|
|
className="h-28 w-full rounded-lg border border-dashed border-muted-foreground/40 bg-muted/40"
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (sortedProviders.length === 0) {
|
|
return <ProviderEmptyState onCreate={onCreate} />;
|
|
}
|
|
|
|
return (
|
|
<DndContext
|
|
sensors={sensors}
|
|
collisionDetection={closestCenter}
|
|
onDragEnd={handleDragEnd}
|
|
>
|
|
<SortableContext
|
|
items={sortedProviders.map((provider) => provider.id)}
|
|
strategy={verticalListSortingStrategy}
|
|
>
|
|
<div className="space-y-3">
|
|
{sortedProviders.map((provider) => (
|
|
<SortableProviderCard
|
|
key={provider.id}
|
|
provider={provider}
|
|
isCurrent={provider.id === currentProviderId}
|
|
appId={appId}
|
|
isEditMode={isEditMode}
|
|
onSwitch={onSwitch}
|
|
onEdit={onEdit}
|
|
onDelete={onDelete}
|
|
onDuplicate={onDuplicate}
|
|
onConfigureUsage={onConfigureUsage}
|
|
onOpenWebsite={onOpenWebsite}
|
|
/>
|
|
))}
|
|
</div>
|
|
</SortableContext>
|
|
</DndContext>
|
|
);
|
|
}
|
|
|
|
interface SortableProviderCardProps {
|
|
provider: Provider;
|
|
isCurrent: boolean;
|
|
appId: AppId;
|
|
isEditMode: boolean;
|
|
onSwitch: (provider: Provider) => void;
|
|
onEdit: (provider: Provider) => void;
|
|
onDelete: (provider: Provider) => void;
|
|
onDuplicate: (provider: Provider) => void;
|
|
onConfigureUsage?: (provider: Provider) => void;
|
|
onOpenWebsite: (url: string) => void;
|
|
}
|
|
|
|
function SortableProviderCard({
|
|
provider,
|
|
isCurrent,
|
|
appId,
|
|
isEditMode,
|
|
onSwitch,
|
|
onEdit,
|
|
onDelete,
|
|
onDuplicate,
|
|
onConfigureUsage,
|
|
onOpenWebsite,
|
|
}: SortableProviderCardProps) {
|
|
const {
|
|
setNodeRef,
|
|
attributes,
|
|
listeners,
|
|
transform,
|
|
transition,
|
|
isDragging,
|
|
} = useSortable({ id: provider.id });
|
|
|
|
const style: CSSProperties = {
|
|
transform: CSS.Transform.toString(transform),
|
|
transition,
|
|
};
|
|
|
|
return (
|
|
<div ref={setNodeRef} style={style}>
|
|
<ProviderCard
|
|
provider={provider}
|
|
isCurrent={isCurrent}
|
|
appId={appId}
|
|
isEditMode={isEditMode}
|
|
onSwitch={onSwitch}
|
|
onEdit={onEdit}
|
|
onDelete={onDelete}
|
|
onDuplicate={onDuplicate}
|
|
onConfigureUsage={
|
|
onConfigureUsage ? (item) => onConfigureUsage(item) : () => undefined
|
|
}
|
|
onOpenWebsite={onOpenWebsite}
|
|
dragHandleProps={{
|
|
attributes,
|
|
listeners,
|
|
isDragging,
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|