Spaces:
Running
Running
The format of the results returned by the /api/jobs endpoint has changed to: {"id":5858,"end_time":"2025-04-01T14:54:00.000Z","description":"Fingerprint from photo on signet table","quantity":1,"customer_ref":"7964 / C Wilkinson","job_status":"Complete","customer_name":"Hockley Jewellers","customer_monthly_flag":null,"item_price":"32.50","total_amount":"32.50"}. Update the code to accommodate these changes. - Follow Up Deployment
Browse files- index.html +39 -16
index.html
CHANGED
|
@@ -403,8 +403,18 @@
|
|
| 403 |
// Initialize date range picker
|
| 404 |
initDateRangePicker();
|
| 405 |
|
| 406 |
-
// Set current week as default
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 407 |
setCurrentWeek();
|
|
|
|
|
|
|
|
|
|
| 408 |
|
| 409 |
// Render jobs tables
|
| 410 |
renderJobsTable();
|
|
@@ -598,6 +608,7 @@
|
|
| 598 |
|
| 599 |
jobsData = await response.json();
|
| 600 |
renderJobsTable();
|
|
|
|
| 601 |
|
| 602 |
// Hide loading overlay
|
| 603 |
document.getElementById('loading-overlay').classList.add('hidden');
|
|
@@ -679,9 +690,10 @@
|
|
| 679 |
row.innerHTML = `
|
| 680 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 681 |
<div class="font-medium text-gray-900">${job.customer_name || 'N/A'}</div>
|
|
|
|
| 682 |
</td>
|
| 683 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 684 |
-
<div class="text-gray-900">${job.
|
| 685 |
</td>
|
| 686 |
<td class="px-6 py-4">
|
| 687 |
<div class="text-gray-900 max-w-xs truncate">${job.description || 'No description'}</div>
|
|
@@ -690,10 +702,10 @@
|
|
| 690 |
<div class="text-gray-900">${job.quantity || 0}</div>
|
| 691 |
</td>
|
| 692 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 693 |
-
<div class="text-gray-900">£${(job.
|
| 694 |
</td>
|
| 695 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 696 |
-
<div class="font-medium text-gray-900">£${(
|
| 697 |
</td>
|
| 698 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 699 |
<img src="${job.thumbnail_url || 'https://via.placeholder.com/100'}" alt="Thumbnail" class="w-12 h-12 object-cover rounded cursor-pointer thumbnail" data-image="${job.image_url || 'https://via.placeholder.com/800'}">
|
|
@@ -728,9 +740,10 @@
|
|
| 728 |
row.innerHTML = `
|
| 729 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 730 |
<div class="font-medium text-gray-900">${job.customer_name || 'N/A'}</div>
|
|
|
|
| 731 |
</td>
|
| 732 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 733 |
-
<div class="text-gray-900">${job.
|
| 734 |
</td>
|
| 735 |
<td class="px-6 py-4">
|
| 736 |
<div class="text-gray-900 max-w-xs truncate">${job.description || 'No description'}</div>
|
|
@@ -828,14 +841,22 @@
|
|
| 828 |
|
| 829 |
// Initialize the pie chart
|
| 830 |
function initPieChart() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 831 |
const customerCounts = {};
|
| 832 |
jobsData.forEach(job => {
|
| 833 |
const customer = job.customer_name || 'Unknown';
|
| 834 |
customerCounts[customer] = (customerCounts[customer] || 0) + 1;
|
| 835 |
});
|
| 836 |
|
| 837 |
-
|
| 838 |
-
const
|
|
|
|
| 839 |
|
| 840 |
const colors = [
|
| 841 |
'rgba(59, 130, 246, 0.7)',
|
|
@@ -845,7 +866,7 @@
|
|
| 845 |
'rgba(220, 38, 38, 0.7)'
|
| 846 |
];
|
| 847 |
|
| 848 |
-
const ctx =
|
| 849 |
new Chart(ctx, {
|
| 850 |
type: 'pie',
|
| 851 |
data: {
|
|
@@ -931,14 +952,14 @@
|
|
| 931 |
const job = [...jobsData, ...invalidJobsData].find(j => j.job_id === jobId);
|
| 932 |
|
| 933 |
if (job) {
|
| 934 |
-
document.getElementById('edit-job-id').value = job.
|
| 935 |
-
document.getElementById('edit-job-id-display').value = job.
|
| 936 |
document.getElementById('edit-customer').value = job.customer_name || '';
|
| 937 |
document.getElementById('edit-description').value = job.description || '';
|
| 938 |
document.getElementById('edit-quantity').value = job.quantity || '';
|
| 939 |
-
document.getElementById('edit-price').value = job.
|
| 940 |
-
document.getElementById('edit-total').value =
|
| 941 |
-
document.getElementById('edit-end-date').value = job.
|
| 942 |
document.getElementById('edit-thumbnail').src = job.thumbnail_url || 'https://via.placeholder.com/100';
|
| 943 |
|
| 944 |
document.getElementById('edit-modal').classList.remove('opacity-0', 'pointer-events-none');
|
|
@@ -1089,6 +1110,7 @@
|
|
| 1089 |
|
| 1090 |
jobsData = await response.json();
|
| 1091 |
renderJobsTable();
|
|
|
|
| 1092 |
|
| 1093 |
// Hide loading overlay
|
| 1094 |
document.getElementById('loading-overlay').classList.add('hidden');
|
|
@@ -1110,8 +1132,9 @@
|
|
| 1110 |
|
| 1111 |
const filteredJobs = jobsData.filter(job =>
|
| 1112 |
(job.customer_name && job.customer_name.toLowerCase().includes(searchTerm)) ||
|
| 1113 |
-
(job.
|
| 1114 |
-
(job.description && job.description.toLowerCase().includes(searchTerm))
|
|
|
|
| 1115 |
);
|
| 1116 |
|
| 1117 |
const tableBody = document.getElementById('jobs-table-body');
|
|
@@ -1181,7 +1204,7 @@
|
|
| 1181 |
let valB = b[column] || '';
|
| 1182 |
|
| 1183 |
// Handle numeric columns
|
| 1184 |
-
if (column === 'quantity' || column === '
|
| 1185 |
valA = parseFloat(valA) || 0;
|
| 1186 |
valB = parseFloat(valB) || 0;
|
| 1187 |
return isAsc ? valB - valA : valA - valB;
|
|
|
|
| 403 |
// Initialize date range picker
|
| 404 |
initDateRangePicker();
|
| 405 |
|
| 406 |
+
// Set current week as default and fetch week's jobs
|
| 407 |
+
const today = new Date();
|
| 408 |
+
const dayOfWeek = today.getDay();
|
| 409 |
+
const monday = new Date(today);
|
| 410 |
+
monday.setDate(today.getDate() - (dayOfWeek === 0 ? 6 : dayOfWeek - 1));
|
| 411 |
+
const friday = new Date(monday);
|
| 412 |
+
friday.setDate(monday.getDate() + 4);
|
| 413 |
+
|
| 414 |
setCurrentWeek();
|
| 415 |
+
const response = await fetch(`${API_BASE_URL}/jobs?status=completed&startDate=${moment(monday).format('YYYY-MM-DD')}&endDate=${moment(friday).format('YYYY-MM-DD')}`);
|
| 416 |
+
if (!response.ok) throw new Error('Failed to fetch jobs');
|
| 417 |
+
jobsData = await response.json();
|
| 418 |
|
| 419 |
// Render jobs tables
|
| 420 |
renderJobsTable();
|
|
|
|
| 608 |
|
| 609 |
jobsData = await response.json();
|
| 610 |
renderJobsTable();
|
| 611 |
+
initPieChart(); // Recompute pie chart with new date range
|
| 612 |
|
| 613 |
// Hide loading overlay
|
| 614 |
document.getElementById('loading-overlay').classList.add('hidden');
|
|
|
|
| 690 |
row.innerHTML = `
|
| 691 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 692 |
<div class="font-medium text-gray-900">${job.customer_name || 'N/A'}</div>
|
| 693 |
+
<div class="text-xs text-gray-500">${job.customer_ref || ''}</div>
|
| 694 |
</td>
|
| 695 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 696 |
+
<div class="text-gray-900">${job.id}</div>
|
| 697 |
</td>
|
| 698 |
<td class="px-6 py-4">
|
| 699 |
<div class="text-gray-900 max-w-xs truncate">${job.description || 'No description'}</div>
|
|
|
|
| 702 |
<div class="text-gray-900">${job.quantity || 0}</div>
|
| 703 |
</td>
|
| 704 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 705 |
+
<div class="text-gray-900">£${parseFloat(job.item_price || 0).toFixed(2)}</div>
|
| 706 |
</td>
|
| 707 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 708 |
+
<div class="font-medium text-gray-900">£${parseFloat(job.total_amount || 0).toFixed(2)}</div>
|
| 709 |
</td>
|
| 710 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 711 |
<img src="${job.thumbnail_url || 'https://via.placeholder.com/100'}" alt="Thumbnail" class="w-12 h-12 object-cover rounded cursor-pointer thumbnail" data-image="${job.image_url || 'https://via.placeholder.com/800'}">
|
|
|
|
| 740 |
row.innerHTML = `
|
| 741 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 742 |
<div class="font-medium text-gray-900">${job.customer_name || 'N/A'}</div>
|
| 743 |
+
<div class="text-xs text-gray-500">${job.customer_ref || ''}</div>
|
| 744 |
</td>
|
| 745 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 746 |
+
<div class="text-gray-900">${job.id}</div>
|
| 747 |
</td>
|
| 748 |
<td class="px-6 py-4">
|
| 749 |
<div class="text-gray-900 max-w-xs truncate">${job.description || 'No description'}</div>
|
|
|
|
| 841 |
|
| 842 |
// Initialize the pie chart
|
| 843 |
function initPieChart() {
|
| 844 |
+
// Clear any existing chart
|
| 845 |
+
const pieChartCanvas = document.getElementById('pieChart');
|
| 846 |
+
const existingChart = Chart.getChart(pieChartCanvas);
|
| 847 |
+
if (existingChart) {
|
| 848 |
+
existingChart.destroy();
|
| 849 |
+
}
|
| 850 |
+
|
| 851 |
const customerCounts = {};
|
| 852 |
jobsData.forEach(job => {
|
| 853 |
const customer = job.customer_name || 'Unknown';
|
| 854 |
customerCounts[customer] = (customerCounts[customer] || 0) + 1;
|
| 855 |
});
|
| 856 |
|
| 857 |
+
// Sort customers alphabetically
|
| 858 |
+
const customers = Object.keys(customerCounts).sort((a, b) => a.localeCompare(b));
|
| 859 |
+
const counts = customers.map(customer => customerCounts[customer]);
|
| 860 |
|
| 861 |
const colors = [
|
| 862 |
'rgba(59, 130, 246, 0.7)',
|
|
|
|
| 866 |
'rgba(220, 38, 38, 0.7)'
|
| 867 |
];
|
| 868 |
|
| 869 |
+
const ctx = pieChartCanvas.getContext('2d');
|
| 870 |
new Chart(ctx, {
|
| 871 |
type: 'pie',
|
| 872 |
data: {
|
|
|
|
| 952 |
const job = [...jobsData, ...invalidJobsData].find(j => j.job_id === jobId);
|
| 953 |
|
| 954 |
if (job) {
|
| 955 |
+
document.getElementById('edit-job-id').value = job.id;
|
| 956 |
+
document.getElementById('edit-job-id-display').value = job.id;
|
| 957 |
document.getElementById('edit-customer').value = job.customer_name || '';
|
| 958 |
document.getElementById('edit-description').value = job.description || '';
|
| 959 |
document.getElementById('edit-quantity').value = job.quantity || '';
|
| 960 |
+
document.getElementById('edit-price').value = job.item_price || '';
|
| 961 |
+
document.getElementById('edit-total').value = job.total_amount || 0;
|
| 962 |
+
document.getElementById('edit-end-date').value = job.end_time ? moment(job.end_time).format('YYYY-MM-DD') : '';
|
| 963 |
document.getElementById('edit-thumbnail').src = job.thumbnail_url || 'https://via.placeholder.com/100';
|
| 964 |
|
| 965 |
document.getElementById('edit-modal').classList.remove('opacity-0', 'pointer-events-none');
|
|
|
|
| 1110 |
|
| 1111 |
jobsData = await response.json();
|
| 1112 |
renderJobsTable();
|
| 1113 |
+
initPieChart(); // Recompute pie chart with new date range
|
| 1114 |
|
| 1115 |
// Hide loading overlay
|
| 1116 |
document.getElementById('loading-overlay').classList.add('hidden');
|
|
|
|
| 1132 |
|
| 1133 |
const filteredJobs = jobsData.filter(job =>
|
| 1134 |
(job.customer_name && job.customer_name.toLowerCase().includes(searchTerm)) ||
|
| 1135 |
+
(job.id && job.id.toString().includes(searchTerm)) ||
|
| 1136 |
+
(job.description && job.description.toLowerCase().includes(searchTerm)) ||
|
| 1137 |
+
(job.customer_ref && job.customer_ref.toLowerCase().includes(searchTerm))
|
| 1138 |
);
|
| 1139 |
|
| 1140 |
const tableBody = document.getElementById('jobs-table-body');
|
|
|
|
| 1204 |
let valB = b[column] || '';
|
| 1205 |
|
| 1206 |
// Handle numeric columns
|
| 1207 |
+
if (column === 'quantity' || column === 'item_price' || column === 'total_amount') {
|
| 1208 |
valA = parseFloat(valA) || 0;
|
| 1209 |
valB = parseFloat(valB) || 0;
|
| 1210 |
return isAsc ? valB - valA : valA - valB;
|