diff --git a/src/components/Controls/AutoComplete.vue b/src/components/Controls/AutoComplete.vue index a478fe2ce..948bf38e9 100644 --- a/src/components/Controls/AutoComplete.vue +++ b/src/components/Controls/AutoComplete.vue @@ -107,6 +107,7 @@ export default { return { showQuickView: false, linkValue: '', + focInp: false, isLoading: false, suggestions: [], highlightedIndex: -1, @@ -187,6 +188,15 @@ export default { const route = getFormRoute(this.linkSchemaName, name); await routeTo(route); }, + async focusInputTag() { + this.focInp = true; + if (this.linkValue) { + return; + } + + await this.$nextTick(); + this.$refs.input.focus(); + }, setLinkValue(value) { this.linkValue = value; }, @@ -282,6 +292,14 @@ export default { return; } + if (!e.target.value || this.focInp) { + e.target.value = null; + this.focInp = false; + this.toggleDropdown(false); + + return; + } + this.toggleDropdown(true); this.updateSuggestions(e.target.value); }, diff --git a/src/components/Controls/Base.vue b/src/components/Controls/Base.vue index 461a40141..db08b00b0 100644 --- a/src/components/Controls/Base.vue +++ b/src/components/Controls/Base.vue @@ -21,6 +21,7 @@ @blur="onBlur" @focus="(e) => !isReadOnly && $emit('focus', e)" @input="(e) => !isReadOnly && $emit('input', e)" + @keydown.enter="setLoyaltyPoints" /> @@ -49,6 +50,7 @@ export default defineComponent({ border: { type: Boolean, default: false }, size: { type: String, default: 'large' }, placeholder: String, + focusInput: Boolean, showLabel: { type: Boolean, default: false }, containerStyles: { type: Object, default: () => ({}) }, textRight: { @@ -64,6 +66,15 @@ export default defineComponent({ default: null, }, }, + async created() { + if (this.focusInput) { + await this.$nextTick(); + (this.$refs.input as HTMLInputElement).focus(); + if (this.value == 0) { + this.triggerChange(''); + } + } + }, emits: ['focus', 'input', 'change'], computed: { doc(): Doc | undefined { @@ -191,6 +202,12 @@ export default defineComponent({ }, }, methods: { + setLoyaltyPoints() { + const inputElement = this.$refs.input as HTMLInputElement; + if (inputElement && inputElement?.value) { + this.$emit('change', inputElement.value); + } + }, onBlur(e: FocusEvent) { const target = e.target; if (!(target instanceof HTMLInputElement)) { @@ -227,7 +244,7 @@ export default defineComponent({ triggerChange(value: unknown): void { value = this.parse(value); - if (value === '') { + if (value === '' || value == 0) { value = null; } diff --git a/src/components/Controls/Link.vue b/src/components/Controls/Link.vue index fe48501ce..f5889d431 100644 --- a/src/components/Controls/Link.vue +++ b/src/components/Controls/Link.vue @@ -26,6 +26,14 @@ export default { this.setLinkValue(); } }, + props: { + focusInput: Boolean, + }, + async created() { + if (this.focusInput) { + this.focusInputTag(); + } + }, methods: { async setLinkValue(newValue, isInput) { if (isInput) { diff --git a/src/components/POS/types.ts b/src/components/POS/types.ts index 0a127ca00..ea31a0f46 100644 --- a/src/components/POS/types.ts +++ b/src/components/POS/types.ts @@ -8,15 +8,18 @@ export type ItemSerialNumbers = { [item: string]: string }; export type DiscountType = 'percent' | 'amount'; -export type ModalName = - | 'Keyboard' - | 'Payment' - | 'ShiftClose' - | 'LoyaltyProgram' - | 'SavedInvoice' - | 'Alert' - | 'CouponCode' - | 'PriceList'; +export const modalNames = [ + 'Keyboard', + 'Payment', + 'ShiftClose', + 'LoyaltyProgram', + 'SavedInvoice', + 'Alert', + 'CouponCode', + 'PriceList', +] as const; + +export type ModalName = typeof modalNames[number]; export type PosEmits = | 'addItem' diff --git a/src/components/ShortcutsHelper.vue b/src/components/ShortcutsHelper.vue index 2af6490d5..f50667da9 100644 --- a/src/components/ShortcutsHelper.vue +++ b/src/components/ShortcutsHelper.vue @@ -191,6 +191,49 @@ export default defineComponent({ }, ], }, + { + label: t`Point of Sale`, + description: t`Applicable when POS is open`, + collapsed: false, + shortcuts: [ + { + shortcut: [ShortcutKey.shift, 'V'], + description: t`Toggle between Grid and List view`, + }, + { + shortcut: [ShortcutKey.shift, 'S'], + description: t`Open Sales Invoice List`, + }, + { + shortcut: [ShortcutKey.shift, 'L'], + description: t`Set Loyalty Program`, + }, + { + shortcut: [ShortcutKey.shift, 'C'], + description: t`Set Coupon Code`, + }, + { + shortcut: [ShortcutKey.shift, 'P'], + description: t`Set Price List`, + }, + { + shortcut: [ShortcutKey.pmod, ShortcutKey.shift, 'H'], + description: t`Open Saved or Submitted Invoice List.`, + }, + { + shortcut: [ShortcutKey.pmod, ShortcutKey.shift, 'S'], + description: t`If any entry form is open, save the details. Otherwise, save the invoice.`, + }, + { + shortcut: [ShortcutKey.pmod, ShortcutKey.shift, 'P'], + description: t`Create Payment.`, + }, + { + shortcut: [ShortcutKey.pmod, ShortcutKey.shift, ShortcutKey.delete], + description: t`If any entry form is open, your entry will be canceled. Otherwise the selected items will be removed.`, + }, + ], + }, ]; }, }); diff --git a/src/pages/POS/CouponCodeModal.vue b/src/pages/POS/CouponCodeModal.vue index d7785d278..f2f67f3b4 100644 --- a/src/pages/POS/CouponCodeModal.vue +++ b/src/pages/POS/CouponCodeModal.vue @@ -63,6 +63,7 @@ :show-label="true" :border="true" :value="couponCode" + :focus-input="true" :df="coupons.fieldMap.coupons" @change="updateCouponCode" /> @@ -161,15 +162,18 @@ export default defineComponent({ }, }, methods: { - updateCouponCode(value: string) { - (this.validationError = false), (this.couponCode = value); - }, - async setCouponCode() { + async updateCouponCode(value: string | Event) { try { - if (!this.couponCode) { - throw new Error(t`Must be select a coupon code`); + if (!value) { + return; + } + this.validationError = false; + + if ((value as Event).type === 'keydown') { + value = ((value as Event).target as HTMLInputElement).value; } + this.couponCode = value as string; const appliedCouponCodes = this.fyo.doc.getNewDoc( ModelNameEnum.AppliedCouponCodes ); @@ -183,8 +187,6 @@ export default defineComponent({ await this.sinvDoc.append('coupons', { coupons: this.couponCode }); this.$emit('applyPricingRule'); - this.$emit('toggleModal', 'CouponCode'); - this.couponCode = ''; this.validationError = false; } catch (error) { @@ -196,6 +198,9 @@ export default defineComponent({ }); } }, + setCouponCode() { + this.$emit('toggleModal', 'CouponCode'); + }, async removeAppliedCoupon(coupon: AppliedCouponCodes) { this.sinvDoc?.items?.map((item: InvoiceItem) => { item.itemDiscountAmount = this.fyo.pesa(0); diff --git a/src/pages/POS/LoyaltyProgramModal.vue b/src/pages/POS/LoyaltyProgramModal.vue index a913168fd..a2934fe11 100644 --- a/src/pages/POS/LoyaltyProgramModal.vue +++ b/src/pages/POS/LoyaltyProgramModal.vue @@ -20,13 +20,15 @@
{{ loyaltyPoints }}
- @@ -52,7 +54,7 @@