create_form #38
|
|
@ -55,7 +55,7 @@ const fetchConfig = async () => {
|
|||
formData[field.key] = [];
|
||||
} else if (field.type === "phone_country") {
|
||||
formData[field.key] = "";
|
||||
phoneParts[field.key] = { code: "", number: "" };
|
||||
phoneParts[field.key] = { code: "", number: "", flag: "" };
|
||||
} else {
|
||||
formData[field.key] = "";
|
||||
}
|
||||
|
|
@ -305,13 +305,6 @@ const onPhoneInput = (key, event) => {
|
|||
formatErrors[key] = false;
|
||||
};
|
||||
|
||||
const onPhoneCountryCodeChange = (key, code) => {
|
||||
if (!phoneParts[key]) return;
|
||||
phoneParts[key].code = code;
|
||||
formData[key] = code + phoneParts[key].number;
|
||||
stepErrors[key] = false;
|
||||
};
|
||||
|
||||
const onPhoneCountryNumberInput = (key, event) => {
|
||||
if (!phoneParts[key]) return;
|
||||
const cleaned = event.target.value.replace(/\D/g, "");
|
||||
|
|
@ -321,8 +314,56 @@ const onPhoneCountryNumberInput = (key, event) => {
|
|||
stepErrors[key] = false;
|
||||
};
|
||||
|
||||
const getPhoneCountryDisplay = (key) => {
|
||||
if (phoneCountrySearchText[key] !== undefined && phoneCountrySearchText[key] !== null) {
|
||||
return phoneCountrySearchText[key];
|
||||
}
|
||||
if (!phoneParts[key] || !phoneParts[key].code) return "";
|
||||
return phoneParts[key].flag
|
||||
? `${phoneParts[key].code}`
|
||||
: phoneParts[key].code;
|
||||
};
|
||||
|
||||
const filteredPhoneCountries = (field, key) => {
|
||||
const text = (phoneCountrySearchText[key] || "").toLowerCase().trim();
|
||||
const list = suggestionsCache.value[field.source] || [];
|
||||
if (!text) return list;
|
||||
return list.filter(
|
||||
item => item.label.toLowerCase().includes(text) || item.dial_code.includes(text)
|
||||
);
|
||||
};
|
||||
|
||||
const onPhoneCountrySearchFocus = (field, key) => {
|
||||
loadSuggestions(field.source);
|
||||
showCountrySuggestions[key] = true;
|
||||
};
|
||||
|
||||
const onPhoneCountrySearchBlur = (key) => {
|
||||
setTimeout(() => {
|
||||
showCountrySuggestions[key] = false;
|
||||
phoneCountrySearchText[key] = undefined;
|
||||
}, 200);
|
||||
};
|
||||
|
||||
const onPhoneCountrySearchInput = (key, event) => {
|
||||
phoneCountrySearchText[key] = event.target.value;
|
||||
showCountrySuggestions[key] = true;
|
||||
};
|
||||
|
||||
const onPhoneCountrySelect = (key, item) => {
|
||||
phoneParts[key].code = item.dial_code;
|
||||
phoneParts[key].flag = item.flag;
|
||||
phoneParts[key].number = phoneParts[key].number || "";
|
||||
formData[key] = item.dial_code + phoneParts[key].number;
|
||||
phoneCountrySearchText[key] = undefined;
|
||||
showCountrySuggestions[key] = false;
|
||||
stepErrors[key] = false;
|
||||
};
|
||||
|
||||
const suggestionsCache = ref({});
|
||||
const showSuggestions = reactive({});
|
||||
const phoneCountrySearchText = reactive({});
|
||||
const showCountrySuggestions = reactive({});
|
||||
|
||||
const loadSuggestions = async (source) => {
|
||||
if (suggestionsCache.value[source]) return;
|
||||
|
|
@ -583,18 +624,39 @@ const getFieldInputType = (field) => {
|
|||
|
||||
<div v-else-if="field.type === 'phone_country'" class="relative">
|
||||
<div class="join w-full">
|
||||
<select
|
||||
class="select join-item bg-white border-gray-200 w-[8.5rem] rounded-l-xl text-sm focus:outline-2 focus:outline-[#22523F] grow text-[#1a1a1a]"
|
||||
:class="{ 'border-red-500': getFieldError(field.key) }"
|
||||
@change="onPhoneCountryCodeChange(field.key, $event.target.value)"
|
||||
>
|
||||
<option value="" selected disabled>{{ tl("form.phone_code_select") }}</option>
|
||||
<option v-for="item in getSelectOptions(field)" :key="item.value" :value="item.dial_code">
|
||||
{{ item.flag }} {{ item.dial_code }}
|
||||
</option>
|
||||
</select>
|
||||
<div class="join-item relative w-28">
|
||||
<label
|
||||
class="input join-item rounded-r-xl grow bg-white border-gray-200 focus-within:outline-2 focus-within:outline-[#22523F]"
|
||||
class="input border-gray-200 rounded-l-xl bg-white w-full focus-within:outline-2 focus-within:outline-[#22523F]"
|
||||
:class="{ 'border-red-500': getFieldError(field.key) }"
|
||||
>
|
||||
<input
|
||||
class="w-full text-[#1a1a1a]"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
:value="getPhoneCountryDisplay(field.key)"
|
||||
:placeholder="tl('form.phone_code_select')"
|
||||
@input="onPhoneCountrySearchInput(field.key, $event)"
|
||||
@focus="onPhoneCountrySearchFocus(field, field.key)"
|
||||
@blur="onPhoneCountrySearchBlur(field.key)"
|
||||
/>
|
||||
</label>
|
||||
<ul
|
||||
v-if="showCountrySuggestions[field.key] && filteredPhoneCountries(field, field.key).length"
|
||||
class="absolute left-0 right-0 z-50 bg-white shadow-lg rounded-b-xl border border-gray-200 border-t-0 max-h-[200px] overflow-y-auto"
|
||||
>
|
||||
<li
|
||||
v-for="item in filteredPhoneCountries(field, field.key)"
|
||||
:key="item.value"
|
||||
class="px-3 py-2 cursor-pointer text-sm text-[#1a1a1a] hover:bg-[#22523F]/10 transition-colors flex items-center gap-2"
|
||||
@mousedown.prevent="onPhoneCountrySelect(field.key, item)"
|
||||
>
|
||||
<span>{{ item.flag }}</span>
|
||||
<span class="font-mono">{{ item.dial_code }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<label
|
||||
class="input join-item grow bg-white rounded-r-xl border-gray-200 focus-within:outline-2 focus-within:outline-[#22523F]"
|
||||
:class="{ 'border-red-500': getFieldError(field.key) }"
|
||||
>
|
||||
<input
|
||||
|
|
|
|||
Loading…
Reference in New Issue