Fix phone input (#201)

* Fix phone input

* remove extra

* fix factory

* Fix phone input

* Validate phone number rule

* Prefill support for country only

* Fix phone input error

* fix tests

---------

Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
formsdev 2023-09-18 18:42:05 +05:30 committed by GitHub
parent 08db014cde
commit d75975bdec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 257 additions and 95 deletions

View File

@ -190,7 +190,7 @@ class AnswerFormRequest extends FormRequest
} }
return $this->getRulesForDate($property); return $this->getRulesForDate($property);
case 'phone_number': case 'phone_number':
return [new ValidPhoneInputRule]; return ['string', 'min:6', new ValidPhoneInputRule];
default: default:
return []; return [];
} }

View File

@ -9,21 +9,16 @@ class ValidPhoneInputRule implements Rule
{ {
public function passes($attribute, $value) public function passes($attribute, $value)
{ {
if (!is_string($value)) { if (!is_string($value) || !Str::startsWith($value, '+')) {
return false; return false;
} }
if (!Str::startsWith($value, '+')) {
return false; $phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
} return $phoneUtil->isValidNumber($phoneUtil->parse($value));
$parts = explode(' ', $value);
if (count($parts) < 2) {
return false;
}
return strlen($parts[1]) >= 5;
} }
public function message() public function message()
{ {
return 'The :attribute must be a string that starts with a "+" character and must be at least 5 digits long.'; return 'The :attribute is invalid.';
} }
} }

View File

