feat: WorkOrderPhoto izolacija, upload modal i SN stupac u tablici putnih naloga
- Dodan WorkOrderPhoto model (FK na WorkOrder, odvojen od VehicleServicePhoto) - Migracija 0022_workorderphoto - WorkOrderViewSet.images action refaktoriran: GET/POST koristi WorkOrderPhoto - WorkOrderPhotoSerializer dodan u serializers.py - WorkOrderPhotoInline dodan u admin.py - Novi WorkOrderPhotoUpload.jsx modal s podrskom za onBack prop i z-[60] - WorkOrderDetailModal: gumb Dodaj fotografije u editMode, photoUploadOpen state, ispravljen onSuccess callback (map na URL stringove), reset pri zatvaranju - FleetDashboardShell: stupac SN u tablici putnih naloga (craneInfo.crane_serial_number) - fleetDashboardStore: uklonjen dupli toast iz uploadWorkOrderPhoto - Dodan test test_work_order_images_endpoint.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import WorkOrderDetailModal from './WorkOrderDetailModal';
|
||||
import SyncLogPanel from './SyncLogPanel';
|
||||
import ServiceRecordForm from '../fleet/ServiceRecordForm';
|
||||
import ServicePhotoUpload from '../fleet/ServicePhotoUpload';
|
||||
import WorkOrderPhotoUpload from '../fleet/WorkOrderPhotoUpload';
|
||||
import ServiceRecordDetailModal from '../fleet/ServiceRecordDetailModal';
|
||||
import ServiceRecordCreateButton from '../fleet/ServiceRecordCreateButton';
|
||||
import ClientsSection from '../crm/ClientsSection';
|
||||
@@ -93,6 +94,7 @@ export default function FleetDashboardShell({ initialSection = 'dashboard', page
|
||||
const [selectedServiceRecord, setSelectedServiceRecord] = useState(null);
|
||||
// photoUpload: { open: bool, serviceRecordId: string|null }
|
||||
const [photoUpload, setPhotoUpload] = useState({ open: false, serviceRecordId: null });
|
||||
const [workOrderPhotoUpload, setWorkOrderPhotoUpload] = useState({ open: false, workOrderId: null });
|
||||
const loading = useStore($dashboardLoading);
|
||||
const error = useStore($dashboardError);
|
||||
const stats = useStore($dashboardStats);
|
||||
@@ -492,6 +494,7 @@ export default function FleetDashboardShell({ initialSection = 'dashboard', page
|
||||
const workOrderColumns = [
|
||||
{ key: 'code', label: 'Putni nalog', className: 'px-4 py-3' },
|
||||
{ key: 'vehicle', label: 'Dizalica', className: 'px-4 py-3' },
|
||||
{ key: 'serialNumber', label: 'SN', className: 'px-4 py-3' },
|
||||
{ key: 'createdAt', label: 'Kreirano', className: 'px-4 py-3' },
|
||||
{ key: 'status', label: 'Status', className: 'px-4 py-3' },
|
||||
{ key: 'creator', label: 'Creator', className: 'px-4 py-3' },
|
||||
@@ -756,6 +759,9 @@ export default function FleetDashboardShell({ initialSection = 'dashboard', page
|
||||
>
|
||||
{[workOrder.craneInfo?.make, workOrder.craneInfo?.model].filter(Boolean).join(' ') || workOrder.craneLabel || workOrder.craneInfo?.registration_number || `#${workOrder.crane || workOrder.vehicle}`}
|
||||
</td>
|
||||
<td className="px-4 py-3 font-mono text-xs text-text-muted">
|
||||
{workOrder.craneInfo?.crane_serial_number || '-'}
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
{formatDate(workOrder.date)}
|
||||
</td>
|
||||
@@ -773,15 +779,10 @@ export default function FleetDashboardShell({ initialSection = 'dashboard', page
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const related = serviceRecords.find((record) => String(record.vehicle) === String(workOrder.vehicle));
|
||||
if (!related) {
|
||||
showToast('Nema servisnog zapisa za ovaj putni nalog. Kreirajte servisni zapis prvo.', 'warning');
|
||||
return;
|
||||
}
|
||||
setPhotoUpload({ open: true, serviceRecordId: related.id });
|
||||
setWorkOrderPhotoUpload({ open: true, workOrderId: workOrder.id });
|
||||
}}
|
||||
className="rounded px-2 py-1 text-xs font-medium text-text-muted hover:bg-canvas-deep hover:text-text-main"
|
||||
title="Upload fotografija"
|
||||
title="Upload fotografija putnog naloga"
|
||||
>
|
||||
📷
|
||||
</button>
|
||||
@@ -913,7 +914,7 @@ export default function FleetDashboardShell({ initialSection = 'dashboard', page
|
||||
{JSON.stringify(group, null, 2)}
|
||||
</pre> */}
|
||||
<td className="px-4 py-3">{formatDate(record.service_date)}</td>
|
||||
<td className="px-4 py-3">{record.crane_serial_number || record.vehicle_registration || '-'}</td>
|
||||
<td className="px-4 py-3">{record.crane_serial_number || '-'}</td>
|
||||
<td className="max-w-md truncate px-4 py-3" title={record.description || ''}>
|
||||
{record.description || '-'}
|
||||
</td>
|
||||
@@ -1094,6 +1095,13 @@ export default function FleetDashboardShell({ initialSection = 'dashboard', page
|
||||
onSuccess={() => fetchFleetDashboardData({ silent: true })}
|
||||
/>
|
||||
|
||||
<WorkOrderPhotoUpload
|
||||
open={workOrderPhotoUpload.open}
|
||||
workOrderId={workOrderPhotoUpload.workOrderId}
|
||||
onClose={() => setWorkOrderPhotoUpload({ open: false, workOrderId: null })}
|
||||
onSuccess={() => fetchFleetDashboardData({ silent: true })}
|
||||
/>
|
||||
|
||||
<ServiceRecordDetailModal
|
||||
open={!!selectedServiceRecord}
|
||||
serviceRecord={selectedServiceRecord}
|
||||
|
||||
Reference in New Issue
Block a user