import { Automat } from 'automat'; export function createEmptyLineitem(line = {}) { return { key: line.key ?? `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, name: line.name ?? null, sku: line.sku ?? null, amount: line.amount ?? null, pu: line.pu ?? null, unit: line.unit ?? null, netprice: line.netprice ?? null, taxrate: line.taxrate ?? null, }; } export const initialDelivery = { id: null, deliveryId: null, date: null, deliveryEntity: null, partyId: null, externalNumber: null, external_number: null, number: null, type: null, lines: [], lineitems: [], notes: [], attachments: [], files: [], }; export const initialState = { deliveryEntities: [], ...initialDelivery, }; export const deliveryEditorAutomat = new Automat(initialState, { setId(id) { deliveryEditorAutomat.setState({ id, deliveryId: id }); }, setDeliveryEntities(deliveryEntities) { deliveryEditorAutomat.setState({ deliveryEntities: deliveryEntities ?? [] }); }, setDelivery(delivery = {}) { const rawLines = delivery.lines ?? delivery.lineitems ?? []; const lines = Array.isArray(rawLines) ? rawLines : []; const partyId = delivery.partyId ?? delivery.deliveryEntity ?? null; const extNum = delivery.externalNumber ?? delivery.external_number ?? null; const id = delivery.id ?? delivery.deliveryId ?? null; const notes = Array.isArray(delivery.notes) ? delivery.notes : delivery.notes ? [delivery.notes] : []; const rawAttachments = delivery.attachments ?? delivery.files ?? []; const attachments = Array.isArray(rawAttachments) ? rawAttachments : []; deliveryEditorAutomat.setState({ ...initialDelivery, ...delivery, id, deliveryId: id, partyId, deliveryEntity: partyId, externalNumber: extNum, external_number: extNum, lines, lineitems: lines, notes, attachments, files: attachments, }); }, setDate(date) { deliveryEditorAutomat.setState({ date }); }, setDeliveryEntity(entityId) { deliveryEditorAutomat.setState({ deliveryEntity: entityId, partyId: entityId }); }, setPartyId(partyId) { deliveryEditorAutomat.setState({ deliveryEntity: partyId, partyId }); }, setExternalNumber(externalNumber) { deliveryEditorAutomat.setState({ externalNumber, external_number: externalNumber, }); }, setNumber(number) { deliveryEditorAutomat.setState({ number }); }, setType(type) { deliveryEditorAutomat.setState({ type }); }, setLines(lines) { const cleanLines = lines ?? []; deliveryEditorAutomat.setState({ lines: cleanLines, lineitems: cleanLines }); }, setLineitems(lines) { const cleanLines = lines ?? []; deliveryEditorAutomat.setState({ lines: cleanLines, lineitems: cleanLines }); }, setNotes(notes) { const cleanNotes = Array.isArray(notes) ? notes : notes ? [notes] : []; deliveryEditorAutomat.setState({ notes: cleanNotes }); }, addLineitem(line = {}) { const item = createEmptyLineitem(line); const nextLines = [...(deliveryEditorAutomat.state.lines ?? []), item]; deliveryEditorAutomat.setState({ lines: nextLines, lineitems: nextLines }); }, addLine(line = {}) { deliveryEditorAutomat.actions.addLineitem(line); }, updateLineitem(payload) { const { index, key, ...fields } = payload || {}; const currentLines = deliveryEditorAutomat.state.lines ?? []; let targetIndex = typeof index === 'number' && !Number.isNaN(index) ? index : -1; if (targetIndex === -1 && key != null) { targetIndex = currentLines.findIndex((l) => l.key === key); } if (targetIndex >= 0 && targetIndex < currentLines.length) { const nextLines = [...currentLines]; nextLines[targetIndex] = { ...nextLines[targetIndex], ...fields, }; deliveryEditorAutomat.setState({ lines: nextLines, lineitems: nextLines }); } }, updateLine(payload) { deliveryEditorAutomat.actions.updateLineitem(payload); }, removeLineitem(payload) { const currentLines = deliveryEditorAutomat.state.lines ?? []; let index = typeof payload === 'number' && !Number.isNaN(payload) ? payload : -1; if (index === -1 && payload != null) { const key = typeof payload === 'string' ? payload : payload?.key; if (key != null) { index = currentLines.findIndex((l) => l.key === key); } } if (index >= 0 && index < currentLines.length) { const nextLines = currentLines.filter((_, i) => i !== index); deliveryEditorAutomat.setState({ lines: nextLines, lineitems: nextLines }); } }, removeLine(payload) { deliveryEditorAutomat.actions.removeLineitem(payload); }, addAttachment(attachment) { const id = attachment.id ?? `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; const item = { ...attachment, id }; const next = [...(deliveryEditorAutomat.state.attachments ?? []), item]; deliveryEditorAutomat.setState({ attachments: next, files: next }); }, setAttachments(attachments) { const clean = Array.isArray(attachments) ? attachments : []; deliveryEditorAutomat.setState({ attachments: clean, files: clean }); }, updateAttachment(payload) { const { id, ...fields } = payload || {}; const current = deliveryEditorAutomat.state.attachments ?? []; const idx = current.findIndex((a) => a.id === id); if (idx !== -1) { const next = [...current]; next[idx] = { ...next[idx], ...fields }; deliveryEditorAutomat.setState({ attachments: next, files: next }); } }, removeAttachment(idOrIndex) { const current = deliveryEditorAutomat.state.attachments ?? []; let next; if (typeof idOrIndex === 'number') { next = current.filter((_, idx) => idx !== idOrIndex); } else { const id = typeof idOrIndex === 'string' ? idOrIndex : idOrIndex?.id; next = current.filter((a) => a.id !== id); } deliveryEditorAutomat.setState({ attachments: next, files: next }); }, resetDelivery() { deliveryEditorAutomat.setState({ ...initialDelivery, }); }, resetDeliveryEditor() { deliveryEditorAutomat.setState({ ...initialState, }); }, }); export const { setId, setDeliveryEntities, setDelivery, setDate, setDeliveryEntity, setPartyId, setExternalNumber, setNumber, setType, setLines, setLineitems, setNotes, addLineitem, addLine, updateLineitem, updateLine, removeLineitem, removeLine, addAttachment, setAttachments, updateAttachment, removeAttachment, resetDelivery, resetDeliveryEditor, } = deliveryEditorAutomat.actions; // Selectors export const selectDeliveryId = (state = deliveryEditorAutomat.state) => state.deliveryId ?? state.id; export const selectDeliveryEntities = (state = deliveryEditorAutomat.state) => state.deliveryEntities; export const selectDeliveryDate = (state = deliveryEditorAutomat.state) => state.date; export const selectDeliveryEntity = (state = deliveryEditorAutomat.state) => state.deliveryEntity ?? state.partyId; export const selectDeliveryExternalNumber = (state = deliveryEditorAutomat.state) => state.externalNumber ?? state.external_number; export const selectDeliveryNumber = (state = deliveryEditorAutomat.state) => state.number; export const selectDeliveryType = (state = deliveryEditorAutomat.state) => state.type; export const selectDeliveryLineitems = (state = deliveryEditorAutomat.state) => state.lines ?? state.lineitems; export const selectDeliveryNotes = (state = deliveryEditorAutomat.state) => state.notes; export const selectDeliveryAttachments = (state = deliveryEditorAutomat.state) => state.attachments; export default deliveryEditorAutomat;