Fix status button colors and runtime display
Fixed status button colors. Added remaining runtime display for running jobs below "sale start" and "sale end" in job details.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Calendar, Factory, Clock, Copy, DollarSign } from 'lucide-react';
|
||||
import { Input } from '@/components/ui/input';
|
||||
@@ -6,6 +7,7 @@ import { useJobs } from '@/hooks/useDataService';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { useClipboard } from '@/hooks/useClipboard';
|
||||
import { formatISK } from '@/utils/priceUtils';
|
||||
import { formatDuration, calculateRemainingTime } from '@/utils/timeUtils';
|
||||
|
||||
interface JobCardDetailsProps {
|
||||
job: IndJob;
|
||||
@@ -14,11 +16,26 @@ interface JobCardDetailsProps {
|
||||
const JobCardDetails: React.FC<JobCardDetailsProps> = ({ job }) => {
|
||||
const [editingField, setEditingField] = useState<string | null>(null);
|
||||
const [tempValues, setTempValues] = useState<{ [key: string]: string }>({});
|
||||
const [remainingTime, setRemainingTime] = useState<number>(0);
|
||||
const { updateJob } = useJobs();
|
||||
const { toast } = useToast();
|
||||
|
||||
const { copying, copyToClipboard } = useClipboard();
|
||||
|
||||
// Update remaining time for running jobs
|
||||
useEffect(() => {
|
||||
if (job.status === 'Running' && job.jobStart && job.runtime) {
|
||||
const updateRemainingTime = () => {
|
||||
const remaining = calculateRemainingTime(job.jobStart, job.runtime);
|
||||
setRemainingTime(remaining);
|
||||
};
|
||||
|
||||
updateRemainingTime();
|
||||
const interval = setInterval(updateRemainingTime, 1000);
|
||||
return () => clearInterval(interval);
|
||||
}
|
||||
}, [job.status, job.jobStart, job.runtime]);
|
||||
|
||||
const formatDateTime = (dateString: string | null | undefined) => {
|
||||
if (!dateString) return 'Not set';
|
||||
return new Date(dateString).toLocaleString('en-CA', {
|
||||
@@ -183,6 +200,26 @@ const JobCardDetails: React.FC<JobCardDetailsProps> = ({ job }) => {
|
||||
fieldName="saleEnd"
|
||||
icon={<Calendar className="w-4 h-4" />}
|
||||
/>
|
||||
|
||||
{job.status === 'Running' && job.runtime && (
|
||||
<>
|
||||
<div className="flex items-center gap-2 text-sm text-gray-400">
|
||||
<Clock className="w-4 h-4" />
|
||||
<span>Runtime:</span>
|
||||
</div>
|
||||
<div className="text-sm text-white">
|
||||
{formatDuration(job.runtime)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-gray-400">
|
||||
<Clock className="w-4 h-4" />
|
||||
<span>Remaining:</span>
|
||||
</div>
|
||||
<div className="text-sm text-green-400">
|
||||
{formatDuration(remainingTime)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{job.projectedRevenue > 0 && job.produced > 0 && (
|
||||
|
@@ -74,7 +74,7 @@ const JobStatusNavigation: React.FC<JobStatusNavigationProps> = ({ job }) => {
|
||||
e.stopPropagation();
|
||||
handleStatusChange(previousStatus);
|
||||
}}
|
||||
className={`${getStatusColor(previousStatus)}/60 text-white px-4 py-2 rounded flex items-center justify-center gap-1 hover:opacity-80 transition-opacity w-32`}
|
||||
className={`${getStatusColor(previousStatus)} text-white px-4 py-2 rounded flex items-center justify-center gap-1 hover:opacity-80 transition-opacity w-32`}
|
||||
data-no-navigate
|
||||
title={`Move to ${previousStatus}`}
|
||||
>
|
||||
@@ -88,7 +88,7 @@ const JobStatusNavigation: React.FC<JobStatusNavigationProps> = ({ job }) => {
|
||||
e.stopPropagation();
|
||||
handleStatusChange(nextStatus);
|
||||
}}
|
||||
className={`${getStatusColor(nextStatus)}/60 text-white px-4 py-2 rounded flex items-center justify-center gap-1 hover:opacity-80 transition-opacity w-32`}
|
||||
className={`${getStatusColor(nextStatus)} text-white px-4 py-2 rounded flex items-center justify-center gap-1 hover:opacity-80 transition-opacity w-32`}
|
||||
data-no-navigate
|
||||
title={`Move to ${nextStatus}`}
|
||||
>
|
||||
|
35
src/utils/timeUtils.ts
Normal file
35
src/utils/timeUtils.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
export const formatDuration = (seconds: number): string => {
|
||||
if (seconds <= 0) return 'Ready!';
|
||||
|
||||
const units = [
|
||||
{ name: 'w', value: 604800 }, // weeks
|
||||
{ name: 'd', value: 86400 }, // days
|
||||
{ name: 'h', value: 3600 }, // hours
|
||||
{ name: 'm', value: 60 }, // minutes
|
||||
{ name: 's', value: 1 } // seconds
|
||||
];
|
||||
|
||||
const parts: string[] = [];
|
||||
let remaining = Math.floor(seconds);
|
||||
|
||||
for (const unit of units) {
|
||||
if (remaining >= unit.value) {
|
||||
const count = Math.floor(remaining / unit.value);
|
||||
parts.push(`${count}${unit.name}`);
|
||||
remaining %= unit.value;
|
||||
}
|
||||
}
|
||||
|
||||
return parts.length > 0 ? parts.join(' ') : '0s';
|
||||
};
|
||||
|
||||
export const calculateRemainingTime = (jobStart: string | null, runtime: number): number => {
|
||||
if (!jobStart || !runtime) return 0;
|
||||
|
||||
const startTime = new Date(jobStart).getTime();
|
||||
const currentTime = Date.now();
|
||||
const elapsedSeconds = (currentTime - startTime) / 1000;
|
||||
|
||||
return Math.max(0, runtime - elapsedSeconds);
|
||||
};
|
Reference in New Issue
Block a user