diff --git a/ns_app/public/js/customer_quick_entry.js b/ns_app/public/js/customer_quick_entry.js index 1f9bf40..561d836 100644 --- a/ns_app/public/js/customer_quick_entry.js +++ b/ns_app/public/js/customer_quick_entry.js @@ -14,20 +14,20 @@ frappe.ui.form.make_quick_entry = function (doctype, after_insert) { let customer_name = ""; - // Pull value from current form route options - if (frappe.route_options?.name) { - customer_name = frappe.route_options.name; - } + // Pull value from current form route options + if (frappe.route_options?.name) { + customer_name = frappe.route_options.name; + } - // Fallback: get typed value from active link field - if (!customer_name) { + // Fallback: get typed value from active link field + if (!customer_name) { - const active = document.activeElement; + const active = document.activeElement; - if (active && active.value) { - customer_name = active.value; - } - } + if (active && active.value) { + customer_name = active.value; + } + } console.log("NS App: Captured customer name:", customer_name); @@ -43,6 +43,7 @@ frappe.ui.form.make_quick_entry = function (doctype, after_insert) { }; ns_app.customer.open_quick_entry = function (opts = {}) { + console.log("NS App: Custom Customer Quick Entry OPENED"); const d = new frappe.ui.Dialog({ @@ -50,96 +51,129 @@ ns_app.customer.open_quick_entry = function (opts = {}) { size: "large", fields: [ + // ───────── CUSTOMER ───────── - { fieldtype: "Section Break", label: "Customer" }, + { + fieldtype: "Section Break", + label: "Customer Information" + }, { fieldname: "customer_name", label: "Customer Name", fieldtype: "Data", reqd: 1, - default: opts.customer_name || "" + default: opts.customer_name || "", + description: "Enter the customer or company name" }, + { fieldname: "customer_type", label: "Customer Type", fieldtype: "Select", options: "Company\nIndividual", default: "Company", - reqd: 1 + reqd: 1, + description: "Select whether this customer is a company or individual" }, + { fieldname: "customer_group", label: "Customer Group", fieldtype: "Link", options: "Customer Group", default: "Commercial", - reqd: 1 + reqd: 1, + description: "Select the customer group" }, + { fieldname: "custom_send_via", - label: "Send Via", + label: "Preferred Delivery Method", fieldtype: "Select", - options: "mail\nemail\nfax" + options: "mail\nemail\nfax", + description: "Choose how documents should be sent to the customer" }, // ───────── CONTACT ───────── - { fieldtype: "Section Break", label: "Primary Contact" }, + { + fieldtype: "Section Break", + label: "Primary Contact" + }, { fieldname: "email_id", - label: "Email", + label: "Email Address", fieldtype: "Data", - options: "Email" + options: "Email", + description: "Enter the customer's email address" }, + { fieldname: "mobile_no", - label: "Mobile", + label: "Mobile Phone Number", fieldtype: "Data", - reqd: 1 + reqd: 1, + description: "Enter the customer's mobile phone number" }, // ───────── ADDRESS ───────── - { fieldtype: "Section Break", label: "Address" }, + { + fieldtype: "Section Break", + label: "Address Information" + }, { fieldname: "address_line1", label: "Address Line 1", fieldtype: "Data", - reqd: 1 + reqd: 1, + description: "Enter the street address" }, + { fieldname: "address_line2", label: "Address Line 2", - fieldtype: "Data" + fieldtype: "Data", + description: "Enter apartment, suite, or secondary address information" }, + { fieldname: "pincode", label: "ZIP Code", fieldtype: "Data", - reqd: 1 + reqd: 1, + description: "Enter the ZIP or postal code" }, + { fieldname: "city", label: "City", - fieldtype: "Data" + fieldtype: "Data", + description: "Enter the city" }, + { fieldname: "state", label: "State", - fieldtype: "Data" + fieldtype: "Data", + description: "Enter the state" }, + { fieldname: "country", label: "Country", fieldtype: "Link", options: "Country", - default: "United States" + default: "United States", + description: "Select the country" } ], primary_action_label: "Create Customer", + primary_action(values) { + console.log("NS App: Create Customer clicked", values); d.disable_primary_action(); @@ -147,10 +181,13 @@ ns_app.customer.open_quick_entry = function (opts = {}) { frappe.call({ method: "ns_app.api.customer.create_customer_full", args: values, + callback(r) { + console.log("NS App: Customer created", r.message); d.hide(); + frappe.show_alert({ message: "Customer created via NS App", indicator: "green" @@ -160,6 +197,7 @@ ns_app.customer.open_quick_entry = function (opts = {}) { opts.callback(r.message); } }, + always() { d.enable_primary_action(); } @@ -167,9 +205,47 @@ ns_app.customer.open_quick_entry = function (opts = {}) { } }); + d.show(); + + // Accessibility labels for screen readers + setTimeout(() => { + + d.fields.forEach(field => { + + const control = d.get_field(field.fieldname); + + if (!control || !control.$input) return; + + // ARIA label + control.$input.attr( + "aria-label", + field.label || field.fieldname + ); + + // Screen reader title + control.$input.attr( + "title", + field.label || field.fieldname + ); + + // Placeholder text + if (field.label) { + control.$input.attr( + "placeholder", + field.label + ); + } + }); + + console.log("NS App: Accessibility labels applied"); + + }, 300); + // ZIP auto-fill d.fields_dict.pincode.df.onchange = () => { + const zip = d.get_value("pincode"); + if (!zip || zip.length < 5) return; console.log("NS App: ZIP lookup", zip); @@ -177,9 +253,11 @@ ns_app.customer.open_quick_entry = function (opts = {}) { fetch(`https://api.zippopotam.us/us/${zip}`) .then(r => r.ok ? r.json() : null) .then(data => { + if (!data || !data.places?.length) return; const p = data.places[0]; + d.set_value("city", p["place name"]); d.set_value("state", p["state"]); d.set_value("country", data.country); @@ -189,29 +267,11 @@ ns_app.customer.open_quick_entry = function (opts = {}) { .catch(() => {}); }; - d.show(); - - let autoPayField = d.get_field("custom_auto_pay_enabled"); - - // Initial state - d.set_df_property( - "custom_auto_pay_id", - "hidden", - !d.get_value("custom_auto_pay_enabled") - ); - - // When checkbox changes - autoPayField.$input.on("change", () => { - let isChecked = d.get_value("custom_auto_pay_enabled"); - - d.set_df_property("custom_auto_pay_id", "hidden", !isChecked); - }); - - - // Prevent Enter from submitting unless primary button is focused d.$wrapper.on("keydown", "input, select, textarea", function (e) { + if (e.key === "Enter") { + const active = document.activeElement; // Allow Enter ONLY if primary action button is focused @@ -230,10 +290,10 @@ ns_app.customer.open_quick_entry = function (opts = {}) { .filter(":visible:not([disabled])"); const index = fields.index(this); + if (index > -1 && index + 1 < fields.length) { fields.eq(index + 1).focus(); } } }); - }; \ No newline at end of file