quill editor

This commit is contained in:
Andreas Knuth 2026-01-22 10:37:58 -06:00
parent e61907e557
commit 209292a61a
3 changed files with 70 additions and 4 deletions

View File

@ -318,8 +318,11 @@ function addQuoteItem(item = null) {
</div>
<div class="col-span-5">
<label class="block text-xs font-medium text-gray-700 mb-1">Description</label>
<textarea data-item="${itemId}" data-field="description" rows="2"
class="item-input w-full px-2 py-2 border border-gray-300 rounded-md text-sm focus:ring-blue-500 focus:border-blue-500">${item ? item.description : ''}</textarea>
<div data-item="${itemId}" data-field="description"
class="item-description-editor border border-gray-300 rounded-md bg-white"
style="min-height: 80px;">
</div>
<input type="hidden" data-item="${itemId}" data-field="description-html" class="item-description-html">
</div>
<div class="col-span-2">
<label class="block text-xs font-medium text-gray-700 mb-1">Rate</label>
@ -349,6 +352,35 @@ function addQuoteItem(item = null) {
itemsDiv.appendChild(itemDiv);
// Initialize Quill editor for description
const editorDiv = itemDiv.querySelector('.item-description-editor');
const hiddenInput = itemDiv.querySelector('.item-description-html');
const quill = new Quill(editorDiv, {
theme: 'snow',
modules: {
toolbar: [
['bold', 'italic', 'underline'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
['clean']
]
}
});
// Load existing content if editing
if (item && item.description) {
quill.root.innerHTML = item.description;
}
// Save HTML content on change
quill.on('text-change', () => {
hiddenInput.value = quill.root.innerHTML;
updateTotals();
});
// Store quill instance for later access
editorDiv.quillInstance = quill;
// Get references to inputs for auto-calculation
const qtyInput = itemDiv.querySelector('[data-field="quantity"]');
const rateInput = itemDiv.querySelector('[data-field="rate"]');
@ -442,9 +474,14 @@ function getQuoteItems() {
const itemDivs = document.querySelectorAll('#quote-items > div');
itemDivs.forEach(div => {
const descEditor = div.querySelector('.item-description-editor');
const descriptionHTML = descEditor && descEditor.quillInstance
? descEditor.quillInstance.root.innerHTML
: '';
const item = {
quantity: div.querySelector('[data-field="quantity"]').value,
description: div.querySelector('[data-field="description"]').value,
description: descriptionHTML,
rate: div.querySelector('[data-field="rate"]').value,
amount: div.querySelector('[data-field="amount"]').value,
is_tbd: div.querySelector('[data-field="is_tbd"]').checked

View File

@ -5,6 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quote Management System - Bay Area Affiliates</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
<style>
.modal {
display: none;

View File

@ -731,6 +731,33 @@ function generateQuoteHTML(quote) {
text-align: left;
}
/* Quill editor formatting in PDF */
.items-table td.description ul,
.items-table td.description ol {
margin: 5px 0;
padding-left: 20px;
}
.items-table td.description li {
margin: 2px 0;
}
.items-table td.description p {
margin: 5px 0;
}
.items-table td.description strong {
font-weight: bold;
}
.items-table td.description em {
font-style: italic;
}
.items-table td.description u {
text-decoration: underline;
}
.items-table td.rate,
.items-table td.amount {
text-align: right;