@ -18,11 +18,12 @@
} }
], ],
"require": { "require": {
"php": "^8.0", "php": "^8.2",
"ext-json": "*", "ext-json": "*",
"aws/aws-sdk-php": "^3.183", "aws/aws-sdk-php": "^3.183",
"doctrine/dbal": "^3.4", "doctrine/dbal": "^3.4",
"fruitcake/laravel-cors": "^2.0", "fruitcake/laravel-cors": "^2.0",
"giggsey/libphonenumber-for-php": "^8.13",
"guzzlehttp/guzzle": "^7.0.1", "guzzlehttp/guzzle": "^7.0.1",
"jhumanj/laravel-model-stats": "^0.4.0", "jhumanj/laravel-model-stats": "^0.4.0",
"laravel/cashier": "^13.4", "laravel/cashier": "^13.4",

224
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "9c7ea2e339a9d3c8ecae0a3ae7cc2883", "content-hash": "563d3a4c1489aa79b9fd5b87309eb28b",
"packages": [ "packages": [
{ {
"name": "asm89/stack-cors", "name": "asm89/stack-cors",
@ -118,16 +118,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.281.2", "version": "3.281.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "5b33690b4ebc32a75164be0d6805d393a3ca9df9" "reference": "eb349b9f31502a05c70362f57913b9fed6b65b1f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5b33690b4ebc32a75164be0d6805d393a3ca9df9", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/eb349b9f31502a05c70362f57913b9fed6b65b1f",
"reference": "5b33690b4ebc32a75164be0d6805d393a3ca9df9", "reference": "eb349b9f31502a05c70362f57913b9fed6b65b1f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -207,9 +207,9 @@
"support": { "support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.281.2" "source": "https://github.com/aws/aws-sdk-php/tree/3.281.8"
}, },
"time": "2023-09-07T18:06:59+00:00" "time": "2023-09-15T18:34:59+00:00"
}, },
{ {
"name": "brick/math", "name": "brick/math",
@ -1402,6 +1402,132 @@
], ],
"time": "2022-02-20T15:07:15+00:00" "time": "2022-02-20T15:07:15+00:00"
}, },
{
"name": "giggsey/libphonenumber-for-php",
"version": "8.13.20",
"source": {
"type": "git",
"url": "https://github.com/giggsey/libphonenumber-for-php.git",
"reference": "c8da9366ab46cbc83f9fd0e7b0ac12f8ddbb721a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/c8da9366ab46cbc83f9fd0e7b0ac12f8ddbb721a",
"reference": "c8da9366ab46cbc83f9fd0e7b0ac12f8ddbb721a",
"shasum": ""
},
"require": {
"giggsey/locale": "^1.7|^2.0",
"php": ">=5.3.2",
"symfony/polyfill-mbstring": "^1.17"
},
"require-dev": {
"pear/pear-core-minimal": "^1.9",
"pear/pear_exception": "^1.0",
"pear/versioncontrol_git": "^0.5",
"phing/phing": "^2.7",
"php-coveralls/php-coveralls": "^1.0|^2.0",
"symfony/console": "^2.8|^3.0|^v4.4|^v5.2",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"libphonenumber\\": "src/"
},
"exclude-from-classmap": [
"/src/data/",
"/src/carrier/data/",
"/src/geocoding/data/",
"/src/timezone/data/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Joshua Gigg",
"email": "giggsey@gmail.com",
"homepage": "https://giggsey.com/"
}
],
"description": "PHP Port of Google's libphonenumber",
"homepage": "https://github.com/giggsey/libphonenumber-for-php",
"keywords": [
"geocoding",
"geolocation",
"libphonenumber",
"mobile",
"phonenumber",
"validation"
],
"support": {
"issues": "https://github.com/giggsey/libphonenumber-for-php/issues",
"source": "https://github.com/giggsey/libphonenumber-for-php"
},
"time": "2023-09-07T06:33:03+00:00"
},
{
"name": "giggsey/locale",
"version": "2.4",
"source": {
"type": "git",
"url": "https://github.com/giggsey/Locale.git",
"reference": "a6b33dfc9e8949b7e28133c4628b29cd9f1850bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/giggsey/Locale/zipball/a6b33dfc9e8949b7e28133c4628b29cd9f1850bb",
"reference": "a6b33dfc9e8949b7e28133c4628b29cd9f1850bb",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"require-dev": {
"ext-json": "*",
"pear/pear-core-minimal": "^1.9",
"pear/pear_exception": "^1.0",
"pear/versioncontrol_git": "^0.5",
"phing/phing": "^2.7",
"php-coveralls/php-coveralls": "^2.0",
"phpunit/phpunit": "^8.5|^9.5",
"symfony/console": "^5.0|^6.0",
"symfony/filesystem": "^5.0|^6.0",
"symfony/finder": "^5.0|^6.0",
"symfony/process": "^5.0|^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Giggsey\\Locale\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Joshua Gigg",
"email": "giggsey@gmail.com",
"homepage": "https://giggsey.com/"
}
],
"description": "Locale functions required by libphonenumber-for-php",
"support": {
"issues": "https://github.com/giggsey/Locale/issues",
"source": "https://github.com/giggsey/Locale/tree/2.4"
},
"time": "2023-04-13T07:40:58+00:00"
},
{ {
"name": "graham-campbell/manager", "name": "graham-campbell/manager",
"version": "v4.7.0", "version": "v4.7.0",
@ -2613,16 +2739,16 @@
}, },
{ {
"name": "laravel/horizon", "name": "laravel/horizon",
"version": "v5.20.0", "version": "v5.20.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/horizon.git", "url": "https://github.com/laravel/horizon.git",
"reference": "2fc2ba769a592e92d170d85e346a5631b3a90ed5" "reference": "6eaf4efebbfc9955be7504b5b6f045d9d10e86af"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/horizon/zipball/2fc2ba769a592e92d170d85e346a5631b3a90ed5", "url": "https://api.github.com/repos/laravel/horizon/zipball/6eaf4efebbfc9955be7504b5b6f045d9d10e86af",
"reference": "2fc2ba769a592e92d170d85e346a5631b3a90ed5", "reference": "6eaf4efebbfc9955be7504b5b6f045d9d10e86af",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2685,9 +2811,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/laravel/horizon/issues", "issues": "https://github.com/laravel/horizon/issues",
"source": "https://github.com/laravel/horizon/tree/v5.20.0" "source": "https://github.com/laravel/horizon/tree/v5.20.1"
}, },
"time": "2023-08-30T14:04:11+00:00" "time": "2023-09-12T11:21:57+00:00"
}, },
{ {
"name": "laravel/serializable-closure", "name": "laravel/serializable-closure",
@ -2751,16 +2877,16 @@
}, },
{ {
"name": "laravel/socialite", "name": "laravel/socialite",
"version": "v5.9.0", "version": "v5.9.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/socialite.git", "url": "https://github.com/laravel/socialite.git",
"reference": "14acfa3262875f180fba51efe3c7aaa089a9ef24" "reference": "49ecc4c907ed88c1254bae991c6b2948945645c2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/socialite/zipball/14acfa3262875f180fba51efe3c7aaa089a9ef24", "url": "https://api.github.com/repos/laravel/socialite/zipball/49ecc4c907ed88c1254bae991c6b2948945645c2",
"reference": "14acfa3262875f180fba51efe3c7aaa089a9ef24", "reference": "49ecc4c907ed88c1254bae991c6b2948945645c2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2817,7 +2943,7 @@
"issues": "https://github.com/laravel/socialite/issues", "issues": "https://github.com/laravel/socialite/issues",
"source": "https://github.com/laravel/socialite" "source": "https://github.com/laravel/socialite"
}, },
"time": "2023-09-05T15:20:21+00:00" "time": "2023-09-07T16:13:53+00:00"
}, },
{ {
"name": "laravel/tinker", "name": "laravel/tinker",
@ -7526,16 +7652,16 @@
}, },
{ {
"name": "spatie/laravel-webhook-server", "name": "spatie/laravel-webhook-server",
"version": "3.4.3", "version": "3.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/laravel-webhook-server.git", "url": "https://github.com/spatie/laravel-webhook-server.git",
"reference": "9d4506fb340db7750bcb088fe0253bdd30beaa32" "reference": "7aec82720bf06c9c9a9221a1f2d5175492a4c3fe"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-webhook-server/zipball/9d4506fb340db7750bcb088fe0253bdd30beaa32", "url": "https://api.github.com/repos/spatie/laravel-webhook-server/zipball/7aec82720bf06c9c9a9221a1f2d5175492a4c3fe",
"reference": "9d4506fb340db7750bcb088fe0253bdd30beaa32", "reference": "7aec82720bf06c9c9a9221a1f2d5175492a4c3fe",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7588,7 +7714,7 @@
"webhook" "webhook"
], ],
"support": { "support": {
"source": "https://github.com/spatie/laravel-webhook-server/tree/3.4.3" "source": "https://github.com/spatie/laravel-webhook-server/tree/3.5.0"
}, },
"funding": [ "funding": [
{ {
@ -7596,7 +7722,7 @@
"type": "custom" "type": "custom"
} }
], ],
"time": "2023-03-17T09:01:16+00:00" "time": "2023-09-12T09:01:43+00:00"
}, },
{ {
"name": "spatie/robots-txt", "name": "spatie/robots-txt",
@ -11920,16 +12046,16 @@
}, },
{ {
"name": "laravel/sail", "name": "laravel/sail",
"version": "v1.24.1", "version": "v1.25.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/sail.git", "url": "https://github.com/laravel/sail.git",
"reference": "3a373bb2845623aed2017c672dc61c84ae974890" "reference": "e81a7bd7ac1a745ccb25572830fecf74a89bb48a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/sail/zipball/3a373bb2845623aed2017c672dc61c84ae974890", "url": "https://api.github.com/repos/laravel/sail/zipball/e81a7bd7ac1a745ccb25572830fecf74a89bb48a",
"reference": "3a373bb2845623aed2017c672dc61c84ae974890", "reference": "e81a7bd7ac1a745ccb25572830fecf74a89bb48a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -11981,7 +12107,7 @@
"issues": "https://github.com/laravel/sail/issues", "issues": "https://github.com/laravel/sail/issues",
"source": "https://github.com/laravel/sail" "source": "https://github.com/laravel/sail"
}, },
"time": "2023-09-01T14:05:17+00:00" "time": "2023-09-11T17:37:09+00:00"
}, },
{ {
"name": "mockery/mockery", "name": "mockery/mockery",
@ -12952,16 +13078,16 @@
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "9.2.27", "version": "9.2.28",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1" "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef",
"reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1", "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -13018,7 +13144,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27" "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.28"
}, },
"funding": [ "funding": [
{ {
@ -13026,7 +13152,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-07-26T13:44:30+00:00" "time": "2023-09-12T14:36:20+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
@ -13271,16 +13397,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "9.6.11", "version": "9.6.12",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "810500e92855eba8a7a5319ae913be2da6f957b0" "reference": "a122c2ebd469b751d774aa0f613dc0d67697653f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/810500e92855eba8a7a5319ae913be2da6f957b0", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a122c2ebd469b751d774aa0f613dc0d67697653f",
"reference": "810500e92855eba8a7a5319ae913be2da6f957b0", "reference": "a122c2ebd469b751d774aa0f613dc0d67697653f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -13295,7 +13421,7 @@
"phar-io/manifest": "^2.0.3", "phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2", "phar-io/version": "^3.0.2",
"php": ">=7.3", "php": ">=7.3",
"phpunit/php-code-coverage": "^9.2.13", "phpunit/php-code-coverage": "^9.2.28",
"phpunit/php-file-iterator": "^3.0.5", "phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1", "phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3", "phpunit/php-text-template": "^2.0.3",
@ -13354,7 +13480,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.11" "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.12"
}, },
"funding": [ "funding": [
{ {
@ -13370,7 +13496,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-08-19T07:10:56+00:00" "time": "2023-09-12T14:39:31+00:00"
}, },
{ {
"name": "pimple/pimple", "name": "pimple/pimple",
@ -14831,16 +14957,16 @@
}, },
{ {
"name": "spatie/ray", "name": "spatie/ray",
"version": "1.37.7", "version": "1.38.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/ray.git", "url": "https://github.com/spatie/ray.git",
"reference": "31e07c3eadc736e180810efff72a0ff882dcddb6" "reference": "b77656d7475875375fcbccf28441eedf1596acd5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/ray/zipball/31e07c3eadc736e180810efff72a0ff882dcddb6", "url": "https://api.github.com/repos/spatie/ray/zipball/b77656d7475875375fcbccf28441eedf1596acd5",
"reference": "31e07c3eadc736e180810efff72a0ff882dcddb6", "reference": "b77656d7475875375fcbccf28441eedf1596acd5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -14891,7 +15017,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/spatie/ray/issues", "issues": "https://github.com/spatie/ray/issues",
"source": "https://github.com/spatie/ray/tree/1.37.7" "source": "https://github.com/spatie/ray/tree/1.38.0"
}, },
"funding": [ "funding": [
{ {
@ -14903,7 +15029,7 @@
"type": "other" "type": "other"
} }
], ],
"time": "2023-09-08T12:08:25+00:00" "time": "2023-09-12T10:41:10+00:00"
}, },
{ {
"name": "symfony/polyfill-iconv", "name": "symfony/polyfill-iconv",
@ -15314,7 +15440,7 @@
"prefer-stable": true, "prefer-stable": true,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": "^8.0", "php": "^8.2",
"ext-json": "*" "ext-json": "*"
}, },
"platform-dev": [], "platform-dev": [],

11
package-lock.json generated
View File

@ -16,6 +16,7 @@
"fuse.js": "^6.4.6", "fuse.js": "^6.4.6",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"js-sha256": "^0.9.0", "js-sha256": "^0.9.0",
"libphonenumber-js": "^1.10.44",
"portal-vue": "^2.1.7", "portal-vue": "^2.1.7",
"prismjs": "^1.24.1", "prismjs": "^1.24.1",
"qrcode": "^1.5.1", "qrcode": "^1.5.1",
@ -8142,6 +8143,11 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/libphonenumber-js": {
"version": "1.10.44",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.44.tgz",
"integrity": "sha512-svlRdNBI5WgBjRC20GrCfbFiclbF0Cx+sCcQob/C1r57nsoq0xg8r65QbTyVyweQIlB33P+Uahyho6EMYgcOyQ=="
},
"node_modules/lilconfig": { "node_modules/lilconfig": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
@ -19111,6 +19117,11 @@
"type-check": "~0.4.0" "type-check": "~0.4.0"
} }
}, },
"libphonenumber-js": {
"version": "1.10.44",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.44.tgz",
"integrity": "sha512-svlRdNBI5WgBjRC20GrCfbFiclbF0Cx+sCcQob/C1r57nsoq0xg8r65QbTyVyweQIlB33P+Uahyho6EMYgcOyQ=="
},
"lilconfig": { "lilconfig": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",

View File

@ -16,6 +16,7 @@
"fuse.js": "^6.4.6", "fuse.js": "^6.4.6",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"js-sha256": "^0.9.0", "js-sha256": "^0.9.0",
"libphonenumber-js": "^1.10.44",
"portal-vue": "^2.1.7", "portal-vue": "^2.1.7",
"prismjs": "^1.24.1", "prismjs": "^1.24.1",
"qrcode": "^1.5.1", "qrcode": "^1.5.1",

View File

@ -12,10 +12,12 @@
<slot name="help"><span class="field-help" v-html="help"/></slot> <slot name="help"><span class="field-help" v-html="help"/></slot>
</small> </small>
</div> </div>
<div :id="id ? id : name" :disabled="disabled" :name="name" :style="inputStyle" class="flex items-center"> <div :id="id ? id : name" :name="name" :style="inputStyle" class="flex items-center">
<v-select class="w-[110px]" dropdown-class="w-[400px]" input-class="rounded-r-none" :data="countries" :value="selectedCountryCode" <v-select class="w-[110px]" dropdown-class="w-[400px]" input-class="rounded-r-none" :data="countries"
:searchable="true" :search-keys="['name']" :option-key="'code'" :color="color" v-model="selectedCountryCode"
:placeholder="'Select a country'" :uppercase-labels="true" :theme="theme" @input="onCountryChange"> :has-error="hasValidation && form.errors.has(name)"
:disabled="disabled" :searchable="true" :search-keys="['name']" :option-key="'code'" :color="color"
:placeholder="'Select a country'" :uppercase-labels="true" :theme="theme" @input="onChangeCountryCode">
<template #option="props"> <template #option="props">
<div class="flex items-center space-x-2 hover:text-white"> <div class="flex items-center space-x-2 hover:text-white">
<country-flag size="normal" class="!-mt-[9px]" :country="props.option.code"/> <country-flag size="normal" class="!-mt-[9px]" :country="props.option.code"/>
@ -25,15 +27,21 @@
</template> </template>
<template #selected="props"> <template #selected="props">
<div class="flex items-center space-x-2 justify-center overflow-hidden"> <div class="flex items-center space-x-2 justify-center overflow-hidden">
<country-flag size="normal" class="!-mt-[9px]" :country="props.option.code" /> <country-flag size="normal" class="!-mt-[9px]" :country="props.option.code"/>
<span>{{ props.option.dial_code }}</span> <span>{{ props.option.dial_code }}</span>
</div> </div>
</template> </template>
</v-select> </v-select>
<input v-model="inputVal" type="text" class="inline-flex-grow !border-l-0 !rounded-l-none" <input v-model="inputVal" type="text" class="inline-flex-grow !border-l-0 !rounded-l-none" :disabled="disabled"
:class="[theme.default.input, { '!ring-red-500 !ring-2': hasValidation && form.errors.has(name), '!cursor-not-allowed !bg-gray-200': disabled }]" :class="[theme.default.input, { '!ring-red-500 !ring-2': hasValidation && form.errors.has(name), '!cursor-not-allowed !bg-gray-200': disabled }]"
:placeholder="placeholder" :style="inputStyle" @input="onInput"> :placeholder="placeholder" :style="inputStyle" @input="onInput">
</div> </div>
<div v-if="help && helpPosition=='below_input'" class="flex">
<small :class="theme.default.help" class="grow">
<slot name="help"><span class="field-help" v-html="help"/></slot>
</small>
</div>
<has-error v-if="hasValidation" :form="form" :field="name"/>
</div> </div>
</template> </template>
@ -42,32 +50,49 @@ import {directive as onClickaway} from 'vue-clickaway'
import inputMixin from '~/mixins/forms/input.js' import inputMixin from '~/mixins/forms/input.js'
import countryCodes from '../../../data/country_codes.json' import countryCodes from '../../../data/country_codes.json'
import CountryFlag from 'vue-country-flag' import CountryFlag from 'vue-country-flag'
import VSelect from './components/VSelect.vue' import parsePhoneNumber from 'libphonenumber-js'
export default { export default {
phone: 'PhoneInput', phone: 'PhoneInput',
components: { components: {CountryFlag},
CountryFlag, VSelect
},
directives: { directives: {
onClickaway: onClickaway onClickaway: onClickaway
}, },
mixins: [inputMixin], mixins: [inputMixin],
props: {
canOnlyCountry: {type: Boolean, default: false}
},
data() { data() {
return { return {
selectedCountryCode: countryCodes[234], selectedCountryCode: this.getCountryBy('US'), // Default US
countries: countryCodes, countries: countryCodes,
isOpen: false, inputVal: null
inputVal: ''
} }
}, },
watch: {
inputVal(newVal, oldVal) { mounted() {
if (newVal.startsWith('0')) { if (this.compVal) {
newVal = newVal.replace(/^0+/, '') const phoneObj = parsePhoneNumber(this.compVal)
if (phoneObj !== undefined && phoneObj) {
if (phoneObj.country !== undefined && phoneObj.country) {
this.selectedCountryCode = this.getCountryBy(phoneObj.country)
}
this.inputVal = phoneObj.nationalNumber
} else if (this.compVal) {
this.selectedCountryCode = this.getCountryBy(this.compVal, 'dial_code')
}
}
},
watch: {
inputVal: {
handler(val) {
if (val && val.startsWith('0')) {
val = val.substring(1)
}
this.compVal = (val) ? this.selectedCountryCode.dial_code + val : null
} }
this.compVal = this.selectedCountryCode.dial_code + ' ' + newVal
}, },
selectedCountryCode(newVal, oldVal) { selectedCountryCode(newVal, oldVal) {
if (this.compVal) { if (this.compVal) {
@ -76,18 +101,19 @@ export default {
} }
}, },
methods: { methods: {
onCountryChange(country) { getCountryBy(code, type = 'code') {
this.selectedCountryCode = country return countryCodes.find((item) => {
this.closeDropdown() return item[type] === code
}, })
closeDropdown() {
this.isOpen = false
}, },
onInput(event) { onInput(event) {
const input = event.target.value this.inputVal = event.target.value.replace(/[^0-9]/g, '')
const digitsOnly = input.replace(/[^0-9]/g, '')
this.inputVal = digitsOnly
}, },
onChangeCountryCode() {
if (this.canOnlyCountry && (this.inputVal === null || this.inputVal === '' || !this.inputVal)) {
this.compVal = this.selectedCountryCode.dial_code
}
}
} }
} }
</script> </script>

View File

@ -69,14 +69,11 @@
<script> <script>
import FormLogicPropertyResolver from '../../../forms/FormLogicPropertyResolver.js' import FormLogicPropertyResolver from '../../../forms/FormLogicPropertyResolver.js'
import FormPendingSubmissionKey from '../../../mixins/forms/form-pending-submission-key.js' import FormPendingSubmissionKey from '../../../mixins/forms/form-pending-submission-key.js'
import PhoneInput from '../../forms/PhoneInput.vue'
import {mapState} from "vuex"; import {mapState} from "vuex";
export default { export default {
name: 'OpenFormField', name: 'OpenFormField',
components: { components: {},
PhoneInput
},
mixins: [FormPendingSubmissionKey], mixins: [FormPendingSubmissionKey],
props: { props: {
form: { form: {

View File

@ -216,6 +216,11 @@
:date-range="field.date_range===true" :date-range="field.date_range===true"
label="Pre-filled value" label="Pre-filled value"
/> />
<phone-input v-else-if="field.type === 'phone_number'"
name="prefill" class="mt-3"
:form="field" :can-only-country="true"
label="Pre-filled value"
/>
<text-area-input v-else-if="field.type === 'text' && field.multi_lines" <text-area-input v-else-if="field.type === 'text' && field.multi_lines"
name="prefill" class="mt-3" name="prefill" class="mt-3"
:form="field" :form="field"
@ -267,7 +272,7 @@
@input="onFieldHelpPositionChange" @input="onFieldHelpPositionChange"
/> />
<template v-if="['text','number','url','email','phone_number'].includes(field.type)"> <template v-if="['text','number','url','email'].includes(field.type)">
<text-input v-model="field.max_char_limit" name="max_char_limit" native-type="number" :min="1" :max="2000" <text-input v-model="field.max_char_limit" name="max_char_limit" native-type="number" :min="1" :max="2000"
:form="field" :form="field"
label="Max character limit" label="Max character limit"
@ -401,7 +406,7 @@ export default {
}, },
mounted() { mounted() {
if (['text', 'number', 'url', 'email', 'phone_number'].includes(this.field?.type) && !this.field?.max_char_limit) { if (['text', 'number', 'url', 'email'].includes(this.field?.type) && !this.field?.max_char_limit) {
this.field.max_char_limit = 2000 this.field.max_char_limit = 2000
} }
}, },

View File

@ -44,7 +44,7 @@ class FormSubmissionDataFactory
$value = $this->faker->url(); $value = $this->faker->url();
break; break;
case 'phone_number': case 'phone_number':
$value = '+1 ' .$this->faker->phoneNumber(); $value = '+33749119783';
break; break;
case 'date': case 'date':
$value = $this->faker->date(); $value = $this->faker->date();