localization: add Arabic translation for quick quantity shortcut and update relevant components to emit selected row events

This commit is contained in:
Osama Muhammed
2025-09-04 21:29:21 +03:00
parent cf91784bc1
commit 4e021f8a68
7 changed files with 202 additions and 6 deletions
@@ -5,7 +5,7 @@
@click="isExapanded = !isExapanded"
/>
<div class="relative">
<div class="relative" @click="emitSelectedRow">
<Link
class="pt-2"
:df="{
@@ -27,7 +27,7 @@
</p>
</div>
<div class="flex items-center">
<div class="flex items-center" @click="emitSelectedRow">
<Int
:df="{
fieldname: 'quantity',
@@ -101,7 +101,7 @@
<div></div>
<template v-if="isExapanded">
<div class="px-4 pt-6 col-span-1">
<div class="px-4 pt-6 col-span-1" @click="emitSelectedRow">
<Int
v-if="isUOMConversionEnabled"
:df="{
@@ -287,7 +287,7 @@ export default defineComponent({
props: {
row: { type: SalesInvoiceItem, required: true },
},
emits: ['runSinvFormulas', 'applyPricingRule'],
emits: ['runSinvFormulas', 'applyPricingRule', 'selectedRow'],
setup() {
return {
isDiscountingEnabled: inject('isDiscountingEnabled') as boolean,
@@ -344,6 +344,9 @@ export default defineComponent({
},
methods: {
emitSelectedRow() {
this.$emit('selectedRow', this.row);
},
adjustQuantity(change: number) {
let currentQuantity = this.row.quantity ?? 1;
let newQuantity = currentQuantity + change;
@@ -55,6 +55,7 @@
:row="(row as SalesInvoiceItem)"
@run-sinv-formulas="runSinvFormulas"
@apply-pricing-rule="$emit('applyPricingRule')"
@selected-row="selectedItemRow"
/>
</Row>
</div>
@@ -94,7 +95,7 @@ export default defineComponent({
isExapanded: false,
};
},
emits: ['applyPricingRule'],
emits: ['applyPricingRule', 'selectedRow'],
computed: {
ratio() {
return [0.1, 0.9, 0.8, 0.8, 0.8, 0.8, 0.2];
@@ -158,6 +159,9 @@ export default defineComponent({
async runSinvFormulas() {
await this.sinvDoc.runFormulas();
},
selectedItemRow(row: SalesInvoiceItem) {
this.$emit('selectedRow', row);
},
isNumeric,
},
});
+4
View File
@@ -216,6 +216,10 @@ export default defineComponent({
shortcut: [ShortcutKey.shift, 'P'],
description: t`Set Price List`,
},
{
shortcut: ['Q', '0-9'],
description: t`Hold Q and type digits to set selected item quantity`,
},
{
shortcut: [ShortcutKey.pmod, ShortcutKey.shift, 'H'],
description: t`Open Saved or Submitted Invoice List.`,
+2
View File
@@ -180,6 +180,7 @@
<SelectedItemTable
@apply-pricing-rule="emitEvent('applyPricingRule')"
@selected-row="(row) => $emit('selectedRow', row)"
/>
</div>
@@ -503,6 +504,7 @@ export default defineComponent({
'setTransferClearanceDate',
'saveAndContinue',
'handlePaymentAction',
'selectedRow',
],
data() {
return {
+3
View File
@@ -499,6 +499,7 @@ export default defineComponent({
'selectedReturnInvoice',
'setTransferClearanceDate',
'saveAndContinue',
'selectedRow',
],
data() {
return {
@@ -524,6 +525,8 @@ export default defineComponent({
selectedRow(row: SalesInvoiceItem, field: string) {
this.selectedItemRow = row;
this.selectedItemField = field;
// Bubble up to POS to allow keyboard shortcuts to target this row
this.$emit('selectedRow', row);
},
getItem,
},
+179
View File
@@ -63,6 +63,7 @@
@set-transfer-clearance-date="setTransferClearanceDate"
@save-and-continue="handleSaveAndContinue"
@handle-payment-action="handlePaymentAction"
@selected-row="setQuickQtySelectedRow"
/>
<ModernPOS
v-else
@@ -113,6 +114,7 @@
@selected-return-invoice="selectedReturnInvoice"
@save-and-continue="handleSaveAndContinue"
@set-transfer-clearance-date="setTransferClearanceDate"
@selected-row="setQuickQtySelectedRow"
/>
</div>
</template>
@@ -240,6 +242,13 @@ export default defineComponent({
itemQtyMap: {} as ItemQtyMap,
coupons: {} as AppliedCouponCodes,
itemSerialNumbers: {} as ItemSerialNumbers,
// Quick Quantity via holding 'Q'
quickQtyActive: false,
quickQtyBuffer: '' as string,
quickQtyRow: null as SalesInvoiceItem | null,
quickQtyKeyDownHandler: null as ((e: KeyboardEvent) => void) | null,
quickQtyKeyUpHandler: null as ((e: KeyboardEvent) => void) | null,
};
},
computed: {
@@ -281,6 +290,7 @@ export default defineComponent({
this.setSinvDoc();
this.setDefaultCustomer();
this.setShortcuts();
this.addQuickQtyListeners();
await this.setItemQtyMap();
await this.setItems();
@@ -288,8 +298,177 @@ export default defineComponent({
deactivated() {
this.shortcuts?.delete(COMPONENT_NAME);
toggleSidebar(true);
this.removeQuickQtyListeners();
},
methods: {
setQuickQtySelectedRow(row: SalesInvoiceItem) {
this.quickQtyRow = row;
},
addQuickQtyListeners() {
this.quickQtyKeyDownHandler = (e: KeyboardEvent) =>
this.onQuickQtyKeyDown(e);
this.quickQtyKeyUpHandler = (e: KeyboardEvent) => this.onQuickQtyKeyUp(e);
window.addEventListener(
'keydown',
this.quickQtyKeyDownHandler as EventListener
);
window.addEventListener(
'keyup',
this.quickQtyKeyUpHandler as EventListener
);
},
removeQuickQtyListeners() {
if (this.quickQtyKeyDownHandler) {
window.removeEventListener(
'keydown',
this.quickQtyKeyDownHandler as EventListener
);
this.quickQtyKeyDownHandler = null;
}
if (this.quickQtyKeyUpHandler) {
window.removeEventListener(
'keyup',
this.quickQtyKeyUpHandler as EventListener
);
this.quickQtyKeyUpHandler = null;
}
},
hasAnyOpenModal(): boolean {
return (
this.openAlertModal ||
this.openPaymentModal ||
this.openKeyboardModal ||
this.openPriceListModal ||
this.openItemEnquiryModal ||
this.openCouponCodeModal ||
this.openShiftCloseModal ||
this.openSavedInvoiceModal ||
this.openLoyaltyProgramModal ||
this.openAppliedCouponsModal ||
this.openReturnSalesInvoiceModal
);
},
onQuickQtyKeyDown(e: KeyboardEvent) {
// Ignore if focus is in an input/contentEditable without modifiers
const notMods = !(e.altKey || e.metaKey || e.ctrlKey);
const target = e.target as HTMLElement | null;
if (
target &&
notMods &&
((target instanceof HTMLInputElement && target.type !== 'button') ||
target instanceof HTMLTextAreaElement ||
target.isContentEditable)
) {
return;
}
// Only active on POS page with no modal open
if (this.hasAnyOpenModal()) {
return;
}
if (e.code === 'KeyQ' && !this.quickQtyActive) {
this.quickQtyActive = true;
this.quickQtyBuffer = '';
return;
}
if (!this.quickQtyActive) {
return;
}
// While holding Q, collect digits; support both main digits and numpad
if (/^Digit[0-9]$/.test(e.code)) {
this.quickQtyBuffer += e.code.replace('Digit', '');
e.preventDefault();
return;
}
if (/^Numpad[0-9]$/.test(e.code)) {
this.quickQtyBuffer += e.code.replace('Numpad', '');
e.preventDefault();
return;
}
if (e.code === 'Backspace') {
this.quickQtyBuffer = this.quickQtyBuffer.slice(0, -1);
e.preventDefault();
return;
}
},
async onQuickQtyKeyUp(e: KeyboardEvent) {
if (e.code !== 'KeyQ' || !this.quickQtyActive) {
return;
}
this.quickQtyActive = false;
const buffer = this.quickQtyBuffer;
this.quickQtyBuffer = '';
if (!buffer || !buffer.length) {
return;
}
const qty = Number(buffer);
if (!Number.isFinite(qty)) {
return;
}
// Determine target row: prefer explicitly selected row; else fallback to last non-free item
let row: SalesInvoiceItem | null = this.quickQtyRow;
if (!row || !(this.sinvDoc.items || []).includes(row)) {
const items = (this.sinvDoc.items || []).filter((r) => !r.isFreeItem);
row = items.length
? (items[items.length - 1] as SalesInvoiceItem)
: null;
}
if (!row) {
return;
}
// Validate and recalculate similar to keyboard modal quantity change
const prevQty = row.quantity ?? 1;
if (!row.isReturn && qty <= 0) {
showToast({
type: 'error',
message: t`Quantity must be greater than zero.`,
duration: 'short',
});
return;
}
try {
await row.set('quantity', qty);
const existingItems =
(this.sinvDoc.items || []).filter(
(invoiceItem: InvoiceItem) =>
invoiceItem.item === row!.item && !invoiceItem.isFreeItem
) || [];
await validateQty(
this.sinvDoc as SalesInvoice,
row,
existingItems as unknown as InvoiceItem[]
);
} catch (error) {
await row.set('quantity', prevQty);
showToast({
type: 'error',
message: t`${error as string}`,
duration: 'short',
});
return;
}
if (!row.isFreeItem) {
await this.applyPricingRule();
await this.sinvDoc.runFormulas();
}
},
async setCustomer(value: string) {
if (!value) {
this.sinvDoc.party = '';
+2 -1
View File
@@ -1098,4 +1098,5 @@ Transfer,تحويل,
"Qty","الكمية",
"Held","معلّقة",
"Grid View","عرض الشبكة",
"Buy","شراء",
"Buy","شراء",
"Hold Q and type digits to set selected item quantity","استمر بالضغط على Q ثم اكتب الأرقام لتعيين كمية الصنف المحدد",
Can't render this file because it contains an unexpected character in line 148 and column 22.