Forráskód Böngészése

Adding facility functionality with simple validation

Herton 7 éve
szülő
commit
700a836faf

+ 5 - 0
package-lock.json

@@ -8423,6 +8423,11 @@
       "integrity": "sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==",
       "dev": true
     },
+    "vuelidate": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/vuelidate/-/vuelidate-0.6.2.tgz",
+      "integrity": "sha512-rowo/OSwC8XEGdWg+ZgTpcgxYtmbQKbGOw4Z+lfT/BkNPoNyPEVgIeObUhhFO7Q7Lz0u0p429qfus/BHs9tMpg=="
+    },
     "vuex": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.0.1.tgz",

+ 109 - 21
src/components/Distributor-form.vue

@@ -5,10 +5,13 @@
       <b-form-group :label="labels.title"
                     label-for="distributor_title">
         <b-form-input id="distributor_title"
+                      :state="validations.title"
                       v-model="distributorLocal.title"
-                      required
                       :placeholder="labels.titlePlaceholder">
         </b-form-input>
+        <b-form-invalid-feedback>
+          {{labels.required}}
+        </b-form-invalid-feedback>
       </b-form-group>
        <!-- Notes Field -->
       <b-form-group :label="labels.notes"
@@ -33,24 +36,27 @@
         <!-- Inline contacts form -->
         <b-form inline v-for="(contact, key) in distributorLocal.contacts" :key="contact.id">
           <b-container>
-            <b-row>
-              <b-input-group class="col mb-3">
+            <b-row class="mb-3">
+              <b-input-group class="col">
                 <b-input v-model="contact.name"
+                :state="Boolean(contact.name)"
                 :placeholder="labels.name" />
               </b-input-group>
               
-              <b-input-group class="col mb-3">
+              <b-input-group class="col">
                 <b-input v-model="contact.email" 
+                    :state="emailValidation(contact.email)"
                     type="email"
-                    :placeholder="labels.email" />
+                    :placeholder="labels.email" 
+                    required/>
               </b-input-group>
 
-              <b-input-group class="col mb-3">
+              <b-input-group class="col">
                 <b-input v-model="contact.phone" 
                   :placeholder="labels.phone"/>
               </b-input-group>
 
-              <b-input-group class="col mb-3 col-sm-2">
+              <b-input-group class="col col-sm-2">
                 <b-button @click.stop="onDelete(key)" 
                   size="sm" 
                   v-b-tooltip.hover :title="labels.delete"
@@ -67,25 +73,35 @@
           <!-- Inline New contact -->
           <b-form inline v-if="newContact.show">
             <b-container>
-              <b-row>
-                <b-input-group class="col mb-3">
+              <b-row class="mb-4">
+                <b-input-group class="col">
                   <b-input v-model="newContact.name"
+                      :state="newContactState.name"
                       :placeholder="labels.name" />
+                    <b-form-invalid-feedback>
+                      {{labels.required}}
+                    </b-form-invalid-feedback>
                 </b-input-group>
 
-                <b-input-group class="col mb-3">
+                <b-input-group class="col">
                 <b-input v-model="newContact.email" 
                     type="email"
-                    :placeholder="labels.email" />
+                    :state="newContactState.email"
+                    :placeholder="labels.email" 
+                    required/>
+                    <b-form-invalid-feedback>
+                      {{labels.emailInvalid}}
+                    </b-form-invalid-feedback>
                 </b-input-group>
 
-                <b-input-group class="col mb-3">
+                <b-input-group class="col">
                   <b-input v-model="newContact.phone" 
                     :placeholder="labels.phone"/>
                 </b-input-group>
                 <!-- Saving new contact -->
-                <b-input-group class="col mb-3 col-sm-2">
-                  <b-button @click.stop="onSaveContact()" 
+                <b-input-group class="col col-sm-2">
+                  <b-button v-if="newContactState.email && newContactState.name"
+                      @click.stop="onSaveContact()" 
                       size="sm" 
                       class="mr-3"
                       v-b-tooltip.hover :title="labels.save"
@@ -103,7 +119,8 @@
               </b-row>
             </b-container>
           </b-form>
-          <b-button @click.stop="onAddContact()" class="mb-12 mr-sm-12"  variant="primary">{{labels.add}}</b-button>
+          <!-- Adding contacts -->
+          <b-button @click.stop="onAddContact()" class="mt-3 mb-12 mr-sm-12"  variant="primary">{{labels.add}}</b-button>
         </b-form-group>
     
         <b-form-group class="text-right">
@@ -119,7 +136,7 @@
 import {mapGetters, mapActions} from 'vuex';
 import * as types from '../store/types';
 import {store} from '../store/store';
