Last active
September 12, 2022 16:25
-
-
Save peteleco/c0badd3255b05371d34f4b7c10689653 to your computer and use it in GitHub Desktop.
A simple validation wrapper for inertia.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <app-layout> | |
| <template #header> | |
| <h2 class="font-semibold text-xl text-gray-800 leading-tight"> | |
| Cadastrar Novo Cliente | |
| </h2> | |
| <breadcrumb slot="breadcrumb" :items="breadcrumbItems"></breadcrumb> | |
| </template> | |
| <div class="py-12"> | |
| <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> | |
| <jet-form-section @submitted="create"> | |
| <template #title> | |
| {{$t('PAGES.CLIENTS.CREATE.form_title')}} | |
| </template> | |
| <template #description> | |
| {{$t('PAGES.CLIENTS.CREATE.form_description')}} | |
| </template> | |
| <template #form> | |
| <!-- Name --> | |
| <div class="col-span-6 sm:col-span-4"> | |
| <jet-label for="name" value="Name" /> | |
| <jet-input id="name" type="text" class="mt-1 block w-full" aria-required="true" v-model="form.name" autocomplete="name" /> | |
| <jet-input-error :message="form.error('name')" class="mt-2" /> | |
| </div> | |
| <!-- Mobile --> | |
| <div class="col-span-6 sm:col-span-4"> | |
| <jet-label for="mobile" value="Celular do cliente"/> | |
| <jet-input-validation :error-bag="form.error('mobile')" :error-length="18" :value="form.mobile" :v-function="vMobile" ref="mobileWrapper"> | |
| <template #input="slotProps"> | |
| <jet-input id="mobile" type="tel" | |
| v-facade="[$t('MASKS.MOBILE')]" | |
| class="mt-1 block w-full" | |
| :class="{'focus:border-gray-400': !slotProps.displayError, 'border-danger-300 focus:border-danger-500': slotProps.displayError}" | |
| aria-required="true" v-model="form.mobile" :aria-placeholder="$t('PAGES.CLIENTS.CREATE.aria_mobile_placeholder')" :placeholder="$t('PAGES.CLIENTS.CREATE.mobile_placeholder')" autocomplete="off"/> | |
| </template> | |
| <template #valid> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" class="w-6 h-6 text-success" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5" /> | |
| </svg> | |
| </template> | |
| <template #invalid> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-danger" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| </template> | |
| </jet-input-validation> | |
| <jet-input-error :message="form.error('mobile')" class="mt-2" /> | |
| </div> | |
| </template> | |
| <template #actions> | |
| <jet-action-message :on="form.recentlySuccessful" class="mr-3"> | |
| Saved. | |
| </jet-action-message> | |
| <jet-button :class="{ 'opacity-25': form.processing }" :disabled="form.processing"> | |
| Save | |
| </jet-button> | |
| </template> | |
| </jet-form-section> | |
| </div> | |
| </div> | |
| </app-layout> | |
| </template> | |
| <script> | |
| import {JetInput, JetButton, JetFormSection, JetInputError, JetLabel, JetActionMessage, JetSecondaryButton} from '@/Jetstream'; | |
| import AppLayout from '@/Layouts/AppLayout'; | |
| import {Breadcrumb} from '@/Components'; | |
| import {JetInputValidation} from '@/Chama/Jetstream'; | |
| import {vMobile} from '@/Chama/Validations'; | |
| export default { | |
| name: "Create", | |
| components: { | |
| AppLayout, | |
| Breadcrumb, | |
| JetActionMessage, | |
| JetButton, | |
| JetFormSection, | |
| JetInputError, | |
| JetLabel, | |
| JetSecondaryButton, | |
| JetInput, | |
| JetInputValidation | |
| }, | |
| computed: { | |
| breadcrumbItems() { | |
| return [ | |
| {route: this.route('app.clients'), label: this.$t('BREADCRUMB.clients')}, | |
| {route: this.route('app.clients.create'), label: this.$t('BREADCRUMB.create')}, | |
| ]; | |
| } | |
| }, | |
| data() { | |
| return { | |
| form: this.$inertia.form({ | |
| '_method': 'POST', | |
| name: this.name, | |
| mobile: this.mobile, | |
| photo: null, | |
| }, { | |
| bag: 'default', | |
| resetOnSuccess: false, | |
| }), | |
| } | |
| }, | |
| methods: { | |
| vMobile, | |
| create() { | |
| this.form.post(this.route('app.clients.post'), { | |
| preserveScroll: true | |
| }); | |
| }, | |
| } | |
| } | |
| </script> | |
| <style scoped> | |
| </style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <span class="flex flex-row mb-1 relative" ref="inputValidation"> | |
| <slot name="input" v-bind:displayError="displayError"></slot> | |
| <span class="absolute right-0 flex items-center py-3 px-4 h-full"> | |
| <template v-if="isValid"> | |
| <slot name="valid"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> | |
| </svg> | |
| </slot> | |
| </template> | |
| <template v-if="displayError"> | |
| <slot name="invalid"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} | |
| d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> | |
| </svg> | |
| </slot> | |
| </template> | |
| </span> | |
| </span> | |
| </template> | |
| <script> | |
| export default { | |
| name: 'InputValidation', | |
| props: { | |
| /** | |
| * The value from input | |
| */ | |
| value: { | |
| type: String, | |
| default: "" | |
| }, | |
| /** | |
| *The function that will be used | |
| * at validation | |
| */ | |
| vFunction: { | |
| type: Function, | |
| default: (val) => true | |
| }, | |
| /** | |
| * After type how many characters | |
| * the error can be displayed | |
| */ | |
| errorLength: { | |
| type: Number, | |
| default: 0 | |
| }, | |
| errorBag: { | |
| default: false | |
| } | |
| }, | |
| watch: { | |
| value: { | |
| // the callback will be called immediately after the start of the observation | |
| immediate: true, | |
| handler(val, oldVal) { | |
| this.handleValueUpdates(val); | |
| } | |
| } | |
| }, | |
| computed: { | |
| isValid() { | |
| return this.valid; | |
| }, | |
| /** | |
| * Tells whether the error can already be displayed | |
| */ | |
| displayError() { | |
| if (this.hasBagError && !this.valid) { | |
| return true; | |
| } | |
| return (!this.valid && this.hasMinLength); | |
| }, | |
| /** | |
| * Checks if enough has been entered | |
| * to display error | |
| * @returns {boolean} | |
| */ | |
| hasMinLength() { | |
| return (this.value.length >= this.errorLength); | |
| }, | |
| /** | |
| * Has error from server request | |
| */ | |
| hasBagError() { | |
| return (this.errorBag.length > 0); | |
| } | |
| }, | |
| data() { | |
| return { | |
| valid: false, | |
| } | |
| }, | |
| methods: { | |
| /** | |
| * Every time that value prop changes this function will be called | |
| * @param val | |
| */ | |
| handleValueUpdates(val) { | |
| if (this.vFunction(val) === true) { | |
| return this.setAsValid(); | |
| } | |
| return this.setAsInvalid(); | |
| }, | |
| setAsValid() { | |
| this.valid = true; | |
| // this.$emit('form-input-validation', this.name, this.valid = true); | |
| }, | |
| setAsInvalid() { | |
| // this.$emit('form-input-validation', this.name, false); | |
| this.valid = false; | |
| }, | |
| } | |
| } | |
| </script> | |
| <style scoped> | |
| </style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Validate mobile numbers in Brazil | |
| const vMobile = (mobile) => { | |
| const m = mobile.replace(/\+|\)|\(| |-/g, ''); | |
| const regex = /^55[1-9]{2}9[1-9][0-9]{7}$/; | |
| const ddd = m.substring(3, 5); | |
| const ddds = ['11', '12', '13', '14', '15', '16', '17', '18', '19', '21', '22', '24', '27', '28', '31', '32', '33', '34', '35', '37', '38', '41', '42', '43', '44', '45', '46', '47', '48', '49', '51', '53', '54', '55', '61', '62', '63', '64', '65', '66', '67', '68', '69', '71', '73', '74', '75', '77', '79', '81', '82', '83', '84', '85', '86', '87', '88', '89', '91', '92', '93', '94', '95', '96', '97', '98', '99']; | |
| if (ddds.indexOf(ddd) < 0) { | |
| return false; | |
| } | |
| return regex.test(m); | |
| } | |
| export default vMobile ; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment