Add bill of materials after job creation

Add functionality to add bill of materials to a job after it has been created.
This commit is contained in:
gpt-engineer-app[bot]
2025-07-09 12:56:32 +00:00
committed by PhatPhuckDave
parent 260c1c0af3
commit dc5b91d104
2 changed files with 45 additions and 6 deletions

View File

@@ -1,4 +1,3 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@@ -12,7 +11,7 @@ import { parseISKAmount } from '@/utils/priceUtils';
interface JobFormProps { interface JobFormProps {
job?: IndJob; job?: IndJob;
onSubmit: (job: IndJobRecordNoId) => void; onSubmit: (job: IndJobRecordNoId, billOfMaterials?: { name: string; quantity: number }[]) => void;
onCancel: () => void; onCancel: () => void;
} }
@@ -26,9 +25,13 @@ const JobForm: React.FC<JobFormProps> = ({ job, onSubmit, onCancel }) => {
}); });
const [jobDump, setJobDump] = useState(''); const [jobDump, setJobDump] = useState('');
const [parsedBillOfMaterials, setParsedBillOfMaterials] = useState<{ name: string; quantity: number }[]>([]);
const parseJobDump = (dumpText: string) => { const parseJobDump = (dumpText: string) => {
if (!dumpText.trim()) return; if (!dumpText.trim()) {
setParsedBillOfMaterials([]);
return;
}
const lines = dumpText.trim().split('\n').filter(line => line.trim()); const lines = dumpText.trim().split('\n').filter(line => line.trim());
@@ -54,6 +57,26 @@ const JobForm: React.FC<JobFormProps> = ({ job, onSubmit, onCancel }) => {
projectedCost: cost, projectedCost: cost,
projectedRevenue: revenue projectedRevenue: revenue
})); }));
// Parse BOM starting from line 4 (after empty line)
const bomLines = lines.slice(4); // Skip first 3 lines and empty line
const billOfMaterials: { name: string; quantity: number }[] = [];
for (const line of bomLines) {
const trimmedLine = line.trim();
if (trimmedLine) {
const lastSpaceIndex = trimmedLine.lastIndexOf(' ');
if (lastSpaceIndex > 0) {
const materialName = trimmedLine.substring(0, lastSpaceIndex).trim();
const materialQuantity = parseInt(trimmedLine.substring(lastSpaceIndex + 1).trim()) || 0;
if (materialName && materialQuantity > 0) {
billOfMaterials.push({ name: materialName, quantity: materialQuantity });
}
}
}
}
setParsedBillOfMaterials(billOfMaterials);
} }
} }
}; };
@@ -73,7 +96,7 @@ const JobForm: React.FC<JobFormProps> = ({ job, onSubmit, onCancel }) => {
status: formData.status, status: formData.status,
projectedCost: formData.projectedCost, projectedCost: formData.projectedCost,
projectedRevenue: formData.projectedRevenue projectedRevenue: formData.projectedRevenue
}); }, parsedBillOfMaterials.length > 0 ? parsedBillOfMaterials : undefined);
}; };
const statusOptions = Object.values(IndJobStatusOptions); const statusOptions = Object.values(IndJobStatusOptions);
@@ -175,6 +198,11 @@ const JobForm: React.FC<JobFormProps> = ({ job, onSubmit, onCancel }) => {
className="bg-gray-800 border-gray-600 text-white min-h-[120px]" className="bg-gray-800 border-gray-600 text-white min-h-[120px]"
rows={6} rows={6}
/> />
{parsedBillOfMaterials.length > 0 && (
<div className="text-sm text-gray-400">
<p>Parsed {parsedBillOfMaterials.length} materials from dump</p>
</div>
)}
</div> </div>
<div className="flex gap-2 pt-4"> <div className="flex gap-2 pt-4">

View File

@@ -93,9 +93,20 @@ const Index = () => {
const { totalJobs, totalProfit, totalRevenue, calculateJobRevenue, calculateJobProfit } = useJobMetrics(regularJobs); const { totalJobs, totalProfit, totalRevenue, calculateJobRevenue, calculateJobProfit } = useJobMetrics(regularJobs);
const handleCreateJob = async (jobData: IndJobRecordNoId) => { const handleCreateJob = async (jobData: IndJobRecordNoId, billOfMaterials?: { name: string; quantity: number }[]) => {
try { try {
await createJob(jobData); const newJob = await createJob(jobData);
// If we have bill of materials from the job dump, add them to the newly created job
if (billOfMaterials && billOfMaterials.length > 0) {
const billItems = billOfMaterials.map(item => ({
name: item.name,
quantity: item.quantity,
unitPrice: 0
}));
await createMultipleBillItems(newJob.id, billItems, 'billOfMaterials');
}
setShowJobForm(false); setShowJobForm(false);
} catch (error) { } catch (error) {
console.error('Error creating job:', error); console.error('Error creating job:', error);