staff update
This commit is contained in:
@@ -1040,7 +1040,9 @@ tr:hover td{ background:#fbfdff; }
|
||||
</div>
|
||||
|
||||
<!-- Create Installment Button -->
|
||||
<button class="btn" id="openCreateModalBtn">+ Create New Installment</button>
|
||||
@can('account.create_order')
|
||||
<button class="btn" id="openCreateModalBtn">+ Create New Order</button>
|
||||
@endcan
|
||||
|
||||
<!-- Date Filters -->
|
||||
<div class="combined-filters-row">
|
||||
@@ -1250,7 +1252,7 @@ tr:hover td{ background:#fbfdff; }
|
||||
|
||||
<div class="create-actions">
|
||||
<button type="button" class="btn ghost" id="cancelCreateModal">Cancel</button>
|
||||
<button type="submit" class="btn">Create Installment</button>
|
||||
<button type="submit" class="btn">Create Order</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -1304,7 +1306,9 @@ tr:hover td{ background:#fbfdff; }
|
||||
|
||||
<div style="display:flex; justify-content: flex-end; gap:12px; margin-top:16px;">
|
||||
<button type="button" class="btn ghost" onclick="closeEntryDetailsModal()">Close</button>
|
||||
@can('account.add_installment')
|
||||
<button type="button" class="btn" id="addInstallmentFromDetails">+ Add New Installment</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1388,7 +1392,9 @@ tr:hover td{ background:#fbfdff; }
|
||||
|
||||
<div style="display:flex; justify-content:flex-end; gap:12px; margin-top:14px;">
|
||||
<button type="button" class="btn ghost" onclick="closeInstallmentModal()">Cancel</button>
|
||||
<button type="submit" class="btn">Create Installment</button>
|
||||
@can('account.add_installment')
|
||||
<button type="submit" class="btn">Create Installment2</button>
|
||||
@endcan
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -1559,6 +1565,14 @@ tr:hover td{ background:#fbfdff; }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.CAN_EDIT_ORDER = @json(auth()->user()->can('account.edit_order'));
|
||||
window.CAN_DELETE_ORDER = @json(auth()->user()->can('account.delete_order'));
|
||||
window.CAN_TOGGLE_PAYMENT = @json(auth()->user()->can('account.toggle_payment_status'));
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
/* ---------- Helpers & state ---------- */
|
||||
|
||||
@@ -1642,7 +1656,12 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
/* ---------- UI binding ---------- */
|
||||
function bindUI(){
|
||||
// Create Order Modal
|
||||
document.getElementById('openCreateModalBtn').addEventListener('click', openCreateOrderModal);
|
||||
//document.getElementById('openCreateModalBtn').addEventListener('click', openCreateOrderModal);
|
||||
const createBtn = document.getElementById('openCreateModalBtn');
|
||||
if (createBtn) {
|
||||
createBtn.addEventListener('click', openCreateOrderModal);
|
||||
}
|
||||
|
||||
document.getElementById('closeCreateModal').addEventListener('click', closeCreateOrderModal);
|
||||
document.getElementById('cancelCreateModal').addEventListener('click', closeCreateOrderModal);
|
||||
document.getElementById('createOrderInlineForm').addEventListener('submit', submitCreateOrderInline);
|
||||
@@ -1667,11 +1686,22 @@ function bindUI(){
|
||||
clearStatusFilters();
|
||||
});
|
||||
document.getElementById('searchBtn').addEventListener('click', handleSearch);
|
||||
document.getElementById('addInstallmentFromDetails').addEventListener('click', () => {
|
||||
if(!currentEntry) return;
|
||||
openInstallmentModal(currentEntry.entry_no, currentEntry.description, currentEntry.region, currentEntry.pending_amount);
|
||||
closeEntryDetailsModal();
|
||||
});
|
||||
|
||||
const addInstallBtn = document.getElementById('addInstallmentFromDetails');
|
||||
|
||||
if (addInstallBtn) {
|
||||
addInstallBtn.addEventListener('click', () => {
|
||||
if (!currentEntry) return;
|
||||
openInstallmentModal(
|
||||
currentEntry.entry_no,
|
||||
currentEntry.description,
|
||||
currentEntry.region,
|
||||
currentEntry.pending_amount
|
||||
);
|
||||
closeEntryDetailsModal();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Installment form submit
|
||||
document.getElementById('installmentForm').addEventListener('submit', submitInstallment);
|
||||
@@ -2120,103 +2150,108 @@ function renderPaymentTable(list){
|
||||
body.innerHTML = '';
|
||||
|
||||
if (!list || list.length === 0) {
|
||||
body.innerHTML = '<tr><td colspan="9" class="empty-state">No entries found</td></tr>';
|
||||
return;
|
||||
body.innerHTML = '<tr><td colspan="9" class="empty-state">No entries found</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const startIndex = (currentPage - 1) * entriesPerPage;
|
||||
const endIndex = startIndex + entriesPerPage;
|
||||
const paginatedEntries = list.slice(startIndex, endIndex);
|
||||
|
||||
|
||||
paginatedEntries.forEach(entry => {
|
||||
const tr = document.createElement('tr');
|
||||
|
||||
// फक्त unpaid/pending वरच actions दिसतील
|
||||
const canActions = ['unpaid', 'pending'].includes(
|
||||
String(entry.payment_status).toLowerCase()
|
||||
);
|
||||
|
||||
tr.innerHTML = `
|
||||
<td>${escapeHtml(entry.entry_no)}</td>
|
||||
<td>${escapeHtml(entry.entry_date)}</td>
|
||||
<td>${escapeHtml(entry.description)}</td>
|
||||
|
||||
<!-- CLICKABLE ORDER QUANTITY -->
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="entry-link"
|
||||
onclick="openEntryOrdersModal('${escapeHtml(entry.entry_no)}')"
|
||||
>
|
||||
${entry.order_quantity ?? '-'}
|
||||
</button>
|
||||
</td>
|
||||
const tr = document.createElement('tr');
|
||||
|
||||
<td>${escapeHtml(entry.region)}</td>
|
||||
<td>
|
||||
<button class="toggle-switch-btn"
|
||||
data-entry="${escapeHtml(entry.entry_no)}"
|
||||
data-pos="${Number(entry.toggle_pos) || 0}"
|
||||
aria-label="Toggle payment state"></button>
|
||||
</td>
|
||||
<td>${formatCurrency(entry.amount)}</td>
|
||||
<td>
|
||||
<span class="status-badge ${statusClass(entry.payment_status)}">
|
||||
${capitalize(entry.payment_status)}
|
||||
</span>
|
||||
</td>
|
||||
const canActions = ['unpaid','pending'].includes(entry.payment_status.toLowerCase());
|
||||
|
||||
<!-- इथे तुझा action-btns block paste कर -->
|
||||
<td>
|
||||
<div class="action-btns">
|
||||
${canActions ? `
|
||||
<button class="action-btn edit-btn" data-entry="${escapeHtml(entry.entry_no)}" title="Edit entry">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.3333 1.99996C11.5084 1.82485 11.7163 1.686 11.945 1.59124C12.1737 1.49649 12.4189 1.44775 12.6667 1.44775C12.9144 1.44775 13.1596 1.49649 13.3883 1.59124C13.617 1.686 13.8249 1.82485 14 1.99996C14.1751 2.17507 14.314 2.38297 14.4087 2.61167C14.5035 2.84037 14.5522 3.08556 14.5522 3.33329C14.5522 3.58102 14.5035 3.82621 14.4087 4.05491C14.314 4.28361 14.1751 4.49151 14 4.66663L4.99998 13.6666L1.33331 14.6666L2.33331 11L11.3333 1.99996Z"
|
||||
stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="action-btn delete-btn" data-entry="${escapeHtml(entry.entry_no)}" title="Delete entry">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2 4H3.33333H14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.33331 4V2.66667C5.33331 2.31305 5.47379 1.97391 5.72384 1.72386C5.97389 1.47381 6.31303 1.33333 6.66665 1.33333H9.33331C9.68693 1.33333 10.0261 1.47381 10.2761 1.72386C10.5262 1.97391 10.6666 2.31305 10.6666 2.66667V4M12.6666 4V13.3333C12.6666 13.6869 12.5262 14.0261 12.2761 14.2761C12.0261 14.5262 11.6869 14.6667 11.3333 14.6667H4.66665C4.31303 14.6667 3.97389 14.5262 3.72384 14.2761C3.47379 14.0261 3.33331 13.6869 3.33331 13.3333V4H12.6666Z"
|
||||
stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
` : ''}
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
// permissions passed from Blade
|
||||
const canEdit = window.CAN_EDIT_ORDER;
|
||||
const canDelete = window.CAN_DELETE_ORDER;
|
||||
const canToggle = window.CAN_TOGGLE_PAYMENT;
|
||||
|
||||
tr.innerHTML = `
|
||||
<td>${escapeHtml(entry.entry_no)}</td>
|
||||
<td>${escapeHtml(entry.entry_date)}</td>
|
||||
<td>${escapeHtml(entry.description)}</td>
|
||||
|
||||
body.appendChild(tr);
|
||||
const btn = tr.querySelector('.toggle-switch-btn');
|
||||
btn.dataset.entry = entry.entry_no; // entry_no from API
|
||||
btn.dataset.pos = entry.toggle_pos ?? 0;
|
||||
setToggleVisual(btn, Number(btn.dataset.pos));
|
||||
btn.addEventListener('click', () => cycleToggle(btn));
|
||||
<td>
|
||||
<button type="button" class="entry-link"
|
||||
onclick="openEntryOrdersModal('${escapeHtml(entry.entry_no)}')">
|
||||
${entry.order_quantity ?? '-'}
|
||||
</button>
|
||||
</td>
|
||||
|
||||
<td>${escapeHtml(entry.region)}</td>
|
||||
|
||||
const actions = tr.querySelector('.action-btns');
|
||||
if (actions) {
|
||||
if (entry.payment_status.toLowerCase() === 'paid') {
|
||||
actions.style.display = 'none';
|
||||
} else {
|
||||
actions.style.display = 'flex';
|
||||
}
|
||||
<td>
|
||||
<button class="toggle-switch-btn"
|
||||
data-entry="${entry.entry_no}"
|
||||
data-pos="${entry.toggle_pos ?? 0}"
|
||||
${!canToggle ? 'disabled class="toggle-switch-btn disabled-toggle"' : ''}
|
||||
></button>
|
||||
</td>
|
||||
|
||||
<td>${formatCurrency(entry.amount)}</td>
|
||||
|
||||
<td>
|
||||
<span class="status-badge ${statusClass(entry.payment_status)}">
|
||||
${capitalize(entry.payment_status)}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="action-btns">
|
||||
|
||||
${(canActions && canEdit) ? `
|
||||
<button class="action-btn edit-btn"
|
||||
data-entry="${entry.entry_no}"
|
||||
title="Edit entry">
|
||||
✎
|
||||
</button>
|
||||
` : ''}
|
||||
|
||||
${(canActions && canDelete) ? `
|
||||
<button class="action-btn delete-btn"
|
||||
data-entry="${entry.entry_no}"
|
||||
title="Delete entry">
|
||||
🗑
|
||||
</button>
|
||||
` : ''}
|
||||
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
|
||||
/* Toggle Button Logic */
|
||||
const toggleBtn = tr.querySelector('.toggle-switch-btn');
|
||||
setToggleVisual(toggleBtn, Number(toggleBtn.dataset.pos));
|
||||
|
||||
if (canToggle) {
|
||||
toggleBtn.addEventListener("click", () => cycleToggle(toggleBtn));
|
||||
} else {
|
||||
toggleBtn.style.opacity = "0.5";
|
||||
toggleBtn.style.cursor = "not-allowed";
|
||||
}
|
||||
|
||||
/* EDIT binding */
|
||||
if (canActions && canEdit) {
|
||||
const editBtn = tr.querySelector(".edit-btn");
|
||||
editBtn?.addEventListener("click", () => openEditModal(entry));
|
||||
}
|
||||
|
||||
/* DELETE binding */
|
||||
if (canActions && canDelete) {
|
||||
const delBtn = tr.querySelector(".delete-btn");
|
||||
delBtn?.addEventListener("click", () => deleteEntry(entry.entry_no));
|
||||
}
|
||||
|
||||
body.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (canActions) {
|
||||
const editBtn = tr.querySelector('.edit-btn');
|
||||
editBtn.addEventListener('click', () => openEditModal(entry));
|
||||
|
||||
const deleteBtn = tr.querySelector('.delete-btn');
|
||||
deleteBtn.addEventListener('click', () => deleteEntry(entry.entry_no));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function cycleToggle(btn) {
|
||||
// वर्तमान position घेऊन पुढचा स्टेट कॅल्क्युलेट करा
|
||||
let pos = parseInt(btn.dataset.pos || '0', 10); // 0 = unpaid, 1 = pending, 2 = paid
|
||||
@@ -2838,30 +2873,30 @@ async function openEntryDetailsModal(entryNo) {
|
||||
<td>${formatCurrency(ins.amount)}</td>
|
||||
|
||||
<td>
|
||||
<select class="installment-status-dropdown"
|
||||
data-id="${ins.id}"
|
||||
onchange="updateInstallmentStatus(${ins.id}, this.value)">
|
||||
<option value="Pending" ${ins.status === 'Pending' ? 'selected' : ''}
|
||||
style="color: #f59e0b; font-weight: 500; padding: 10px;">
|
||||
⏳ Pending
|
||||
</option>
|
||||
<option value="Loading" ${ins.status === 'Loading' ? 'selected' : ''}
|
||||
style="color: #3b82f6; font-weight: 500; padding: 10px;">
|
||||
📦 Loading
|
||||
</option>
|
||||
<option value="Packed" ${ins.status === 'Packed' ? 'selected' : ''}
|
||||
style="color: #8b5cf6; font-weight: 500; padding: 10px;">
|
||||
📦 Packed
|
||||
</option>
|
||||
<option value="Dispatched" ${ins.status === 'Dispatched' ? 'selected' : ''}
|
||||
style="color: #10b981; font-weight: 500; padding: 10px;">
|
||||
🚚 Dispatched
|
||||
</option>
|
||||
<option value="Delivered" ${ins.status === 'Delivered' ? 'selected' : ''}
|
||||
style="color: #0c6b2e; font-weight: 500; padding: 10px;">
|
||||
✅ Delivered
|
||||
</option>
|
||||
</select>
|
||||
<select class="installment-status-dropdown"
|
||||
data-id="${ins.id}"
|
||||
onchange="updateInstallmentStatus(${ins.id}, this.value)">
|
||||
<option value="Pending" ${ins.status === 'Pending' ? 'selected' : ''}
|
||||
style="color: #f59e0b; font-weight: 500; padding: 10px;">
|
||||
⏳ Pending
|
||||
</option>
|
||||
<option value="Loading" ${ins.status === 'Loading' ? 'selected' : ''}
|
||||
style="color: #3b82f6; font-weight: 500; padding: 10px;">
|
||||
📦 Loading
|
||||
</option>
|
||||
<option value="Packed" ${ins.status === 'Packed' ? 'selected' : ''}
|
||||
style="color: #8b5cf6; font-weight: 500; padding: 10px;">
|
||||
📦 Packed
|
||||
</option>
|
||||
<option value="Dispatched" ${ins.status === 'Dispatched' ? 'selected' : ''}
|
||||
style="color: #10b981; font-weight: 500; padding: 10px;">
|
||||
🚚 Dispatched
|
||||
</option>
|
||||
<option value="Delivered" ${ins.status === 'Delivered' ? 'selected' : ''}
|
||||
style="color: #0c6b2e; font-weight: 500; padding: 10px;">
|
||||
✅ Delivered
|
||||
</option>
|
||||
</select>
|
||||
|
||||
</td>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user