Skip to content

Commit 617f8d9

Browse files
AchoArnoldCopilot
andauthored
feat(web): replace phone number input with v-phone-input (#905)
- Install v-phone-input and flag-icons packages - Create vPhoneInput.client.ts plugin with autocomplete country selector, SVG flags, and validation disabled (validate: null) - Add v-phone-input to build.transpile in nuxt.config.ts - Replace VTextField with v-phone-input in messages/index.vue - Add getRecipientNumber() to handle short codes by stripping country dial code prefix when the number is not a valid E.164 phone number This allows sending SMS to short code numbers (e.g. 91291) without the frontend prepending a country code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c33e887 commit 617f8d9

5 files changed

Lines changed: 110 additions & 4 deletions

File tree

web/app/pages/messages/index.vue

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
<script setup lang="ts">
22
import { mdiArrowLeft, mdiSend, mdiCircle } from "@mdi/js";
3+
import {
4+
isValidPhoneNumber,
5+
getCountryCallingCode,
6+
type CountryCode,
7+
} from "libphonenumber-js";
38
49
definePageMeta({
510
middleware: ["auth"],
@@ -18,10 +23,27 @@ const { useApi } = useApiComposable();
1823
1924
const sending = ref(false);
2025
const formPhoneNumber = ref("");
26+
const phoneCountry = ref("US");
2127
const formContent = ref("");
2228
const formAttachments = ref("");
2329
const errors = ref(new Map<string, string[]>());
2430
31+
function getRecipientNumber(): string {
32+
const phone = formPhoneNumber.value;
33+
if (isValidPhoneNumber(phone)) {
34+
return phone;
35+
}
36+
// Short code — strip the country dial code prefix
37+
const dialCode = getCountryCallingCode(
38+
phoneCountry.value.toUpperCase() as CountryCode,
39+
);
40+
const prefix = `+${dialCode}`;
41+
if (phone.startsWith(prefix)) {
42+
return phone.slice(prefix.length);
43+
}
44+
return phone;
45+
}
46+
2547
async function sendMessage() {
2648
errors.value = new Map();
2749
sending.value = true;
@@ -31,7 +53,7 @@ async function sendMessage() {
3153
await api("/v1/messages/send", {
3254
method: "POST",
3355
body: {
34-
to: formPhoneNumber.value,
56+
to: getRecipientNumber(),
3557
from: phonesStore.owner,
3658
content: formContent.value,
3759
attachments: formAttachments.value
@@ -95,15 +117,17 @@ async function sendMessage() {
95117
<VRow>
96118
<VCol cols="12" md="8" offset-md="2" xl="6" offset-xl="3">
97119
<form @submit.prevent="sendMessage">
98-
<VTextField
120+
<v-phone-input
99121
v-model="formPhoneNumber"
122+
v-model:country="phoneCountry"
100123
:disabled="sending"
101124
:error="errors.has('to')"
102125
:error-messages="errors.get('to')"
103126
variant="outlined"
104127
persistent-placeholder
105-
placeholder="Recipient phone number e.g +18005550199"
128+
placeholder="Recipient phone number e.g 18005550199"
106129
label="Phone Number"
130+
country-label="Country"
107131
/>
108132
<VTextarea
109133
v-model="formContent"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import "flag-icons/css/flag-icons.min.css";
2+
import "v-phone-input/styles";
3+
import {
4+
createVPhoneInput,
5+
autocompletePhoneCountryInput,
6+
VPhoneCountryFlagSvg,
7+
} from "v-phone-input";
8+
9+
export default defineNuxtPlugin((nuxtApp) => {
10+
const vPhoneInput = createVPhoneInput({
11+
...autocompletePhoneCountryInput,
12+
countryDisplayComponent: VPhoneCountryFlagSvg,
13+
validate: null,
14+
});
15+
16+
nuxtApp.vueApp.use(vPhoneInput);
17+
});

web/nuxt.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default defineNuxtConfig({
99
css: ["vuetify/styles"],
1010

1111
build: {
12-
transpile: ["vuetify", "chart.js", "vue-chartjs"],
12+
transpile: ["vuetify", "chart.js", "vue-chartjs", "v-phone-input"],
1313
},
1414

1515
vite: {

web/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
"date-fns": "^4.3.0",
2020
"firebase": "^12.13.0",
2121
"firebaseui": "^6.1.0",
22+
"flag-icons": "^7.5.0",
2223
"libphonenumber-js": "^1.13.3",
2324
"moment": "^2.30.1",
2425
"nuxt": "^4.4.6",
2526
"pusher-js": "^8.5.0",
2627
"qrcode": "^1.5.4",
2728
"sass": "^1.100.0",
29+
"v-phone-input": "^7.0.0",
2830
"vue": "^3.5.34",
2931
"vue-chartjs": "^5.3.3",
3032
"vue-router": "^5.0.7",

web/pnpm-lock.yaml

Lines changed: 63 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)