mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
138 lines
4.6 KiB
TypeScript
138 lines
4.6 KiB
TypeScript
import ResourceFlowCard from '@/components/resource-flow/ResourceFlowCard';
|
|
import Button from '@/components/ui/Button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
|
|
import { Flex, Stack } from '@/components/ui/layout';
|
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/Tabs';
|
|
import { useResourceFlowsByOrganization } from '@/hooks/api';
|
|
import { useTranslation } from '@/hooks/useI18n';
|
|
import type { ResourceDirection } from '@/schemas/backend/resource-flow';
|
|
import { Plus } from 'lucide-react';
|
|
import React, { useMemo, useState } from 'react';
|
|
|
|
interface ResourceFlowListProps {
|
|
organizationId: string;
|
|
onAddResourceFlow?: (direction: ResourceDirection) => void;
|
|
onViewMatches?: (resourceId: string) => void;
|
|
}
|
|
|
|
const ResourceFlowList: React.FC<ResourceFlowListProps> = ({
|
|
organizationId,
|
|
onAddResourceFlow,
|
|
onViewMatches,
|
|
}) => {
|
|
const { t } = useTranslation();
|
|
const [activeTab, setActiveTab] = useState('inputs');
|
|
const { data: resourceFlows, isLoading, error } = useResourceFlowsByOrganization(organizationId);
|
|
// Normalize and memoize filtered flows to prevent recalculation on every render
|
|
const safeResourceFlows = useMemo(
|
|
() => (Array.isArray(resourceFlows) ? resourceFlows : []),
|
|
[resourceFlows]
|
|
);
|
|
|
|
const { inputFlows, outputFlows } = useMemo(() => {
|
|
return {
|
|
inputFlows: safeResourceFlows.filter((flow) => flow?.Direction === 'input'),
|
|
outputFlows: safeResourceFlows.filter((flow) => flow?.Direction === 'output'),
|
|
};
|
|
}, [safeResourceFlows]);
|
|
|
|
// Show loading state only if we don't have any placeholder data
|
|
if (isLoading && safeResourceFlows.length === 0) {
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>{t('resourceFlows.title')}</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-muted-foreground">{t('common.loading')}</p>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>{t('resourceFlows.title')}</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-destructive">
|
|
{t('common.error')}: {error.message}
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<Flex align="center" justify="between">
|
|
<CardTitle>{t('resourceFlows.title')}</CardTitle>
|
|
{onAddResourceFlow && (
|
|
<Flex gap="xs">
|
|
<Button variant="outline" size="sm" onClick={() => onAddResourceFlow('input')}>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
{t('resourceFlows.addInput')}
|
|
</Button>
|
|
<Button variant="outline" size="sm" onClick={() => onAddResourceFlow('output')}>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
{t('resourceFlows.addOutput')}
|
|
</Button>
|
|
</Flex>
|
|
)}
|
|
</Flex>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
|
<TabsList className="grid w-full grid-cols-2">
|
|
<TabsTrigger value="inputs">
|
|
{t('resourceFlows.inputs')} ({inputFlows.length})
|
|
</TabsTrigger>
|
|
<TabsTrigger value="outputs">
|
|
{t('resourceFlows.outputs')} ({outputFlows.length})
|
|
</TabsTrigger>
|
|
</TabsList>
|
|
<TabsContent value="inputs" className="mt-4">
|
|
<Stack spacing="md">
|
|
{inputFlows.length > 0 ? (
|
|
inputFlows.map((flow) => (
|
|
<ResourceFlowCard
|
|
key={flow.ID}
|
|
resourceFlow={flow}
|
|
onViewMatches={onViewMatches}
|
|
/>
|
|
))
|
|
) : (
|
|
<p className="text-center text-muted-foreground py-8">
|
|
{t('resourceFlows.noInputs')}
|
|
</p>
|
|
)}
|
|
</Stack>
|
|
</TabsContent>
|
|
<TabsContent value="outputs" className="mt-4">
|
|
<Stack spacing="md">
|
|
{outputFlows.length > 0 ? (
|
|
outputFlows.map((flow) => (
|
|
<ResourceFlowCard
|
|
key={flow.ID}
|
|
resourceFlow={flow}
|
|
onViewMatches={onViewMatches}
|
|
/>
|
|
))
|
|
) : (
|
|
<p className="text-center text-muted-foreground py-8">
|
|
{t('resourceFlows.noOutputs')}
|
|
</p>
|
|
)}
|
|
</Stack>
|
|
</TabsContent>
|
|
</Tabs>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
export default React.memo(ResourceFlowList);
|