feat: dodaj DOCX akcije i napomene na racunima
Some checks failed
ERP CI/CD Pipeline / test (push) Has been cancelled
ERP CI/CD Pipeline / Deploy (server git pull + compose) (push) Has been cancelled

- dodaje DOCX preuzimanje za putni nalog, servisne zapise i racune na /putni-nalozi/racuni\n- uvodi modal za uredjivanje teksta napomene izvjestaja servisera\n- poboljsava update work order toka i upsert lokalnog stanja\n- ukljucuje TaskCalendar migraciju, dev watch stabilizaciju i deploy upute

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
mariomitte
2026-07-23 13:34:53 +02:00
parent 1055820741
commit ae6ae08fb1
9 changed files with 294 additions and 7 deletions

View File

@@ -1,22 +1,28 @@
import { useEffect, useMemo, useState } from 'preact/hooks';
import { useStore } from '@nanostores/preact';
import {
downloadWorkOrderDocx,
downloadWorkOrderPdf,
downloadWorkOrderInvoicesDocx,
downloadWorkOrderInvoicesPdf,
downloadWorkOrderServiceRecordsDocx,
downloadWorkOrderServiceRecordsPdf,
fetchWorkOrderAdditionalCostsTable,
fetchWorkOrderById,
fetchWorkOrderInvoices,
fetchWorkOrderTaskServiceContext,
updateTaskWorkHoursTable,
updateWorkOrder,
updateWorkOrderAdditionalCostsTable,
} from '../../stores/fleetDashboardStore';
import { $accessToken, $authReady, hydrateAuthFromStorage } from '../../stores/authStore';
import { fetchNotifications, connectNotifications } from '../../stores/notificationStore';
import { formatWorkOrderDisplayCode } from '../../lib/displayIds';
import { showToast } from '../../stores/toastStore';
import { resolveMediaUrl, useAuthenticatedMediaSources } from './WorkOrderImageCarousel';
import TaskWorkHoursTableModal from './TaskWorkHoursTableModal';
import WorkOrderAdditionalCostsModal from './WorkOrderAdditionalCostsModal';
import WorkOrderServiceNotesModal from './WorkOrderServiceNotesModal';
function readWorkOrderIdFromQuery() {
if (typeof window === 'undefined') {
@@ -77,6 +83,9 @@ export default function WorkOrderInvoicesPdfPage() {
const [additionalCostsTable, setAdditionalCostsTable] = useState({ data: { rows: [] }, total_for_payout: '0.00' });
const [editingAdditionalCosts, setEditingAdditionalCosts] = useState(false);
const [savingAdditionalCosts, setSavingAdditionalCosts] = useState(false);
const [editingServiceReportNote, setEditingServiceReportNote] = useState(false);
const [savingServiceReportNote, setSavingServiceReportNote] = useState(false);
const [serviceReportNoteError, setServiceReportNoteError] = useState('');
useEffect(() => {
hydrateAuthFromStorage();
@@ -207,6 +216,24 @@ export default function WorkOrderInvoicesPdfPage() {
}
};
const handleSaveServiceReportNote = async (notes) => {
if (!workOrderId) return;
setSavingServiceReportNote(true);
setServiceReportNoteError('');
try {
const updated = await updateWorkOrder(workOrderId, { notes: String(notes || '') });
setWorkOrder(updated);
setEditingServiceReportNote(false);
showToast('Napomena za izvještaj servisera je spremljena.', 'success');
} catch (err) {
const message = err?.message || 'Spremanje napomene nije uspjelo.';
setServiceReportNoteError(message);
showToast(message, 'error');
} finally {
setSavingServiceReportNote(false);
}
};
return (
<section className="mx-auto w-full max-w-5xl space-y-4 p-4 sm:p-6">
<div className="rounded-xl border border-border-hairline bg-canvas-elevated p-4">
@@ -225,6 +252,14 @@ export default function WorkOrderInvoicesPdfPage() {
>
Preuzmi PDF putnog naloga
</button>
<button
type="button"
onClick={() => downloadWorkOrderDocx(workOrderId)}
disabled={!workOrderId}
className="rounded-lg border border-border-hairline px-4 py-2 text-sm font-semibold text-text-main hover:bg-canvas-deep disabled:opacity-60"
>
Preuzmi DOCX putnog naloga
</button>
</div>
</div>
@@ -244,6 +279,14 @@ export default function WorkOrderInvoicesPdfPage() {
>
Uredi tablicu radnih sati
</button>
<button
type="button"
onClick={() => setEditingServiceReportNote(true)}
disabled={!workOrderId}
className="rounded-lg border border-border-hairline px-4 py-2 text-sm font-semibold text-text-main hover:bg-canvas-deep disabled:opacity-60"
>
Uredi tekst napomene
</button>
<button
type="button"
onClick={() => downloadWorkOrderServiceRecordsPdf(workOrderId)}
@@ -252,6 +295,14 @@ export default function WorkOrderInvoicesPdfPage() {
>
Preuzmi PDF servisnih zapisa
</button>
<button
type="button"
onClick={() => downloadWorkOrderServiceRecordsDocx(workOrderId)}
disabled={!workOrderId}
className="rounded-lg border border-border-hairline px-4 py-2 text-sm font-semibold text-text-main hover:bg-canvas-deep disabled:opacity-60"
>
Preuzmi DOCX servisnih zapisa
</button>
</div>
</div>
{loading && <p className="text-sm text-text-muted">Učitavanje task konteksta...</p>}
@@ -331,6 +382,14 @@ export default function WorkOrderInvoicesPdfPage() {
>
Preuzmi račune putnog naloga
</button>
<button
type="button"
onClick={() => downloadWorkOrderInvoicesDocx(workOrderId)}
disabled={!workOrderId}
className="rounded-lg border border-border-hairline px-4 py-2 text-sm font-semibold text-text-main hover:bg-canvas-deep disabled:opacity-60"
>
Preuzmi DOCX računa
</button>
</div>
</div>
{!loading && !error && (
@@ -385,6 +444,17 @@ export default function WorkOrderInvoicesPdfPage() {
onClose={() => setEditingAdditionalCosts(false)}
onSave={handleSaveAdditionalCostsTable}
/>
<WorkOrderServiceNotesModal
open={editingServiceReportNote}
workOrder={workOrder}
saving={savingServiceReportNote}
error={serviceReportNoteError}
onClose={() => {
setEditingServiceReportNote(false);
setServiceReportNoteError('');
}}
onSave={handleSaveServiceReportNote}
/>
</section>
);
}