create_form #48

Merged
esteban merged 42 commits from create_form into main 2026-07-28 11:50:56 +00:00
1 changed files with 81 additions and 19 deletions
Showing only changes of commit 49dfb0d96f - Show all commits

View File

@ -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 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 rounded-r-xl grow bg-white border-gray-200 focus-within:outline-2 focus-within:outline-[#22523F]"
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