Add projected cost and revenue
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
|
||||
import React from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@@ -160,6 +159,17 @@ const JobCard: React.FC<JobCardProps> = ({ job, onEdit, onDelete }) => {
|
||||
<span className="text-sm">Expenditure</span>
|
||||
</div>
|
||||
<div className="font-semibold">{formatISK(totalExpenditure)}</div>
|
||||
{job.projectedCost > 0 && (
|
||||
<div className="text-xs text-gray-400">
|
||||
vs Projected: {formatISK(job.projectedCost)}
|
||||
<Badge
|
||||
variant={totalExpenditure <= job.projectedCost ? 'default' : 'destructive'}
|
||||
className="ml-1 text-xs"
|
||||
>
|
||||
{((totalExpenditure / job.projectedCost) * 100).toFixed(1)}%
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="flex items-center justify-center gap-1 text-green-400">
|
||||
@@ -167,6 +177,17 @@ const JobCard: React.FC<JobCardProps> = ({ job, onEdit, onDelete }) => {
|
||||
<span className="text-sm">Income</span>
|
||||
</div>
|
||||
<div className="font-semibold">{formatISK(totalIncome)}</div>
|
||||
{job.projectedRevenue > 0 && (
|
||||
<div className="text-xs text-gray-400">
|
||||
vs Projected: {formatISK(job.projectedRevenue)}
|
||||
<Badge
|
||||
variant={totalIncome >= job.projectedRevenue ? 'default' : 'destructive'}
|
||||
className="ml-1 text-xs"
|
||||
>
|
||||
{((totalIncome / job.projectedRevenue) * 100).toFixed(1)}%
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="text-sm text-gray-400">Profit</div>
|
||||
@@ -176,6 +197,11 @@ const JobCard: React.FC<JobCardProps> = ({ job, onEdit, onDelete }) => {
|
||||
<Badge variant={profit >= 0 ? 'default' : 'destructive'} className="text-xs">
|
||||
{margin.toFixed(1)}%
|
||||
</Badge>
|
||||
{job.projectedRevenue > 0 && job.projectedCost > 0 && (
|
||||
<div className="text-xs text-gray-400 mt-1">
|
||||
vs Projected: {formatISK(job.projectedRevenue - job.projectedCost)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
@@ -1,14 +1,14 @@
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { IndBillitemRecordNoId, IndJobStatusOptions, IndJobRecordNoId, IndFacilityRecord, IndBillitemRecord } from '@/lib/pbtypes';
|
||||
import { IndJobStatusOptions, IndJobRecordNoId, IndBillitemRecord } from '@/lib/pbtypes';
|
||||
import MaterialsImportExport from './MaterialsImportExport';
|
||||
import { IndJob } from '@/lib/types';
|
||||
import { parseISKAmount } from '@/utils/priceUtils';
|
||||
// import { getFacilities } from '@/services/facilityService';
|
||||
|
||||
interface JobFormProps {
|
||||
@@ -32,7 +32,9 @@ const JobForm: React.FC<JobFormProps> = ({ job, onSubmit, onCancel }) => {
|
||||
billOfMaterials: job?.billOfMaterials || [],
|
||||
consumedMaterials: job?.consumedMaterials || [],
|
||||
expenditures: job?.expenditures || [],
|
||||
income: job?.income || []
|
||||
income: job?.income || [],
|
||||
projectedCost: job?.projectedCost || 0,
|
||||
projectedRevenue: job?.projectedRevenue || 0
|
||||
});
|
||||
|
||||
// useEffect(() => {
|
||||
@@ -62,7 +64,9 @@ const JobForm: React.FC<JobFormProps> = ({ job, onSubmit, onCancel }) => {
|
||||
billOfMaterials: formData.billOfMaterials.map(item => item.id),
|
||||
consumedMaterials: formData.consumedMaterials.map(item => item.id),
|
||||
expenditures: formData.expenditures.map(item => item.id),
|
||||
income: formData.income.map(item => item.id)
|
||||
income: formData.income.map(item => item.id),
|
||||
projectedCost: formData.projectedCost,
|
||||
projectedRevenue: formData.projectedRevenue
|
||||
});
|
||||
};
|
||||
|
||||
@@ -191,6 +195,35 @@ const JobForm: React.FC<JobFormProps> = ({ job, onSubmit, onCancel }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="projectedCost" className="text-gray-300">Projected Cost</Label>
|
||||
<Input
|
||||
id="projectedCost"
|
||||
type="text"
|
||||
value={formData.projectedCost ? `${formData.projectedCost.toLocaleString()} ISK` : ''}
|
||||
onChange={(e) => setFormData({
|
||||
...formData,
|
||||
projectedCost: parseISKAmount(e.target.value)
|
||||
})}
|
||||
className="bg-gray-800 border-gray-600 text-white"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="projectedRevenue" className="text-gray-300">Projected Revenue</Label>
|
||||
<Input
|
||||
id="projectedRevenue"
|
||||
type="text"
|
||||
value={formData.projectedRevenue ? `${formData.projectedRevenue.toLocaleString()} ISK` : ''}
|
||||
onChange={(e) => setFormData({
|
||||
...formData,
|
||||
projectedRevenue: parseISKAmount(e.target.value)
|
||||
})}
|
||||
className="bg-gray-800 border-gray-600 text-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 pt-4">
|
||||
<Button type="submit" className="flex-1 bg-blue-600 hover:bg-blue-700">
|
||||
{job ? 'Update Job' : 'Create Job'}
|
||||
|
@@ -134,6 +134,8 @@ export type IndJobRecord = {
|
||||
jobStart?: IsoDateString
|
||||
outputItem: string
|
||||
outputQuantity: number
|
||||
projectedCost?: number
|
||||
projectedRevenue?: number
|
||||
saleEnd?: IsoDateString
|
||||
saleStart?: IsoDateString
|
||||
status: IndJobStatusOptions
|
||||
|
@@ -17,4 +17,6 @@ export type IndJob = {
|
||||
saleStart?: IsoDateString
|
||||
status: IndJobStatusOptions
|
||||
updated?: IsoDateString
|
||||
projectedCost?: number
|
||||
projectedRevenue?: number
|
||||
}
|
Reference in New Issue
Block a user