aboutsummaryrefslogtreecommitdiff
path: root/src/tools/phone-parser-and-formatter/phone-parser-and-formatter.vue
blob: d17356a939d31bd169b9821228845f17c1e189dc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<template>
  <div>
    <n-form-item label="Default country code:">
      <n-select v-model:value="defaultCountryCode" :options="countriesOptions" />
    </n-form-item>
    <n-form-item label="Phone number:" v-bind="validation.attrs">
      <n-input v-model:value="rawPhone" placeholder="Enter a phone number" />
    </n-form-item>

    <n-table v-if="parsedDetails">
      <tbody>
        <tr v-for="{ label, value } in parsedDetails" :key="label">
          <td>
            <n-text strong>{{ label }}</n-text>
          </td>
          <td>
            <span-copyable v-if="value" :value="value"></span-copyable>
            <n-text v-else depth="3" italic>Unknown</n-text>
          </td>
        </tr>
      </tbody>
    </n-table>
  </div>
</template>

<script setup lang="ts">
import { withDefaultOnError } from '@/utils/defaults';
import { parsePhoneNumber, getCountries, getCountryCallingCode } from 'libphonenumber-js/max';
import { booleanToHumanReadable } from '@/utils/boolean';
import { useValidation } from '@/composable/validation';
import lookup from 'country-code-lookup';
import {
  formatTypeToHumanReadable,
  getFullCountryName,
  getDefaultCountryCode,
} from './phone-parser-and-formatter.models';

const rawPhone = ref('');
const defaultCountryCode = ref(getDefaultCountryCode());
const validation = useValidation({
  source: rawPhone,
  rules: [
    {
      validator: (value) => value === '' || /^[0-9 +\-()]+$/.test(value),
      message: 'Invalid phone number',
    },
  ],
});

const parsedDetails = computed(() => {
  if (!validation.isValid) return undefined;

  const parsed = withDefaultOnError(() => parsePhoneNumber(rawPhone.value, 'FR'), undefined);

  if (!parsed) return undefined;

  return [
    {
      label: 'Country',
      value: parsed.country,
    },
    {
      label: 'Country',
      value: getFullCountryName(parsed.country),
    },
    {
      label: 'Country calling code',
      value: parsed.countryCallingCode,
    },
    {
      label: 'Is valid?',
      value: booleanToHumanReadable(parsed.isValid()),
    },
    {
      label: 'Is possible?',
      value: booleanToHumanReadable(parsed.isPossible()),
    },
    {
      label: 'Type',
      value: formatTypeToHumanReadable(parsed.getType()),
    },
    {
      label: 'International format',
      value: parsed.formatInternational(),
    },
    {
      label: 'National format',
      value: parsed.formatNational(),
    },
    {
      label: 'E.164 format',
      value: parsed.format('E.164'),
    },
    {
      label: 'RFC3966 format',
      value: parsed.format('RFC3966'),
    },
  ];
});

const countriesOptions = getCountries().map((code) => ({
  label: `${lookup.byIso(code)?.country || code} (+${getCountryCallingCode(code)})`,
  value: code,
}));
</script>

<style lang="less" scoped></style>