Files
eve-industrializer/src/components/MaterialsImportExport.tsx
gpt-engineer-app[bot] 15280ecdab Refactor MaterialsImportExport component
Refactor the MaterialsImportExport component into smaller, more manageable files.
2025-07-09 21:18:51 +02:00

174 lines
5.6 KiB
TypeScript

import React, { useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import { FileText } from 'lucide-react';
import { IndBillitemRecord } from '@/lib/pbtypes';
import { IndJob } from '@/lib/types';
import { dataService } from '@/services/dataService';
import { useToast } from '@/hooks/use-toast';
import { useMaterialsCalculations } from '@/hooks/useMaterialsCalculations';
import { parseBillOfMaterials, parseConsumedMaterials } from '@/utils/materialsParser';
import { exportBillOfMaterials, exportConsumedMaterials, exportMissingMaterials } from '@/utils/materialsExporter';
import MaterialsActions from './MaterialsActions';
import MaterialsList from './MaterialsList';
interface MaterialsImportExportProps {
job?: IndJob;
billOfMaterials: IndBillitemRecord[];
consumedMaterials: IndBillitemRecord[];
onBillOfMaterialsUpdate: (billItems: IndBillitemRecord[]) => void;
onConsumedMaterialsUpdate: (billItems: IndBillitemRecord[]) => void;
}
const MaterialsImportExport: React.FC<MaterialsImportExportProps> = ({
job,
billOfMaterials,
consumedMaterials,
onBillOfMaterialsUpdate,
onConsumedMaterialsUpdate
}) => {
const [bomInput, setBomInput] = useState('');
const [consumedInput, setConsumedInput] = useState('');
const { toast } = useToast();
const { calculateMissingMaterials } = useMaterialsCalculations(job, billOfMaterials);
const handleImportBom = async () => {
if (!job) return;
const materials = parseBillOfMaterials(bomInput);
if (materials.length > 0) {
try {
const updatedJob = await dataService.createMultipleBillItems(job.id, materials, 'billOfMaterials');
onBillOfMaterialsUpdate(updatedJob.billOfMaterials);
setBomInput('');
} catch (error) {
console.error('Error importing bill of materials:', error);
}
}
};
const handleImportConsumed = async () => {
if (!job) return;
const materials = parseConsumedMaterials(consumedInput);
if (materials.length > 0) {
try {
const updatedJob = await dataService.createMultipleBillItems(job.id, materials, 'consumedMaterials');
onConsumedMaterialsUpdate(updatedJob.consumedMaterials);
setConsumedInput('');
} catch (error) {
console.error('Error importing consumed materials:', error);
}
}
};
const handleExportBom = () => {
const exported = exportBillOfMaterials(billOfMaterials);
navigator.clipboard.writeText(exported);
toast({
title: "Exported",
description: "Bill of materials copied to clipboard",
duration: 2000,
});
};
const handleExportConsumed = () => {
const exported = exportConsumedMaterials(consumedMaterials);
navigator.clipboard.writeText(exported);
toast({
title: "Exported",
description: "Consumed materials copied to clipboard",
duration: 2000,
});
};
const handleExportMissing = () => {
const missingMaterials = calculateMissingMaterials();
const exported = exportMissingMaterials(missingMaterials);
if (exported) {
navigator.clipboard.writeText(exported);
toast({
title: "Exported",
description: "Missing materials copied to clipboard",
duration: 2000,
});
} else {
toast({
title: "Nothing Missing",
description: "All materials are satisfied for this job",
duration: 2000,
});
}
};
const missingMaterials = calculateMissingMaterials();
return (
<Card className="bg-gray-900 border-gray-700 text-white">
<CardHeader>
<CardTitle className="text-blue-400 flex items-center gap-2">
<FileText className="w-5 h-5" />
Materials Management
</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="space-y-4">
<Label className="text-gray-300">Bill of Materials</Label>
<MaterialsActions
type="bom"
onImport={handleImportBom}
onExport={handleExportBom}
onExportMissing={handleExportMissing}
importDisabled={!job}
missingDisabled={!job || missingMaterials.length === 0}
/>
<Textarea
placeholder="Paste bill of materials here (e.g., Mexallon 1000)"
value={bomInput}
onChange={(e) => setBomInput(e.target.value)}
className="bg-gray-800 border-gray-600 text-white"
rows={4}
/>
</div>
<div className="space-y-4">
<Label className="text-gray-300">Consumed Materials</Label>
<MaterialsActions
type="consumed"
onImport={handleImportConsumed}
onExport={handleExportConsumed}
importDisabled={!job}
/>
<Textarea
placeholder="Paste consumed materials here (tab-separated: Item\tRequired)"
value={consumedInput}
onChange={(e) => setConsumedInput(e.target.value)}
className="bg-gray-800 border-gray-600 text-white"
rows={4}
/>
</div>
<MaterialsList
title="Current Bill of Materials"
materials={billOfMaterials}
/>
<MaterialsList
title="Current Consumed Materials"
materials={consumedMaterials}
/>
<MaterialsList
title="Missing Materials"
materials={missingMaterials}
className="text-red-400"
/>
</CardContent>
</Card>
);
};
export default MaterialsImportExport;