diff options
author | Mateja <mail@matejamaric.com> | 2021-07-24 18:58:17 +0200 |
---|---|---|
committer | Mateja <mail@matejamaric.com> | 2021-07-24 18:58:17 +0200 |
commit | d30fd3054c66d707a8210872b7db6cf4a1a98793 (patch) | |
tree | 6667713fc67fcaaa4e4dae291d95828fc5e802ad /client | |
parent | 080ca69a42ae8c510560bd176484adafd2c29a0c (diff) | |
download | mevn-ecommerce-d30fd3054c66d707a8210872b7db6cf4a1a98793.tar.gz mevn-ecommerce-d30fd3054c66d707a8210872b7db6cf4a1a98793.zip |
Added boilerplate pages and `ProductCard` component.
Diffstat (limited to 'client')
-rw-r--r-- | client/package-lock.json | 5 | ||||
-rw-r--r-- | client/package.json | 1 | ||||
-rw-r--r-- | client/src/App.vue | 14 | ||||
-rw-r--r-- | client/src/components/ExampleComponent.vue | 14 | ||||
-rw-r--r-- | client/src/components/ProductCard.vue | 20 | ||||
-rw-r--r-- | client/src/router/index.js | 34 | ||||
-rw-r--r-- | client/src/views/Checkout.vue | 9 | ||||
-rw-r--r-- | client/src/views/ExamplePage.vue | 5 | ||||
-rw-r--r-- | client/src/views/Home.vue | 11 | ||||
-rw-r--r-- | client/src/views/Login.vue | 77 | ||||
-rw-r--r-- | client/src/views/Product.vue | 30 | ||||
-rw-r--r-- | client/src/views/Register.vue | 111 |
12 files changed, 299 insertions, 32 deletions
diff --git a/client/package-lock.json b/client/package-lock.json index b7fc6a8..24dc872 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11229,6 +11229,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "validator": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz", + "integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/client/package.json b/client/package.json index 0ed3938..17dc6f0 100644 --- a/client/package.json +++ b/client/package.json @@ -11,6 +11,7 @@ "@popperjs/core": "^2.9.2", "bootstrap": "^5.0.2", "core-js": "^3.6.5", + "validator": "^13.6.0", "vue": "^3.0.0", "vue-router": "^4.0.0-0", "vuex": "^4.0.0-0" diff --git a/client/src/App.vue b/client/src/App.vue index c8219c0..3a66a9e 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -10,7 +10,13 @@ <router-link class="nav-link" active-class="active" to="/">Home</router-link> </li> <li class="nav-item"> - <router-link class="nav-link" active-class="active" to="/example">Example</router-link> + <router-link class="nav-link" active-class="active" to="/checkout">Checkout</router-link> + </li> + <li class="nav-item"> + <router-link class="nav-link" active-class="active" to="/register">Register</router-link> + </li> + <li class="nav-item"> + <router-link class="nav-link" active-class="active" to="/login">Login</router-link> </li> </ul> </div> @@ -21,4 +27,10 @@ </div> </template> +<script> +export default { + +} +</script> + <style lang="scss"></style> diff --git a/client/src/components/ExampleComponent.vue b/client/src/components/ExampleComponent.vue deleted file mode 100644 index 5e207f9..0000000 --- a/client/src/components/ExampleComponent.vue +++ /dev/null @@ -1,14 +0,0 @@ -<template> - <div> - <p v-text="msg"></p> - </div> -</template> - -<script> -export default { - name: 'ExampleComponent', - props: { - msg: String - } -} -</script> diff --git a/client/src/components/ProductCard.vue b/client/src/components/ProductCard.vue new file mode 100644 index 0000000..57698e5 --- /dev/null +++ b/client/src/components/ProductCard.vue @@ -0,0 +1,20 @@ +<template> + <div class="card"> + <img :src="productImg" class="card-img-top"> + <div class="card-body"> + <h5 class="card-title">{{ productName }}</h5> + <a :href="productLink" class="btn btn-dark w-100">Details</a> + </div> + </div> +</template> + +<script> +export default { + name: 'ProductCard', + props: { + productName: String, + productImg: String, + productLink: String + } +} +</script> diff --git a/client/src/router/index.js b/client/src/router/index.js index 22d739e..eee610c 100644 --- a/client/src/router/index.js +++ b/client/src/router/index.js @@ -1,6 +1,9 @@ import {createRouter, createWebHistory} from 'vue-router'; -import Home from '../views/Home.vue'; -import ExamplePage from '../views/ExamplePage.vue'; +import Home from '@/views/Home.vue'; +import Product from '@/views/Product.vue'; +import Checkout from '@/views/Checkout.vue'; +import Login from '@/views/Login.vue'; +import Register from '@/views/Register.vue'; const routes = [ { @@ -9,15 +12,30 @@ const routes = [ component: Home }, { - path: '/example', - name: 'Example', - component: ExamplePage + path: '/product/:id', + name: 'Product', + component: Product + }, + { + path: '/checkout', + name: 'Checkout', + component: Checkout + }, + { + path: '/login', + name: 'Login', + component: Login + }, + { + path: '/register', + name: 'Register', + component: Register } -] +]; const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes -}) +}); -export default router +export default router; diff --git a/client/src/views/Checkout.vue b/client/src/views/Checkout.vue new file mode 100644 index 0000000..42523ca --- /dev/null +++ b/client/src/views/Checkout.vue @@ -0,0 +1,9 @@ +<template> + Checkout page +</template> + +<script> +export default { + +} +</script> diff --git a/client/src/views/ExamplePage.vue b/client/src/views/ExamplePage.vue deleted file mode 100644 index 1cb803e..0000000 --- a/client/src/views/ExamplePage.vue +++ /dev/null @@ -1,5 +0,0 @@ -<template> - <div> - Example Page. - </div> -</template> diff --git a/client/src/views/Home.vue b/client/src/views/Home.vue index 77ed4e4..3e89885 100644 --- a/client/src/views/Home.vue +++ b/client/src/views/Home.vue @@ -1,15 +1,18 @@ <template> - <div> - <ExampleComponent msg="Example text inside example component."/> + <div class="row mt-5"> + <div class="col-lg-3 col-md-4 col-sm-6"> + <ProductCard/> + </div> </div> </template> <script> -import ExampleComponent from '@/components/ExampleComponent'; +import ProductCard from '@/components/ProductCard'; + export default { name: 'Home', components: { - ExampleComponent + ProductCard } } </script> diff --git a/client/src/views/Login.vue b/client/src/views/Login.vue new file mode 100644 index 0000000..8789a5e --- /dev/null +++ b/client/src/views/Login.vue @@ -0,0 +1,77 @@ +<template> + <div class="mt-5"> + <div class="row d-flex justify-content-center"> + <div class="col-md-7"> + <div class="card px-5 py-4"> + + <div class="text-center mb-4"> + <h4>Login</h4> + </div> + + <div class="forms-inputs mb-4"> + <span>Email</span> + <input type="text" v-model="email" + :class="{'form-control': true, 'is-invalid' : !validEmail(email) && emailBlured}" + @blur="emailBlured = true"> + <div class="invalid-feedback">A valid email is required!</div> + </div> + + <div class="forms-inputs mb-4"> + <span>Password</span> + <input type="password" v-model="password" + :class="{'form-control': true, 'is-invalid' : !validPassword(password) && passwordBlured}" + @blur="passwordBlured = true"> + <div class="invalid-feedback">Password is required!</div> + </div> + + <div class="forms-inputs mb-4"> + <button @click.stop.prevent="login" class="btn btn-dark w-100">Login</button> + </div> + + </div> + </div> + </div> + </div> +</template> + +<script> +import validator from 'validator'; + +export default { + name: 'Login', + data() { + return { + valid: false, + email: "", + emailBlured : false, + password: "", + passwordBlured:false + } + }, + methods: { + validEmail: (email) => validator.isEmail(email), + validPassword: (password) => password.length, + + validate() { + this.emailBlured = true; + this.passwordBlured = true; + if (this.validEmail(this.email) && this.validPassword(this.password)) { + this.valid = true; + } + }, + + login() { + this.validate(); + if (this.valid) { + alert('Successfully logged in!'); + } + } + } +} +</script> + +<style lang="scss"> + .forms-inputs input:focus { + border: 2px solid #000 + } +</style> diff --git a/client/src/views/Product.vue b/client/src/views/Product.vue new file mode 100644 index 0000000..e03c900 --- /dev/null +++ b/client/src/views/Product.vue @@ -0,0 +1,30 @@ +<template> + <div class="row"> + <div class="col-md-4"> + <img :src="productImg"> + </div> + <div class="col-md-4"> + <h3>{{ productName }}</h3> + <p>{{ productDescription }}</p> + <div class="btn btn-primary" @click="buy">Add to cart</div> + </div> + </div> +</template> + +<script> +export default { + name: 'Product', + data() { + return { + productName: String, + productDescription: String, + productImg: String + } + }, + methods: { + buy() { + + } + } +} +</script> diff --git a/client/src/views/Register.vue b/client/src/views/Register.vue new file mode 100644 index 0000000..e1679de --- /dev/null +++ b/client/src/views/Register.vue @@ -0,0 +1,111 @@ +<template> + <div class="mt-5"> + <div class="row d-flex justify-content-center"> + <div class="col-md-7"> + <div class="card px-5 py-4"> + <div class="form-data" v-if="!submitted"> + + <div class="text-center mb-4"> + <h4>Register</h4> + </div> + + <div class="forms-inputs mb-4"> + <span>First name</span> + <input type="text" v-model="firstname" + :class="{'form-control':true, 'is-invalid' : !validName(firstname) && firstnameBlured}" + @blur="firstnameBlured = true"> + <div class="invalid-feedback">A valid first name is required!</div> + </div> + + <div class="forms-inputs mb-4"> + <span>Last name</span> + <input type="text" v-model="lastname" + :class="{'form-control':true, 'is-invalid' : !validName(lastname) && lastnameBlured}" + @blur="lastnameBlured = true"> + <div class="invalid-feedback">A valid last name is required!</div> + </div> + + <div class="forms-inputs mb-4"> + <span>Email</span> + <input type="text" v-model="email" + :class="{'form-control':true, 'is-invalid' : !validEmail(email) && emailBlured}" + @blur="emailBlured = true"> + <div class="invalid-feedback">A valid email is required!</div> + </div> + + <div class="forms-inputs mb-4"> + <span>Password</span> + <input type="password" v-model="password" + :class="{'form-control':true, 'is-invalid' : !validPassword(password) && passwordBlured}" + @blur="passwordBlured = true"> + <div class="invalid-feedback">Password must be 8 character!</div> + </div> + + <div class="mb-3"> + <button @click.stop.prevent="submit" class="btn btn-dark w-100">Register</button> + </div> + + </div> + <div class="success-data" v-else> + + <div class="text-center d-flex flex-column"> + <span class="text-center">You have been successfully registered!</span> + </div> + + </div> + </div> + </div> + </div> + </div> +</template> + +<script> +import validator from 'validator'; + +export default { + name: 'Register', + data() { + return { + valid : false, + submitted : false, + firstname: "", + firstnameBlured: false, + lastname: "", + lastnameBlured: false, + email : "", + emailBlured : false, + password:"", + passwordBlured:false, + } + }, + methods: { + validate() { + this.firstnameBlured = true; + this.lastnameBlured = true; + this.emailBlured = true; + this.passwordBlured = true; + if (this.validName(this.firstname) && this.validName(this.lastname) && this.validEmail(this.email) && this.validPassword(this.password)) { + this.valid = true; + } + }, + + validEmail: (email) => validator.isEmail(email), + //validPassword: (password) => validator.isStrongPassword(password, { minLength: 8 }), + validPassword: (password) => password.length > 7, + validName: (name) => validator.isAlpha(name) && name.length, + + submit() { + this.validate(); + if (this.valid) { + this.submitted = true; + } + } + } +} +</script> + +<style lang="scss"> + .forms-inputs input:focus { + border: 2px solid #000 + } +</style> |