diff --git a/src/components/BatchTransactionForm.tsx b/src/components/BatchTransactionForm.tsx index 5522de8..ac08939 100644 --- a/src/components/BatchTransactionForm.tsx +++ b/src/components/BatchTransactionForm.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; @@ -173,6 +173,22 @@ const BatchTransactionForm: React.FC = ({ onClose, on setTransactionGroups(groups); }; + // Read clipboard on mount + useEffect(() => { + const readClipboard = async () => { + try { + const text = await navigator.clipboard.readText(); + if (text.trim()) { + setPastedData(text); + handlePaste(text); + } + } catch (err) { + // Clipboard reading failed, ignore silently + } + }; + readClipboard(); + }, []); + const handleAssignJob = (groupIndex: number, jobId: string) => { setTransactionGroups(prev => { const newGroups = [...prev]; diff --git a/src/components/JobCardDetails.tsx b/src/components/JobCardDetails.tsx index 67b9e02..111fc9e 100644 --- a/src/components/JobCardDetails.tsx +++ b/src/components/JobCardDetails.tsx @@ -1,11 +1,11 @@ import { useState } from 'react'; import { Calendar, Factory, Clock, Copy } from 'lucide-react'; -import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'; import { Input } from '@/components/ui/input'; import { IndJob } from '@/lib/types'; import { useJobs } from '@/hooks/useDataService'; import { useToast } from '@/hooks/use-toast'; import { useClipboard } from '@/hooks/useClipboard'; +import { formatISK } from '@/utils/priceUtils'; interface JobCardDetailsProps { job: IndJob; @@ -149,33 +149,55 @@ const JobCardDetails: React.FC = ({ job }) => { /> - {job.billOfMaterials && job.billOfMaterials.length > 0 && ( - - -
- BOM: {job.billOfMaterials.length} items (hover to view) -
-
- -
-

Bill of Materials

-
- {job.billOfMaterials.map((item, index) => ( -
- {item.name} - {item.quantity.toLocaleString()} -
- ))} -
-
-
-
+ {job.projectedRevenue > 0 && job.produced > 0 && ( +
+ +
)} ); }; +interface MinPriceDisplayProps { + job: IndJob; +} + +const MinPriceDisplay: React.FC = ({ job }) => { + const { copying, copyToClipboard } = useClipboard(); + + // Get sales tax from localStorage (default 0%) + const salesTax = parseFloat(localStorage.getItem('salesTax') || '0') / 100; + + const minPricePerUnit = job.projectedRevenue / job.produced; + const minPriceWithTax = minPricePerUnit * (1 + salesTax); + + const handleCopyPrice = async (e: React.MouseEvent) => { + e.stopPropagation(); + await copyToClipboard( + minPriceWithTax.toFixed(2), + 'minPrice', + 'Minimum price copied to clipboard' + ); + }; + + return ( +
+ + Min Price: + + {formatISK(minPriceWithTax)} + {copying === 'minPrice' && } + + + per unit {salesTax > 0 && `(+${(salesTax * 100).toFixed(1)}% tax)`} + +
+ ); +}; + export default JobCardDetails; diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index 20c745a..02562ee 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -1,7 +1,10 @@ import { useState, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Plus, Factory, TrendingUp, Briefcase, FileText } from 'lucide-react'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { Plus, Factory, TrendingUp, Briefcase, FileText, Settings } from 'lucide-react'; import { IndTransactionRecordNoId, IndJobRecordNoId } from '@/lib/pbtypes'; import { formatISK } from '@/utils/priceUtils'; import { getStatusPriority } from '@/utils/jobStatusUtils'; @@ -256,6 +259,7 @@ const Index = () => {

Jobs

+ + + +
+
+ + setSalesTax(e.target.value)} + placeholder="0" + min="0" + max="100" + step="0.1" + className="bg-gray-800 border-gray-600 text-white" + /> +

+ Applied to minimum price calculations +

+
+
+ + +
+
+
+ + ); +}; + export default Index;