diff --git a/public/js/modals/invoice-modal.js b/public/js/modals/invoice-modal.js index cbde3b6..45bda8b 100644 --- a/public/js/modals/invoice-modal.js +++ b/public/js/modals/invoice-modal.js @@ -53,18 +53,45 @@ function updateRecurringChildUi(invoice = null) { let childBadge = document.getElementById('invoice-recurring-child-badge'); let childNote = document.getElementById('invoice-recurring-child-note'); - // First-time setup: wrap/change the visible label text + // Find or create a stable label span if (!labelText) { - const textNode = Array.from(recurringWrapper.childNodes).find(node => - node.nodeType === Node.TEXT_NODE && node.textContent.trim().includes('Recurring') + // Prefer an existing span/text element containing "Recurring" + const existingTextElement = Array.from(recurringWrapper.children).find(el => + el !== recurringCb && + el.id !== 'invoice-recurring-child-badge' && + el.textContent && + el.textContent.trim() === 'Recurring' ); - if (textNode) { - const span = document.createElement('span'); - span.id = 'invoice-recurring-label-text'; - span.textContent = 'Recurring'; - recurringWrapper.replaceChild(span, textNode); - labelText = span; + if (existingTextElement) { + existingTextElement.id = 'invoice-recurring-label-text'; + labelText = existingTextElement; + } else { + // Fallback: try to replace a raw text node + const textNode = Array.from(recurringWrapper.childNodes).find(node => + node.nodeType === Node.TEXT_NODE && + node.textContent.trim().includes('Recurring') + ); + + if (textNode) { + const span = document.createElement('span'); + span.id = 'invoice-recurring-label-text'; + span.textContent = 'Recurring'; + recurringWrapper.replaceChild(span, textNode); + labelText = span; + } else { + // Final fallback: create label text after checkbox + labelText = document.createElement('span'); + labelText.id = 'invoice-recurring-label-text'; + labelText.textContent = 'Recurring'; + labelText.className = 'ml-2'; + + if (recurringCb.nextSibling) { + recurringWrapper.insertBefore(labelText, recurringCb.nextSibling); + } else { + recurringWrapper.appendChild(labelText); + } + } } } @@ -80,7 +107,9 @@ function updateRecurringChildUi(invoice = null) { childNote = document.createElement('div'); childNote.id = 'invoice-recurring-child-note'; childNote.className = 'mt-1 ml-8 text-xs text-gray-500 hidden'; - recurringWrapper.parentElement.appendChild(childNote); + + const parent = recurringWrapper.parentElement || recurringWrapper; + parent.appendChild(childNote); } const isChild = !!invoice?.recurring_source_id; @@ -89,11 +118,14 @@ function updateRecurringChildUi(invoice = null) { labelText.textContent = 'Recurring child invoice'; childBadge.classList.remove('hidden'); - const sourceNumber = invoice.recurring_source_invoice_number - || invoice.source_invoice_number - || invoice.recurring_source_id; + const sourceNumber = + invoice.recurring_source_invoice_number || + invoice.source_invoice_number || + invoice.recurring_source_id; + + childNote.textContent = + `This invoice was generated from recurring invoice #${sourceNumber} and will not create further recurring invoices.`; - childNote.textContent = `This invoice was generated from recurring invoice #${sourceNumber} and will not create further recurring invoices.`; childNote.classList.remove('hidden'); } else { labelText.textContent = 'Recurring';