/** @odoo-module * * LaundryQuickCreatePartner — POS-only quick create. * * UX rules: * - Phone is REQUIRED and the FIRST input (autofocused on mount). * - Name is OPTIONAL. If empty on confirm, the backend * `res.partner.laundry_quick_create` falls back to using the phone * value as the partner name (single source of truth — JS does not * duplicate that fallback). * - Street is fully optional. * * All user-facing strings come from `_t()` getters so the active * language switches the popup text cleanly. No mixed-language labels. */ import { Component, useState, useRef, onMounted } from "@odoo/owl"; import { Dialog } from "@web/core/dialog/dialog"; import { _t } from "@web/core/l10n/translation"; export class LaundryQuickCreatePartner extends Component { static components = { Dialog }; static template = "laundry_management.QuickCreatePartner"; static props = { getPayload: { type: Function }, close: { type: Function }, }; setup() { this.state = useState({ phone: "", name: "", street: "", phoneError: false, }); this.phoneRef = useRef("phoneInput"); onMounted(() => { if (this.phoneRef.el) this.phoneRef.el.focus(); }); } // ── Translatable labels (computed each render so language change // propagates without a remount) ───────────────────────────────── get title() { return _t("Quick Create Customer"); } get labelPhone() { return _t("Phone / Mobile"); } get labelName() { return _t("Name"); } get labelStreet() { return _t("Street"); } get labelCreate() { return _t("Create"); } get labelCancel() { return _t("Cancel"); } get nameOptionalHint() { return _t("(optional — phone is used if empty)"); } get placeholderPhone() { return _t("e.g. +966 50 123 4567"); } get placeholderName() { return _t("Customer name"); } get placeholderStreet() { return _t("Building, street, district…"); } get errorPhoneRequired() { return _t("Phone is required."); } confirm() { const phone = (this.state.phone || "").trim(); if (!phone) { this.state.phoneError = true; return; } this.props.getPayload({ phone, name: (this.state.name || "").trim(), // empty → backend falls back to phone street: (this.state.street || "").trim(), }); this.props.close(); } cancel() { this.props.close(); } }