mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Remove nested git repository from bugulma/frontend/.git - Add all frontend files to main repository tracking - Convert from separate frontend/backend repos to unified monorepo - Preserve all frontend code and development history as tracked files - Eliminate nested repository complexity for simpler development workflow This creates a proper monorepo structure with frontend and backend coexisting in the same repository for easier development and deployment.
100 lines
3.4 KiB
TypeScript
100 lines
3.4 KiB
TypeScript
import { Search } from 'lucide-react';
|
|
import React from 'react';
|
|
import { useAuth } from '@/contexts/AuthContext';
|
|
import { useTranslation } from '@/hooks/useI18n';
|
|
import type { BackendResourceFlow } from '@/schemas/backend/resource-flow';
|
|
import Badge from '@/components/ui/Badge';
|
|
import Button from '@/components/ui/Button';
|
|
import { Card } from '@/components/ui/Card';
|
|
|
|
interface ResourceFlowCardProps {
|
|
resourceFlow: BackendResourceFlow;
|
|
onViewMatches?: (resourceId: string) => void;
|
|
}
|
|
|
|
const ResourceFlowCard: React.FC<ResourceFlowCardProps> = ({ resourceFlow, onViewMatches }) => {
|
|
const { t } = useTranslation();
|
|
const { isAuthenticated } = useAuth();
|
|
|
|
const formatQuantity = () => {
|
|
const { amount, unit, temporal_unit } = resourceFlow.Quantity;
|
|
let quantity = `${amount} ${unit}`;
|
|
if (temporal_unit) {
|
|
quantity += `/${temporal_unit}`;
|
|
}
|
|
return quantity;
|
|
};
|
|
|
|
const getQualityInfo = () => {
|
|
const quality = resourceFlow.Quality;
|
|
const info: string[] = [];
|
|
|
|
if (quality.temperature_celsius !== undefined) {
|
|
info.push(`${quality.temperature_celsius}°C`);
|
|
}
|
|
if (quality.pressure_bar !== undefined) {
|
|
info.push(`${quality.pressure_bar} bar`);
|
|
}
|
|
if (quality.physical_state) {
|
|
info.push(quality.physical_state);
|
|
}
|
|
|
|
return info.join(' • ');
|
|
};
|
|
|
|
const getTypeLabel = () => {
|
|
return t(`resourceTypes.${resourceFlow.Type}`) || resourceFlow.Type;
|
|
};
|
|
|
|
return (
|
|
<Card className="shadow-none">
|
|
<div className="p-4 space-y-3">
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex-1">
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<Badge variant={resourceFlow.Direction === 'input' ? 'destructive' : 'default'}>
|
|
{resourceFlow.Direction === 'input'
|
|
? t('resourceFlows.input')
|
|
: t('resourceFlows.output')}
|
|
</Badge>
|
|
<Badge variant="outline">{getTypeLabel()}</Badge>
|
|
{resourceFlow.PrecisionLevel && (
|
|
<Badge variant="outline" className="text-xs">
|
|
{resourceFlow.PrecisionLevel}
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
<h4 className="font-semibold text-base mb-1">{getTypeLabel()}</h4>
|
|
<p className="text-sm text-muted-foreground mb-2">{formatQuantity()}</p>
|
|
{getQualityInfo() && (
|
|
<p className="text-xs text-muted-foreground">{getQualityInfo()}</p>
|
|
)}
|
|
{resourceFlow.EconomicData && (
|
|
<div className="mt-2 text-xs text-muted-foreground">
|
|
{resourceFlow.EconomicData.cost_out !== undefined && (
|
|
<span>Cost: €{resourceFlow.EconomicData.cost_out.toFixed(2)}</span>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
{onViewMatches && resourceFlow.Direction === 'output' && isAuthenticated && (
|
|
<div className="flex gap-2 pt-2 border-t">
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={() => onViewMatches(resourceFlow.ID)}
|
|
className="flex-1"
|
|
>
|
|
<Search className="h-4 w-4 mr-2" />
|
|
{t('resourceFlows.findMatches')}
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
export default React.memo(ResourceFlowCard);
|