-import {cloneDeep, debounce} from 'lodash';
+import {cloneDeep} from 'lodash';
 
 export default {
   props: {
@@ -143,6 +160,8 @@ export default {
         name: 'Name',
         email: 'Email',
         phone: 'Phone',
+        required: 'Field required',
+        emailInvalid: 'Email invalid or missing',
       },
       newContact: {
         show: false,
@@ -150,7 +169,9 @@ export default {
         email: '',
         phone: '',
       },
-      distributorLocal: {},
+      distributorLocal: {
+        contacts:[],
+      },
     }
   },
   computed: {
@@ -161,11 +182,50 @@ export default {
       distributor() {
         return this.$store.getters['distributor/GET_DISTRIBUTOR'](this.id)
       },
+      newContactState() {
+        let state = {
+          email: this.emailValidation(this.newContact.email),
+          name: this.newContact.name ? true : false,
+        };
+      return state;
+      },
+      validations() {
+        let validations = {
+          title: this.distributorLocal.title ? true : false,
+          contacts: this.distributorLocal.contacts.length ? this.distributorLocal.contacts.map( contact => {
+            return {
+              email: this.emailValidation(contact.email),
+              name: contact.name ? true : false,
+            }
+          }) : [],
+        };
+
+        if (validations.title  && !validations.contacts ) {
+            validations.pass = true;
+            return validations;
+          } else {
+
+            let contactsValid = true;
+            for (let element of validations.contacts) {
+                if (!element.email || !element.name) {
+                  // Checks each contact validation object and return false if any are false 
+                  contactsValid = false;
+                  break;
+                }
+              };
+            // Returns true if the title and contact fields are valid
+            validations.pass = (contactsValid && validations.title) ? true : false;
+          }
+
+        return validations;
+      },
   },
   watch: {
     id(newId) {
       if (newId) {
         this.distributorLocal = cloneDeep(this.distributor);
+      } else {
+        this.resetDistributor();
       }
     }
   },
@@ -173,19 +233,35 @@ export default {
     ...mapActions({
           saveDistributor: types.SET_DISTRIBUTOR,
       }),
-    onSubmit (ev) {
+    onSubmit() {
       this.saveDistributor({
         id: this.distributorLocal.id, 
         distributor: this.distributorLocal
       });
       this.$root.$emit('bv::hide::modal', 'distributor_modal_form');
     },
-    onAddContact () {
+    onAddContact() {
       this.newContact.show = true;
     },
     onSaveContact() {
-      this.distributorLocal.contacts.push(this.newContact);
-      this.newContact.show = false;
+      const newContact = cloneDeep(this.newContact);
+      this.distributorLocal.contacts.push(newContact);
+      this.resetNewContact();
+    },
+    resetNewContact() {
+      this.newContact = {
+        show: false,
+        success: false,
+        name: '',
+        email: '',
+        phone: '',   
+      }
+    },
+    resetDistributor() {
+      this.distributorLocal = {
+          title: '',
+          contacts:[],
+        };
     },
     onCancelSaveContact() {
       this.newContact.show = false;
@@ -195,6 +271,14 @@ export default {
     },
     onCancel() {
       this.$root.$emit('bv::hide::modal', 'distributor_modal_form');
+    },
+    emailValidation(email) {
+      if( /(.+)@(.+){2,}\.(.+){2,}/.test(email) ){
+        // valid email
+        return true;
+      } else {
+        return false;
+      }
     }
   },
   mounted() {
@@ -221,8 +305,12 @@ export default {
       }
     }
     .form-inline {
+      .input-group > .form-control:not(:last-child){
+        border-radius: 0.25rem;
+      }
       .input-group {
         padding-left: 0;
+        height: 39px;
       }
     }
   }

+ 5 - 2
src/components/Distributor.vue

@@ -28,7 +28,7 @@
         </b-table>
 
         <!-- Button to add Distributor-->
-        <b-button :pressed.sync="addDistributor" variant="primary">
+        <b-button @click.stop="addDistributor" variant="primary">
           {{labels.add_distributor}}
         </b-button>
       </div>
@@ -48,7 +48,6 @@ export default {
   },
   data () {
     return {
-      addDistributor: true,
       labels: {
         title: 'Distributor page',
         add_distributor: 'Add distributor',
@@ -77,6 +76,10 @@ export default {
     resetDistributorModal () {
       this.selectedId = null;
     },
+    addDistributor() {
+      this.selectedId = null;
+      this.$root.$emit('bv::show::modal', 'distributor_modal_form')
+    },
     ...mapActions({
       loadMockedDistributors: types.FETCH_DISTRIBUTORS,
     }),

+ 6 - 6
src/main.js

@@ -1,9 +1,9 @@
-import Vue from 'vue'
-import App from './App.vue'
-import Vuex from 'vuex'
-import VueRouter from 'vue-router'
-import {routes} from './routes'
-import Axios from 'axios'
+import Vue from 'vue';
+import App from './App.vue';
+import Vuex from 'vuex';
+import VueRouter from 'vue-router';
+import {routes} from './routes';
+import Axios from 'axios';
 import {store} from './store/store';
 
 // Setting up axios as the default $http method  

+ 3 - 12
src/store/modules/distributor/actions.js

@@ -50,21 +50,12 @@ export default {
      */
     [types.SET_DISTRIBUTOR]: ({commit, getters}, payload) => {
         if (payload.id) {
+            // api call
             // Update server with what changed
+        } else { debugger
             // api call
-            commit(types.UPDATE_DISTRIBUTOR, payload.distributor);
-        } else {
             // Add new distributor
-            // api call
-            let distributor = {
-                id: Math.floor(Math.random() * 9000),
-            }
-            commit(types.UPDATE_DISTRIBUTOR, 
-                Object.assign(
-                    distributor, 
-                    payload.distributor
-                )
-            );
         }
+        commit(types.UPDATE_DISTRIBUTOR, payload.distributor);
     },
 };

+ 6 - 0
src/store/modules/distributor/mutations.js

@@ -1,5 +1,6 @@
 import * as types from '../../types';
 import Vue from 'vue';
+import {cloneDeep} from 'lodash';
 
 export default {
     [types.UPDATE_DISTRIBUTORS]: (state, payload) => {
@@ -12,6 +13,11 @@ export default {
                     distributor = Object.assign(distributor, payload);
                 } 
             });
+        } else {
+            //Todo: remove this temporaty logic
+            let distributor = cloneDeep(payload);
+            distributor.id = Math.floor(Math.random() * 9000);
+            state.distributors.push(distributor);
         }
     }
 };