Add phone number formatting and improve UI components

- Integrate libphonenumber-js for proper phone number formatting
- Display phone numbers in national format in PhoneInput component
- Strip non-numeric characters from phone input automatically
- Fix refresh button icon rendering in EmailThreadView
- Improve EOI button layout alignment and centering
This commit is contained in:
Matt 2025-06-12 22:35:17 +02:00
parent 331d8b8194
commit e57756e433
5 changed files with 28 additions and 9 deletions

View File

@ -29,7 +29,7 @@
</div>
<!-- Generate EOI Button - Only show if no documents uploaded and no generated EOI -->
<div v-if="!hasGeneratedEOI && !hasEOIDocuments" class="d-flex flex-wrap" :class="mobile ? 'gap-3' : 'gap-4'">
<div v-if="!hasGeneratedEOI && !hasEOIDocuments" class="d-flex flex-wrap justify-space-between align-center" :class="mobile ? 'gap-3' : 'gap-4'">
<v-btn
@click="generateEOI"
:loading="isGenerating"
@ -37,6 +37,7 @@
variant="flat"
prepend-icon="mdi-file-document-plus"
:size="mobile ? 'default' : 'large'"
class="justify-center"
:class="mobile ? 'flex-grow-1' : ''"
>
Generate EOI

View File

@ -5,12 +5,12 @@
Email History
<v-spacer />
<v-btn
icon="mdi-refresh"
:size="mobile ? 'small' : 'small'"
icon
variant="text"
@click="loadEmails"
:loading="loading"
>
<v-icon size="small">mdi-refresh</v-icon>
<v-tooltip activator="parent" location="bottom">
Refresh emails
</v-tooltip>

View File

@ -80,6 +80,7 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { parsePhoneNumberFromString } from 'libphonenumber-js';
interface Country {
name: string;
@ -386,8 +387,16 @@ const filteredCountries = computed(() => {
return [...preferred, ...others];
});
// Display value (local number without country code)
const displayValue = computed(() => localNumber.value);
// Display value with local formatting
const displayValue = computed(() => {
const full = selectedCountry.value.dialCode + localNumber.value;
try {
const phoneNumber = parsePhoneNumberFromString(full);
return phoneNumber ? phoneNumber.format('NATIONAL') : localNumber.value;
} catch {
return localNumber.value;
}
});
// Parse initial value
watch(() => props.modelValue, (newValue) => {
@ -416,11 +425,12 @@ watch(() => props.modelValue, (newValue) => {
}
}, { immediate: true });
// Update phone number
// Update phone number - strip non-numeric characters
const updatePhone = (value: string) => {
localNumber.value = value;
if (value) {
emit('update:modelValue', selectedCountry.value.dialCode + value);
const digits = value.replace(/\D/g, '');
localNumber.value = digits;
if (digits) {
emit('update:modelValue', selectedCountry.value.dialCode + digits);
} else {
emit('update:modelValue', '');
}

7
package-lock.json generated
View File

@ -11,6 +11,7 @@
"@vite-pwa/nuxt": "^0.10.6",
"formidable": "^3.5.4",
"imap": "^0.8.19",
"libphonenumber-js": "^1.12.9",
"lodash-es": "^4.17.21",
"mailparser": "^3.7.3",
"mime-types": "^3.0.1",
@ -8771,6 +8772,12 @@
"libqp": "2.1.1"
}
},
"node_modules/libphonenumber-js": {
"version": "1.12.9",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.9.tgz",
"integrity": "sha512-VWwAdNeJgN7jFOD+wN4qx83DTPMVPPAUyx9/TUkBXKLiNkuWWk6anV0439tgdtwaJDrEdqkvdN22iA6J4bUCZg==",
"license": "MIT"
},
"node_modules/libqp": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/libqp/-/libqp-2.1.1.tgz",

View File

@ -13,6 +13,7 @@
"@vite-pwa/nuxt": "^0.10.6",
"formidable": "^3.5.4",
"imap": "^0.8.19",
"libphonenumber-js": "^1.12.9",
"lodash-es": "^4.17.21",
"mailparser": "^3.7.3",
"mime-types": "^3.0.1",