Sort jobs such and such
This commit is contained in:
@@ -29,9 +29,9 @@ const JobCard: React.FC<JobCardProps> = ({ job, onEdit, onDelete }) => {
|
|||||||
case 'Planned': return 'bg-gray-600';
|
case 'Planned': return 'bg-gray-600';
|
||||||
case 'Acquisition': return 'bg-yellow-600';
|
case 'Acquisition': return 'bg-yellow-600';
|
||||||
case 'Running': return 'bg-blue-600';
|
case 'Running': return 'bg-blue-600';
|
||||||
case 'Done': return 'bg-green-600';
|
case 'Done': return 'bg-purple-600';
|
||||||
case 'Selling': return 'bg-purple-600';
|
case 'Selling': return 'bg-orange-600';
|
||||||
case 'Closed': return 'bg-gray-800';
|
case 'Closed': return 'bg-green-600';
|
||||||
default: return 'bg-gray-600';
|
default: return 'bg-gray-600';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Plus, Factory, TrendingUp, Briefcase } from 'lucide-react';
|
import { Plus, Factory, TrendingUp, Briefcase } from 'lucide-react';
|
||||||
import { IndTransactionRecordNoId, IndJobRecordNoId, IndTransactionRecord } from '@/lib/pbtypes';
|
import { IndTransactionRecordNoId, IndJobRecordNoId, IndTransactionRecord, IndJobStatusOptions } from '@/lib/pbtypes';
|
||||||
import * as jobService from '@/services/jobService';
|
import * as jobService from '@/services/jobService';
|
||||||
import * as transactionService from '@/services/transactionService';
|
import * as transactionService from '@/services/transactionService';
|
||||||
import { formatISK } from '@/utils/priceUtils';
|
import { formatISK } from '@/utils/priceUtils';
|
||||||
@@ -36,6 +36,29 @@ const Index = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Sort jobs by status priority
|
||||||
|
const getStatusPriority = (status: IndJobStatusOptions): number => {
|
||||||
|
switch (status) {
|
||||||
|
case 'Planned': return 6;
|
||||||
|
case 'Acquisition': return 1;
|
||||||
|
case 'Running': return 2;
|
||||||
|
case 'Done': return 3;
|
||||||
|
case 'Selling': return 4;
|
||||||
|
case 'Closed': return 5;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sortedJobs = [...jobs].sort((a, b) => {
|
||||||
|
const priorityA = getStatusPriority(a.status);
|
||||||
|
const priorityB = getStatusPriority(b.status);
|
||||||
|
if (priorityA === priorityB) {
|
||||||
|
// If same status, sort by creation date (newest first)
|
||||||
|
return new Date(b.created || '').getTime() - new Date(a.created || '').getTime();
|
||||||
|
}
|
||||||
|
return priorityA - priorityB;
|
||||||
|
});
|
||||||
|
|
||||||
const handleCreateJob = async (jobData: IndJobRecordNoId) => {
|
const handleCreateJob = async (jobData: IndJobRecordNoId) => {
|
||||||
try {
|
try {
|
||||||
const newJob = await createJob(jobData);
|
const newJob = await createJob(jobData);
|
||||||
@@ -296,7 +319,7 @@ const Index = () => {
|
|||||||
</Card>
|
</Card>
|
||||||
) : (
|
) : (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-6">
|
||||||
{jobs.map((job) => (
|
{sortedJobs.map((job) => (
|
||||||
<div key={job.id} onClick={() => setSelectedJob(job)} className="cursor-pointer">
|
<div key={job.id} onClick={() => setSelectedJob(job)} className="cursor-pointer">
|
||||||
<JobCard
|
<JobCard
|
||||||
job={job}
|
job={job}
|
||||||
|
@@ -2,27 +2,27 @@
|
|||||||
export const parseISKAmount = (iskString: string): number => {
|
export const parseISKAmount = (iskString: string): number => {
|
||||||
// Remove "ISK" and any extra whitespace
|
// Remove "ISK" and any extra whitespace
|
||||||
const cleanString = iskString.replace(/ISK/gi, '').trim();
|
const cleanString = iskString.replace(/ISK/gi, '').trim();
|
||||||
|
|
||||||
// Handle negative values
|
// Handle negative values
|
||||||
const isNegative = cleanString.startsWith('-');
|
const isNegative = cleanString.startsWith('-');
|
||||||
const numberString = cleanString.replace(/^-/, '');
|
const numberString = cleanString.replace(/^-/, '');
|
||||||
|
|
||||||
// Remove commas and parse
|
// Remove commas and parse
|
||||||
const amount = parseFloat(numberString.replace(/,/g, ''));
|
const amount = parseFloat(numberString.replace(/,/g, ''));
|
||||||
|
|
||||||
return isNegative ? -amount : amount;
|
return isNegative ? -amount : amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const formatISK = (amount: number): string => {
|
export const formatISK = (amount: number): string => {
|
||||||
const absAmount = Math.abs(amount);
|
const absAmount = Math.abs(amount);
|
||||||
const sign = amount < 0 ? '-' : '';
|
const sign = amount < 0 ? '-' : '';
|
||||||
|
|
||||||
// Format with commas and appropriate decimal places
|
// Format with commas and appropriate decimal places
|
||||||
const formatted = absAmount.toLocaleString('en-US', {
|
const formatted = absAmount.toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
});
|
});
|
||||||
|
|
||||||
return `${sign}${formatted} ISK`;
|
return `${sign}${formatted} ISK`;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,23 +39,29 @@ export const parseTransactionLine = (line: string): {
|
|||||||
} | null => {
|
} | null => {
|
||||||
try {
|
try {
|
||||||
const parts = line.split('\t');
|
const parts = line.split('\t');
|
||||||
if (parts.length < 8) return null;
|
if (parts.length < 6) return null;
|
||||||
|
|
||||||
const [dateStr, quantityStr, itemName, unitPriceStr, totalAmountStr, buyer, location, corporation, wallet] = parts;
|
let dateStr, quantityStr, itemName, unitPriceStr, totalAmountStr, buyer, location, corporation, wallet;
|
||||||
|
if (parts.length === 8) {
|
||||||
|
[dateStr, quantityStr, itemName, unitPriceStr, totalAmountStr, buyer, location, corporation, wallet] = parts;
|
||||||
|
} else {
|
||||||
|
[dateStr, quantityStr, itemName, unitPriceStr, totalAmountStr, buyer, location] = parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse date (YYYY.MM.DD HH:mm format)
|
// Parse date (YYYY.MM.DD HH:mm format)
|
||||||
const [datePart, timePart] = dateStr.split(' ');
|
const [datePart, timePart] = dateStr.split(' ');
|
||||||
const [year, month, day] = datePart.split('.').map(Number);
|
const [year, month, day] = datePart.split('.').map(Number);
|
||||||
const [hour, minute] = timePart.split(':').map(Number);
|
const [hour, minute] = timePart.split(':').map(Number);
|
||||||
const date = new Date(year, month - 1, day, hour, minute);
|
const date = new Date(year, month - 1, day, hour, minute);
|
||||||
|
|
||||||
// Parse quantity (remove commas)
|
// Parse quantity (remove commas)
|
||||||
const quantity = parseInt(quantityStr.replace(/,/g, ''));
|
const quantity = parseInt(quantityStr.replace(/,/g, ''));
|
||||||
|
|
||||||
// Parse prices
|
// Parse prices
|
||||||
const unitPrice = parseISKAmount(unitPriceStr);
|
const unitPrice = parseISKAmount(unitPriceStr);
|
||||||
const totalAmount = parseISKAmount(totalAmountStr);
|
const totalAmount = parseISKAmount(totalAmountStr);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
date,
|
date,
|
||||||
quantity,
|
quantity,
|
||||||
|
Reference in New Issue
Block a user