feat: dodaj ishodište i PDF račune za putni nalog
Dodano je origin_location polje kroz backend model, serializer, admin i UI modal za kreiranje/uređivanje putnog naloga (default: Zagreb). Računi putnog naloga sada prihvaćaju slike i PDF datoteke, uz backend validaciju formata, podršku za serving PDF-a i prilagodbu preview prikaza. Za greške uploada računa dodan je error toast kako bi poruke validacije bile vidljive korisniku odmah u sučelju. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -32,6 +32,7 @@ export default function WorkOrderDetailModal({ open, workOrder, onClose, onSubmi
|
||||
servicer_vehicle_start_mileage: '',
|
||||
servicer_vehicle_end_mileage: '',
|
||||
servicer_vehicle_fuel_cost: '',
|
||||
origin_location: 'Zagreb',
|
||||
location: '',
|
||||
travel_start_at: '',
|
||||
travel_end_at: '',
|
||||
@@ -92,11 +93,12 @@ export default function WorkOrderDetailModal({ open, workOrder, onClose, onSubmi
|
||||
if (!open || !workOrder) return;
|
||||
setIsEditing(false);
|
||||
setForm({
|
||||
has_travel_order: !!(workOrder.travel_start_at || workOrder.travel_end_at || workOrder.location || workOrder.start_mileage != null || workOrder.end_mileage != null),
|
||||
has_travel_order: !!(workOrder.travel_start_at || workOrder.travel_end_at || workOrder.origin_location || workOrder.location || workOrder.start_mileage != null || workOrder.end_mileage != null),
|
||||
display_code: workOrder.display_code || '',
|
||||
status: workOrder.status || 'open',
|
||||
start_mileage: String(workOrder.start_mileage ?? ''),
|
||||
end_mileage: workOrder.end_mileage == null ? '' : String(workOrder.end_mileage),
|
||||
origin_location: workOrder.origin_location || 'Zagreb',
|
||||
location: workOrder.location || '',
|
||||
travel_start_at: workOrder.travel_start_at ? String(workOrder.travel_start_at).slice(0, 16) : '',
|
||||
travel_end_at: workOrder.travel_end_at ? String(workOrder.travel_end_at).slice(0, 16) : '',
|
||||
@@ -332,6 +334,7 @@ export default function WorkOrderDetailModal({ open, workOrder, onClose, onSubmi
|
||||
servicer_vehicle_start_mileage: form.servicer_vehicle_start_mileage === '' ? null : Number(form.servicer_vehicle_start_mileage),
|
||||
servicer_vehicle_end_mileage: form.servicer_vehicle_end_mileage === '' ? null : Number(form.servicer_vehicle_end_mileage),
|
||||
servicer_vehicle_fuel_cost: form.servicer_vehicle_fuel_cost === '' ? null : Number(form.servicer_vehicle_fuel_cost),
|
||||
origin_location: form.origin_location.trim() || 'Zagreb',
|
||||
location: form.location.trim(),
|
||||
travel_start_at: travelStart ? travelStart.toISOString() : null,
|
||||
travel_end_at: travelEnd ? travelEnd.toISOString() : null,
|
||||
@@ -599,6 +602,16 @@ export default function WorkOrderDetailModal({ open, workOrder, onClose, onSubmi
|
||||
<div className="rounded-xl border border-border-hairline bg-canvas-base p-3">
|
||||
<h4 className="mb-2 text-sm font-semibold text-text-main">Putni podaci</h4>
|
||||
<div className="grid gap-4 sm:grid-cols-2">
|
||||
<label className="sm:col-span-2 flex flex-col gap-1 text-sm">
|
||||
<span className="font-medium text-text-main">Lokacija ishodišta</span>
|
||||
<input
|
||||
type="text"
|
||||
value={form.origin_location}
|
||||
onInput={(event) => setForm({ ...form, origin_location: event.currentTarget.value })}
|
||||
className="rounded-lg border border-border-hairline bg-canvas-base px-3 py-2 text-text-main disabled:bg-canvas-deep"
|
||||
disabled={!isEditing}
|
||||
/>
|
||||
</label>
|
||||
<label className="sm:col-span-2 flex flex-col gap-1 text-sm">
|
||||
<span className="font-medium text-text-main">Lokacija odredišta {form.has_travel_order ? '*' : ''}</span>
|
||||
<div className="flex gap-2">
|
||||
@@ -658,6 +671,7 @@ export default function WorkOrderDetailModal({ open, workOrder, onClose, onSubmi
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
has_travel_order: checked,
|
||||
origin_location: checked ? (prev.origin_location || 'Zagreb') : 'Zagreb',
|
||||
location: checked ? prev.location : '',
|
||||
travel_start_at: checked ? prev.travel_start_at : '',
|
||||
travel_end_at: checked ? prev.travel_end_at : '',
|
||||
@@ -980,10 +994,10 @@ export default function WorkOrderDetailModal({ open, workOrder, onClose, onSubmi
|
||||
/>
|
||||
</label>
|
||||
<label className="flex flex-col gap-1 text-sm sm:col-span-2">
|
||||
<span className="font-medium text-text-main">slika_računa</span>
|
||||
<span className="font-medium text-text-main">slika_računa / pdf_računa</span>
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
accept="image/*,.pdf,application/pdf"
|
||||
onChange={(event) => {
|
||||
const file = event.currentTarget.files && event.currentTarget.files[0] ? event.currentTarget.files[0] : null;
|
||||
setInvoiceForm((prev) => ({ ...prev, imageFile: file }));
|
||||
|
||||
Reference in New Issue
Block a user