diff --git a/apps/ops/src/layouts/MainLayout.vue b/apps/ops/src/layouts/MainLayout.vue
index 0cb0c82..3b91b75 100644
--- a/apps/ops/src/layouts/MainLayout.vue
+++ b/apps/ops/src/layouts/MainLayout.vue
@@ -45,7 +45,7 @@
+ @keydown.enter.prevent="doSearch" @keydown.escape="closeMobileSearch">
@@ -69,7 +69,8 @@
@@ -189,12 +190,28 @@ async function runSearch (q) {
searchLoading.value = false
}
-function doSearch () {
+function moveHighlight (dir) {
+ if (!searchResults.value.length) return
+ searchDropdownOpen.value = true
+ highlightIdx.value = Math.max(-1, Math.min(searchResults.value.length - 1, highlightIdx.value + dir))
+}
+
+async function doSearch () {
+ const q = searchQuery.value?.trim()
+ if (!q || q.length < 2) return
+
+ // Always cancel debounce and run search immediately on Enter
+ if (!searchResults.value.length) {
+ clearTimeout(searchTimer)
+ searchLoading.value = true
+ await runSearch(q)
+ }
+
if (searchResults.value.length) {
const idx = highlightIdx.value >= 0 ? highlightIdx.value : 0
goToResult(searchResults.value[idx])
- } else if (searchQuery.value.trim()) {
- router.push({ path: '/clients', query: { q: searchQuery.value.trim() } })
+ } else {
+ router.push({ path: '/clients', query: { q } })
clearSearch()
}
}
diff --git a/apps/ops/src/pages/ClientDetailPage.vue b/apps/ops/src/pages/ClientDetailPage.vue
index 5741243..73503df 100644
--- a/apps/ops/src/pages/ClientDetailPage.vue
+++ b/apps/ops/src/pages/ClientDetailPage.vue
@@ -264,7 +264,7 @@
- Tickets ({{ tickets.length }})
+ Tickets ({{ tickets.length }}{{ !ticketsExpanded ? '+' : '' }})
{{ openTicketCount }} ouverts
@@ -316,17 +316,31 @@
-
-
-
+ props.row.priority = v.value">
+
+ {{ props.row.priority }}
+
+
- {{ props.row.status }}
+ props.row.status = v.value">
+
+ {{ props.row.status }}
+
+
+
+
+
@@ -470,7 +484,7 @@ import { listDocs, getDoc } from 'src/api/erp'
import { authFetch } from 'src/api/auth'
import { BASE_URL } from 'src/config/erpnext'
import { formatDate, formatMoney, staffColor, staffInitials } from 'src/composables/useFormatters'
-import { locStatusClass, ticketStatusClass, invStatusClass, deviceColorClass } from 'src/composables/useStatusClasses'
+import { locStatusClass, ticketStatusClass, invStatusClass, deviceColorClass, priorityClass } from 'src/composables/useStatusClasses'
import { useDetailModal } from 'src/composables/useDetailModal'
import { useSubscriptionGroups, isRebate, subMainLabel, sectionTotal, annualPrice } from 'src/composables/useSubscriptionGroups'
import { useSubscriptionActions } from 'src/composables/useSubscriptionActions'
@@ -591,6 +605,7 @@ async function loadCustomer (id) {
comments.value = []
contact.value = null
modalOpen.value = false
+ ticketsExpanded.value = false
invoicesExpanded.value = false
paymentsExpanded.value = false
@@ -635,7 +650,7 @@ async function loadCustomer (id) {
listDocs('Issue', {
filters: custFilter,
fields: ['name', 'subject', 'status', 'priority', 'opening_date', 'service_location', 'legacy_ticket_id', 'is_important', 'assigned_staff', 'opened_by_staff', 'issue_type'],
- limit: 200, orderBy: 'opening_date desc',
+ limit: 10, orderBy: 'is_important desc, opening_date desc',
}),
listDocs('Sales Invoice', {
filters: custFilter,
@@ -677,12 +692,29 @@ async function loadCustomer (id) {
}
}
-// ── Lazy-load more invoices/payments on demand ──
+// ── Lazy-load more tickets/invoices/payments on demand ──
+const ticketsExpanded = ref(false)
const invoicesExpanded = ref(false)
const paymentsExpanded = ref(false)
+const loadingMoreTickets = ref(false)
const loadingMoreInvoices = ref(false)
const loadingMorePayments = ref(false)
+async function loadAllTickets () {
+ if (ticketsExpanded.value || !customer.value) return
+ loadingMoreTickets.value = true
+ try {
+ const tix = await listDocs('Issue', {
+ filters: { customer: customer.value.name },
+ fields: ['name', 'subject', 'status', 'priority', 'opening_date', 'service_location', 'legacy_ticket_id', 'is_important', 'assigned_staff', 'opened_by_staff', 'issue_type'],
+ limit: 500, orderBy: 'is_important desc, opening_date desc',
+ })
+ tickets.value = tix
+ ticketsExpanded.value = true
+ } catch {}
+ loadingMoreTickets.value = false
+}
+
async function loadAllInvoices () {
if (invoicesExpanded.value || !customer.value) return
loadingMoreInvoices.value = true