Commit 496651de authored by catea792's avatar catea792
parents ffcb4ea2 c70504d5
<template>
<div class=" page-header dark-section">
<h3 class="page-subtitle">
categories
</h3>
<h2 class="page-title">
BREADCRUMB
</h2>
<ul class="breadcrumb">
<v-breadcrumbs :items="items">
<template #divider>
<v-icon>mdi-chevron-right</v-icon>
</template>
</v-breadcrumbs>
</ul>
</div>
</template>
<script>
export default {
name: 'BreadCrumb',
computed: {
items () {
const items = [{ text: 'Home', disabled: false, href: '/' }]
this.$route.matched.forEach((route) => {
if (route.name) {
items.push({ text: route.name, disabled: false, href: route.path })
}
})
return items
}
}
}
</script>
<style scope>
.page-header {
background-image: url(https://d-themes.com/html/riode/images/shop/page-header-back.jpg);
background-color: #3C63A4;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 250px;
padding: 3em 1em;
background-color: #C8C3BF;
background-position: center;
background-size: cover;
text-align: center;
color: #222;
width: 100vw;
margin-top: 10px;
}
.breadcrumb {
display: flex;
flex-wrap: wrap;
align-items: center;
color: #666;
font-family: Poppins,sans-serif;
font-size: 1.4rem;
}
.v-application a {
color: #fff !important;
}
.page-title {
margin-bottom: 0;
text-transform: uppercase;
font-size: 4rem;
line-height: 1.125;
color: #222;
color: #fff;
}
.page-subtitle {
margin-bottom: 0.5rem;
text-transform: uppercase;
font-size: 2rem;
line-height: 1.2;
color: #fff;
}
</style>
<!-- eslint-disable vue/no-template-shadow -->
<template>
<v-row
justify="center"
>
<v-dialog
v-model="dialogDetail"
width="900px"
min-height="550px"
>
<v-row class="flex-row justify-center">
<v-col>
<v-carousel hide-delimiters :show-arrows="hover" :width="400">
<v-carousel-item
v-for="(item, i) in images"
:key="i"
:width="400"
:heigh="400"
:src="item"
cover
/>
</v-carousel>
</v-col>
<v-col>
<v-card-title v-model="item.name" class="modal-title" style="margin-left:-30px">
{{ name }}
</v-card-title>
<v-row class="flex-row align-center">
<h3 class="mr-4">
Price:
</h3>
<v-card-title v-model="item.price">
{{ price + "$" }}
</v-card-title>
</v-row>
<v-card-text v-model="item.description" class="descrip">
{{ description }}
</v-card-text>
<v-row class="flex-row justify-center align-center">
<h3 class="mr-4">
Color
</h3>
<v-row
cols="12"
>
<v-radio-group
v-model="color_modal"
row
mandatory
class="square-radio"
>
<v-radio
label="red"
color="red"
value="red"
class="square-radio"
/>
<v-radio
label="blue"
color="primary"
value="red darken-3"
class="square-radio"
/>
<v-radio
label="yellow"
color="yellow"
value="yellow"
class="square-radio"
/>
</v-radio-group>
</v-row>
</v-row>
<v-row class="flex-row justify-start align-center">
<h3 class="mr-4">
Size
</h3>
<v-btn-toggle
v-model="size_modal"
color="primary"
mandatory
>
<v-btn value="S">
S
</v-btn>
<v-btn value="M">
M
</v-btn>
<v-btn value="L">
L
</v-btn>
</v-btn-toggle>
</v-row>
<v-row class="mt-7">
<v-divider :thickness="2" />
</v-row>
<v-row cols="12" md="2" class="flex-row align-center">
<h3 class="mr-4">
Quantity
</h3>
<v-col md="2">
<v-text-field
v-model="quantity_modal"
type="number"
/>
</v-col>
<v-btn color="primary" dense @click="addProductToCard()">
Add to card (+)
</v-btn>
<v-btn
plain
>
<v-icon large>
mdi-heart-outline
</v-icon>
</v-btn>
</v-row>
<v-row class="mb-1">
<v-divider :thickness="2" />
</v-row>
<v-row>
<v-icon class="mx-2">
mdi-twitter
</v-icon>
<v-icon class="mx-2">
mdi-facebook
</v-icon>
<v-icon class="mx-2">
mdi-instagram
</v-icon>
</v-row>
</v-col>
</v-row>
</v-dialog>
</v-row>
</template>
<script>
import { eventBus } from '~/plugins/eventBus.js'
export default {
name: 'DetailModal',
props: {
status: {
type: Boolean,
default: false
},
name: {
type: String,
required: true
},
price: {
type: String,
required: true
},
description: {
type: String,
required: true
},
images: {
type: Array,
required: true
},
product_id: {
type: String,
required: true
}
},
data: () => ({
selected: '',
item: {
name: '',
price: '',
description: ''
},
size_modal: undefined,
color_modal: undefined,
quantity_modal: ''
}),
computed: {
dialogDetail () {
return this.status
}
},
methods: {
closeDialog () {
this.$props.status = false
},
addProductToCard () {
const fd = new FormData()
fd.append('product_id', this.product_id)
fd.append('color', this.color_modal)
fd.append('size', this.size_modal)
fd.append('quantity', this.quantity_modal)
this.$axios
.post('/carts/add-to-cart', fd, {
headers: {
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
}
})
.then((response) => {
this.$toast.success('Add product successfully!', {
duration: 3000
})
this.$props.status = false
eventBus.$emit('add-to-cart', response)
})
.catch((errors) => {
this.$toast.error('something went wrong while trying create!', {
duration: 3000
})
})
}
}
}
</script>
<style scoped>
::v-deep .v-dialog{
background-color: white;
}
.square-radio .v-input--selection-controls__input {
border-radius: 0 !important;
width: 24px !important;
height: 24px !important;
}
.square-radio .v-input--selection-controls__ripple {
border-radius: 50% !important;
}
.square-radio .v-input--selection-controls__input:checked:before {
border-radius: 50% !important;
}
.modal-title {
font-size: 30px;
font-weight: bold;
margin-left:-30px;
margin-top:10px;
}
.hex-variant {
/* margin-top:0px; */
}
.descrip {
margin-left:-30px;
}
.v-dialog {
overflow: hidden;
}
</style>
<!-- eslint-disable vue/no-parsing-error -->
<template> <template>
<v-footer dark padless> <v-footer class="mt-12 flex-wrap" min-height="350px" dark padless>
<v-card flat tile class="indigo lighten-1 white--text text-center"> <v-row class="d-flex justify-space-between align-center">
<v-card-text> <v-col
<v-btn v-for="icon in icons" :key="icon" class="mx-4 white--text" icon> cols="12"
<v-icon size="24px"> md="3"
{{ icon }}
</v-icon>
</v-btn>
</v-card-text>
<v-card-text class="white--text pt-0">
Phasellus feugiat arcu sapien, et iaculis ipsum elementum sit amet.
Mauris cursus commodo interdum. Praesent ut risus eget metus luctus
accumsan id ultrices nunc. Sed at orci sed massa consectetur dignissim a
sit amet dui. Duis commodo vitae velit et faucibus. Morbi vehicula
lacinia malesuada. Nulla placerat augue vel ipsum ultrices, cursus
iaculis dui sollicitudin. Vestibulum eu ipsum vel diam elementum tempor
vel ut orci. Orci varius natoque penatibus et magnis dis parturient
montes, nascetur ridiculus mus.
</v-card-text>
<v-divider />
<div class="footer-bottom">
<div class="footer-bottom-left">
<figure class="payment">
<img
src="~/assets/images/payment.png"
alt="payment"
width="159"
height="29"
> >
</figure> <v-img
width="153px"
src="https://d-themes.com/html/riode/images/logo-footer.png"
/>
</v-col>
<div class="flex-column">
<h3>Subscribe to our Newsletter</h3>
<h4>Get all the latest information, Sales and Offers.</h4>
</div> </div>
<p class="copyright"> <v-col
Riode eCommerce © 2022. All Rights Reserved cols="12"
</p> md="4"
<div class="footer-bottom-right">
<div class="social-link">
<v-btn
v-for="icon in icons"
:key="icon"
class="mx-4 white--text"
icon
> >
<v-icon size="24px"> <v-text-field label="email address here ..."></v-text-field>
{{ icon }} </v-col>
</v-icon> <v-btn color="primary">SUBSCRIBE</v-btn>
</v-btn> </v-row>
</div> <v-divider></v-divider>
</div>
</div>
</v-card>
</v-footer> </v-footer>
</template> </template>
<script> <script>
export default { export default {
name: 'FooterBar',
data: () => ({ data: () => ({
icons: ['mdi-facebook', 'mdi-twitter', 'mdi-linkedin', 'mdi-instagram'] icons: ['mdi-facebook', 'mdi-twitter', 'mdi-linkedin', 'mdi-instagram'],
img: 'https://d-themes.com/html/riode/images/logo-footer.png'
}) })
} }
</script> </script>
<style> <style></style>
.footer-bottom-left {
position: absolute;
left: 0;
}
.footer-bottom-right {
position: absolute;
right: 0;
}
.copyright {
position: absolute;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
}
</style>
<template>
<v-row
justify="center"
>
<v-dialog
v-model="dialog"
width="450px"
@click:outside="closeDialog"
>
<v-card-title class="justify-center">
<p class="font-weight-black" style="font-size: 35px">
LOGIN
</p>
</v-card-title>
<v-form ref="form" justify="center" class="formlogin">
<v-col cols="12" sm="6" md="12">
<v-text-field
v-model="email"
variant="underlined"
label="Email"
required
/>
</v-col>
<v-col cols="12" sm="6" md="12">
<v-text-field
v-model="password"
variant="underlined"
label="Password"
required
/>
</v-col>
<v-col cols="12" sm="6" md="12" justify-content: space-between>
<v-checkbox
label="Remember me"
/>
</v-col>
<div class="d-flex flex-column">
<v-btn
color="primary"
class="mt-4"
block
@click="login"
>
Login
</v-btn>
<v-btn
color="primary"
class="mt-4"
block
@click="$emit('close')"
>
Close
</v-btn>
</div>
</v-form>
<v-col cols="12" style="display:flex">
<v-divider sm="6" /> login with <v-divider sm="6" />
</v-col>
<v-col cols="12" style="text-align: center;">
<v-icon>
mdi-twitter
</v-icon>
<v-icon>
mdi-facebook
</v-icon>
<v-icon>
mdi-instagram
</v-icon>
</v-col>
</v-dialog>
</v-row>
</template>
<script>
export default {
name: 'LoginModal',
props: {
status: {
type: Boolean,
default: true
}
},
data: () => ({
email: '',
password: ''
}),
computed: {
dialog () {
return this.status
}
},
methods: {
async login () {
try {
const resp = await this.$axios.post('/login',
{
email: this.email,
password: this.password
})
localStorage.setItem('token', resp.data.data.bearer_token)
this.$auth.$storage.setUniversal('token', resp.data.data.bearer_token)
this.$auth.$storage.setUniversal('userName', resp.data.data.name)
this.$auth.$storage.setUniversal('loggedIn', 'true')
if (resp.status === 200) {
this.$toast.success('Successfully authenticated', {
duration: 2000
})
this.$router.push('home')
}
} catch (e) {
this.$toast.error('Username or Password not valid', {
duration: 2000
})
this.$router.push('/login')
}
},
closeDialog () {
this.$props.status = false
}
}
}
</script>
<style scoped>
.formlogin {
padding: 30px;
}
::v-deep .v-dialog{
background-color: #5ae2dc;
}
</style>
<template>
<v-carousel
cycle
height="550"
hide-delimiter-background
show-arrows-on-hover
>
<v-carousel-item
v-for="(slide, i) in slides"
:key="i"
:src="img[i]"
>
<v-row
class="fill-height"
align="center"
justify="center"
>
<div class="text-h2">
{{ slide }} Slide
</div>
</v-row>
</v-carousel-item>
</v-carousel>
</template>
<script>
export default {
name: 'PageCarousels',
data () {
return {
img: [
'https://d-themes.com/html/riode/images/demos/demo1/slides/slide1.jpg',
'https://d-themes.com/html/riode/images/demos/demo1/slides/slide2.jpg'
],
slides: [
'First',
'Second'
]
}
}
}
</script>
<style>
.v-window__container {
margin-top: 20px;
}
</style>
<template>
<v-row justify="center">
<v-dialog
v-model="dialog"
width="450px"
@click:outside="closeDialog"
>
<v-card-title class="justify-center">
<p class="font-weight-black" style="font-size: 35px">
REGISTER
</p>
</v-card-title>
<v-form ref="form" justify="center" class="formlogin">
<v-col cols="12" sm="6" md="12">
<v-text-field
v-model="name"
variant="underlined"
label="Name"
:rules="requiredRules"
required
/>
</v-col>
<v-col cols="12" sm="6" md="12">
<v-text-field
v-model="email"
variant="underlined"
label="Email"
:rules="emailRules"
required
/>
</v-col>
<v-col cols="12" sm="6" md="12">
<v-text-field
v-model="password"
variant="underlined"
label="Password"
type="password"
:rules="passwordRules"
required
/>
</v-col>
<v-col cols="12" sm="6" md="12">
<v-text-field
v-model="password_confirmation"
variant="underlined"
label="Confirm your password"
type="password"
:rules="[passwordRules, passwordConfirmationRule]"
required
/>
</v-col>
<v-col cols="12" sm="6" md="12" justify-content: space-between>
<v-checkbox
v-model="checkbox"
label="I agree to the privacy policy"
/>
</v-col>
<div class="d-flex flex-column">
<v-btn
color="primary"
class="mt-4"
block
@click="signup"
>
Sign Up
</v-btn>
<v-btn
color="primary"
class="mt-4"
block
@click="$emit('close')"
>
Close
</v-btn>
</div>
</v-form>
<v-col cols="12" style="display:flex">
<v-divider sm="6" /> login with <v-divider sm="6" />
</v-col>
<v-col cols="12" style="text-align: center;">
<v-icon>
mdi-twitter
</v-icon>
<v-icon>
mdi-facebook
</v-icon>
<v-icon>
mdi-instagram
</v-icon>
</v-col>
</v-dialog>
</v-row>
</template>
<script>
export default {
name: 'SignupModal',
props: {
status: {
type: Boolean,
default: false
}
},
data: () => ({
name: '',
email: '',
password: '',
password_confirmation: '',
checkbox: '',
requiredRules: [
v => !!v || 'This field is required'
],
emailRules: [
v => !!v || 'E-mail is required',
v => /.+@.+\..+/.test(v) || 'E-mail must be valid'
],
passwordRules: [
v => !!v || 'Password is required',
v => (v && v.length >= 6) || 'Password must be more than 6 characters',
v => (v && v.length <= 255) || 'Password must be less than 255 characters'
]
}),
computed: {
dialog () {
return this.status
},
passwordConfirmationRule () {
return () => (this.password === this.password_confirmation) || 'Password must match'
}
},
methods: {
async signup () {
try {
await this.$axios.post('/register', {
name: this.name,
email: this.email,
password: this.password,
password_confirmation: this.password_confirmation
}
).then((resp) => {
if (resp.data.status === 'success') {
this.$toast.success('Register successfully', {
duration: 2000
})
this.$router.push('login')
}
})
} catch (error) {
this.$toast.error(error.response.data.message, {
duration: 2000
})
}
},
closeDialog () {
this.$props.status = false
}
}
}
</script>
<style scoped>
.formlogin {
padding: 30px;
}
::v-deep .v-dialog{
background-color: #5ae2dc;
}
</style>
This diff is collapsed.
<template>
<v-container>
<div class="navbar d-flex justify-space-between ">
<div class="d-flex justify-space-between col-md-7">
<div>
<span>
Home
</span>
</div>
<div class="dropdown">
<span>
Products
</span>
<v-icon>mdi-chevron-down</v-icon>
<div class="dropdown-content elevation-10" :elevation="2">
<v-treeview
:active.sync="active"
rounded
dense
hoverable
activatable
:items="categories"
@update:active="setCategory(item)"
>
<template #label="{ item }">
<nuxt-link :to="`/home-page/categories/${item.id}`" tag="div">
{{ item.name }}
</nuxt-link>
</template>
</v-treeview>
</div>
</div>
<div>
<span>
Pages
</span>
</div>
<div>
<span>
Blogs
</span>
</div>
<div>
<span>
About
</span>
</div>
</div>
<div class="d-flex align-center ">
<v-icon>mdi-tag</v-icon>
<span class="mx-2">
Special offer!
</span>
<span class="mx-2">
Buy riode
</span>
</div>
</div>
</v-container>
</template>
<script>
import { mapActions, mapState } from 'vuex'
export default {
name: 'NavBar',
data: () => ({
active: [],
open: [],
categories: []
}),
computed: {
...mapState(['selectedCategory']),
...mapActions(['setSelectedCategory']),
selected () {
if (!this.active.length) { return undefined }
const id = this.active[0]
console.log(id)
// console.log(this.categories.find(category => category.id === id).name)
return this.categories.find(category => category.id === id) || ''
}
},
watch: {
selected () {
if (!this.active.length) { return undefined }
const id = this.active[0]
return id || ''
}
},
beforeCreate () {
this.$axios
.get('guest/categories/index')
.then((response) => {
this.categories = response.data.data
})
.catch(function (error) {
console.log(error)
})
},
mounted () {
},
methods: {
setCategory () {
console.log(this.selected)
this.$store.commit('category/setCurrentCategory', this.selected.name || '')
}
}
}
</script>
<style scoped>
.navbar span {
font-weight: bold;
cursor: pointer;
transition: 0.3s;
}
.navbar span:hover {
color: #26c;
}
.dropdown {
position: relative;
}
.dropdown:hover .dropdown-content {
display: block;
}
.dropdown-content {
display: none;
position: absolute;
z-index: 1;
background-color: #ffffff;
min-width: 350px;
/* margin-top: 20px; */
}
</style>
<style>
div .v-treeview-node__label {
cursor: pointer;
}
</style>
<template>
<nuxt />
</template>
\ No newline at end of file
<template>
<v-app>
<UserHeader ref="child" />
<Nuxt />
<FooterBar />
</v-app>
</template>
<script>
import Header from '@/components/user/Header'
import FooterBar from '@/components/FooterBar'
export default {
component: {
Header,
FooterBar
},
components: { FooterBar },
created () {
this.changeColor()
},
methods: {
changeColor () {
this.$vuetify.theme.dark = !this.$vuetify.theme.dark
return true
}
}
}
</script>
<style>
body{
font-family: monospace;
}
</style>
...@@ -29,7 +29,8 @@ export default { ...@@ -29,7 +29,8 @@ export default {
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [ plugins: [
'~/plugins/axios.js', '~/plugins/axios.js',
'~/plugins/formatTime.js' '~/plugins/formatTime.js',
'~/plugins/eventBus.js'
], ],
// Auto import components: https://go.nuxtjs.dev/config-components // Auto import components: https://go.nuxtjs.dev/config-components
......
<template> <template>
<div> <div>
<div> <div>
<h1 style="text-align: center">ABOUT</h1> <h1 style="text-align: center">
ABOUT
</h1>
</div> </div>
</div> </div>
</template> </template>
<!-- eslint-disable vue/no-v-for-template-key -->
<!-- eslint-disable vue/html-end-tags -->
<!-- eslint-disable vue/no-unused-vars -->
<template>
<div>
<BreadCrumb :items="breadcrumbItems" />
<v-container class="pa-0">
<v-row class="d-flex align-center pl-2 mt-2">
<v-col>
<v-hover v-slot="{ hover }">
<v-btn outlined :style="{ 'background-color': hover ? '#1976d2' : '#f5f5f5','color':hover ? '#f5f5f5' : 'black' }">
FILTER
</v-btn>
</v-hover>
</v-col>
</v-row>
<v-row class="pt-5 pb-5">
<v-col
v-for="(item, i) in pagedCards"
:key="i"
cols="12"
md="3"
>
<v-hover
v-slot="{ hover }"
:elevation="hover ? 12 : 2"
:class="{ 'on-hover': hover }"
>
<v-card
:elevation="hover ? 16 : 2"
:class="{ 'on-hover': hover }"
class="mx-auto pa-2 ma-3"
max-width="280"
link
>
<div>
<v-img
:src="item.images[0]"
height="250px"
cover
/>
</div>
<v-card-title class="d-flex justify-center">
{{ item.name }}
</v-card-title>
<v-card-subtitle class="d-flex justify-center">
{{ item.price + "$" }}
</v-card-subtitle>
<v-card-actions class="d-flex justify-center">
<v-btn
:class="{ 'show-btns': hover }"
icon
@click="getDataItem"
>
<v-icon
:class="{ 'show-btns': hover }"
>
mdi-cart
</v-icon>
</v-btn>
<v-btn
:class="{ 'show-btns': hover }"
icon
@click="addToWishlish(item)"
>
<v-icon
:class="{ 'show-btns': hover }"
>
mdi-heart
</v-icon>
</v-btn>
<v-btn
:class="{ 'show-btns': hover }"
icon
@click="openDialogDetail(); getDataItem(item)"
>
<v-icon
:class="{ 'show-btns': hover }"
>
mdi-magnify
</v-icon>
</v-btn>
</v-card-actions>
</v-card>
</v-hover>
</v-col>
</v-row>
<v-divider />
<v-row class="d-flex align-center justify-space-between pl-2 mt-2">
<div class="text-center">
<v-pagination v-model="currentPage" :total-visible="totalVisiblePages" :length="totalPages" class="my-3" circle>
<template #prev="{ active, disabled }">
<v-btn small class="mr-2" :disabled="disabled" @click="prevPage">
<v-icon small>
mdi-chevron-left
</v-icon>
</v-btn>
</template>
<template #next="{ active, disabled }">
<v-btn small class="ml-2" :disabled="disabled" @click="nextPage">
<v-icon small>
mdi-chevron-right
</v-icon>
</v-btn>
</template>
</v-pagination>
</div>
</v-row>
</v-container>
<DetailModal
:status="activeDetail"
:name="productModal.name"
:price="productModal.price"
:description="productModal.description"
:images="productModal.images"
:product_id="productModal.id"
@close="activeDetail=false"
/>
</div>
</template>
<script>
import BreadCrumb from '@/components/BreadCrumb'
import DetailModal from '@/components/DetailModal'
import { eventBus } from '~/plugins/eventBus.js'
export default {
layout: 'user',
component: {
BreadCrumb,
DetailModal
},
data: () => {
return {
activeDetail: false,
breadcrumbItems: [
{
text: 'Home',
disabled: false,
href: '/home'
},
{
text: 'Element',
disabled: false,
href: '/'
},
{
text: 'Post',
disabled: false,
href: '/posts'
}
],
icons: ['mdi-cart', 'mdi-heart', 'mdi-magnify'],
products: [],
page: 1,
productModal: {
name: '',
price: '',
description: '',
images: []
},
profile: {
name: '',
price: '',
description: ''
},
itemsPerPage: 8,
currentPage: 1,
wishlish: []
}
},
computed: {
totalPages () {
return Math.ceil(this.products.length / this.itemsPerPage)
},
pagedCards () {
const startIndex = (this.currentPage - 1) * this.itemsPerPage
const endIndex = startIndex + this.itemsPerPage
return this.products.slice(startIndex, endIndex)
},
totalVisiblePages () {
return Math.min(this.totalPages, 7)
}
},
created () {
this.getProductByCategoryId()
},
methods: {
async getProductByCategoryId () {
const resp = await this.$axios.get(`/guest/categories/products-by-category-id/${this.$route.params.id}`, {
headers: {
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
}
})
.then(response => (this.products = response.data.data[0].products))
.catch(function (error) {
console.log(error)
})
console.log(resp[0].products)
console.log(this.products[0].images[0])
},
openDialogDetail () {
this.activeDetail = false
this.activeDetail = true
},
getDataItem (item) {
console.log(item)
this.productModal = item
console.log(this.productModal.name)
},
saveProfile (data) {
this.profile = this.productModal
},
nextPage () {
this.currentPage++
},
prevPage () {
this.currentPage--
},
addToWishlish (item) {
const fd = new FormData()
fd.append('product_id', item.id)
this.$axios
.post('/wish-list/add-to-wish-list',
fd,
{
headers: {
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
}
})
.then((response) => {
console.log(response)
this.$toast.success('Add product successfully!', {
duration: 2000
})
eventBus.$emit('add-to-wish-list', response)
})
.catch((errors) => {
this.$toast.error('something went wrong!', {
duration: 2000
})
})
}
}
}
</script>
<style lang="scss" scoped>
.v-card {
transition: opacity .4s ease-in-out;
}
.v-card:not(.on-hover) {
opacity: 0.9;
}
.show-btns {
color: #1976d2 !important;
}
.mdi-fast-forward::before {
content: "\F0211";
}
.mdi:before, .mdi-set {
display: inline-block;
font: normal normal normal 24px/1 "Material Design Icons";
font-size: inherit;
text-rendering: auto;
line-height: inherit;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
::before, ::after {
text-decoration: inherit;
vertical-align: inherit;
}
*, ::before, ::after {
background-repeat: no-repeat;
box-sizing: inherit;
}
.v-btn--icon.v-size--default .v-icon, .v-btn--fab.v-size--default .v-icon {
height: 24px;
font-size: 24px;
width: 24px;
}
.v-btn > .v-btn__content .v-icon {
color: rgba(255, 255, 255, 1);
}
</style>
<!-- eslint-disable vue/no-v-for-template-key -->
<!-- eslint-disable vue/html-end-tags -->
<!-- eslint-disable vue/no-unused-vars -->
<template>
<div>
<BreadCrumb />
<v-container class="pa-0">
<v-row class="d-flex align-center pl-2 mt-2">
<v-col>
<v-hover v-slot="{ hover }">
<v-btn outlined :style="{ 'background-color': hover ? '#1976d2' : '#f5f5f5','color':hover ? '#f5f5f5' : 'black' }">
FILTER
</v-btn>
</v-hover>
</v-col>
</v-row>
<v-row class="pt-5 pb-5">
<v-col
v-for="(item, i) in items"
:key="i"
cols="12"
md="3"
>
<v-hover
v-slot="{ hover }"
:elevation="hover ? 12 : 2"
:class="{ 'on-hover': hover }"
>
<v-card
:elevation="hover ? 16 : 2"
:class="{ 'on-hover': hover }"
class="mx-auto pa-2 ma-3"
max-width="280"
link
>
<div>
<v-img
:src="item.images"
height="250px"
cover
/>
<!-- <v-card-actions v-if="hover" class="d-flex align-center justify-center" style="position: absolute">
<v-btn
v-for="(icon, index) in icons"
:key="index"
:class="{ 'show-btns': hover }"
icon
>
<v-icon
:class="{ 'show-btns': hover }"
>
{{ icon }}
</v-icon>
</v-btn>
</v-card-actions> -->
</div>
<v-card-title class="d-flex justify-center">
{{ item.name }}
</v-card-title>
<v-card-subtitle class="d-flex justify-center">
{{ item.price }}
</v-card-subtitle>
<v-card-actions class="d-flex justify-center">
<v-btn
:class="{ 'show-btns': hover }"
icon
>
<v-icon
:class="{ 'show-btns': hover }"
>
mdi-cart
</v-icon>
</v-btn>
<v-btn
:class="{ 'show-btns': hover }"
icon
>
<v-icon
:class="{ 'show-btns': hover }"
>
mdi-heart
</v-icon>
</v-btn>
<v-btn
:class="{ 'show-btns': hover }"
icon
>
<v-icon
:class="{ 'show-btns': hover }"
>
mdi-magnify
</v-icon>
</v-btn>
</v-card-actions>
</v-card>
</v-hover>
</v-col>
</v-row>
<v-divider />
<v-row class="d-flex align-center justify-space-between pl-2 mt-2">
<div class="text-center">
<v-pagination
v-model="page"
:length="4"
prev-icon="mdi-menu-left"
next-icon="mdi-menu-right"
/>
</div>
</v-row>
</v-container>
</div>
</template>
<script>
import BreadCrumb from '@/components/BreadCrumb'
export default {
components: { BreadCrumb },
layout: 'user',
component: {
BreadCrumb
},
data: () => {
return {
items: [
{
images: 'https://cdn.vuetifyjs.com/images/cards/sunshine.jpg',
name: 'Brunch this weekend?',
price: '50$'
},
{
images: 'https://cdn.vuetifyjs.com/images/cards/sunshine.jpg',
name: 'Brunch this weekend?',
price: '50$'
},
{
images: 'https://cdn.vuetifyjs.com/images/cards/sunshine.jpg',
name: 'Brunch this weekend?',
price: '50$'
},
{
images: 'https://cdn.vuetifyjs.com/images/cards/sunshine.jpg',
name: 'Brunch this weekend?',
price: '50$'
},
{
images: 'https://cdn.vuetifyjs.com/images/cards/sunshine.jpg',
name: 'Brunch this weekend?',
price: '50$'
},
{
images: 'https://cdn.vuetifyjs.com/images/cards/sunshine.jpg',
name: 'Brunch this weekend?',
price: '50$'
},
{
images: 'https://cdn.vuetifyjs.com/images/cards/sunshine.jpg',
name: 'Brunch this weekend?',
price: '50$'
},
{
images: 'https://cdn.vuetifyjs.com/images/cards/sunshine.jpg',
name: 'Brunch this weekend?',
price: '50$'
}
],
icons: ['mdi-cart', 'mdi-heart', 'mdi-magnify'],
products: [],
page: 1
}
},
created () {
this.getProductByCategoryId()
},
methods: {
async getProductByCategoryId () {
const resp = await this.$axios.get('/guest/categories/products-by-category-id/1', {
headers: {
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
}
})
.then(response => (this.products = response.data.data[0].products))
.catch(function (error) {
console.log(error)
})
console.log(resp[0].products)
console.log(this.products[0])
}
}
}
</script>
<style lang="scss" scoped>
.v-card {
transition: opacity .4s ease-in-out;
}
.v-card:not(.on-hover) {
opacity: 0.9;
}
.show-btns {
color: #1976d2 !important;
}
.mdi-fast-forward::before {
content: "\F0211";
}
.mdi:before, .mdi-set {
display: inline-block;
font: normal normal normal 24px/1 "Material Design Icons";
font-size: inherit;
text-rendering: auto;
line-height: inherit;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
::before, ::after {
text-decoration: inherit;
vertical-align: inherit;
}
*, ::before, ::after {
background-repeat: no-repeat;
box-sizing: inherit;
}
.v-btn--icon.v-size--default .v-icon, .v-btn--fab.v-size--default .v-icon {
height: 24px;
font-size: 24px;
width: 24px;
}
.v-btn > .v-btn__content .v-icon {
color: rgba(255, 255, 255, 1);
}
</style>
<template>
<div>
<!-- Banners -->
<PageCarousels />
</div>
</template>
<script>
import PageCarousels from '@/components/PageCarousels'
export default {
layout: 'user',
component: {
PageCarousels
}
}
</script>
<style>
</style>
...@@ -120,6 +120,7 @@ export default { ...@@ -120,6 +120,7 @@ export default {
localStorage.setItem('token', resp.data.data.bearer_token) localStorage.setItem('token', resp.data.data.bearer_token)
this.$auth.$storage.setUniversal('token', resp.data.data.bearer_token) this.$auth.$storage.setUniversal('token', resp.data.data.bearer_token)
this.$auth.$storage.setUniversal('userName', resp.data.data.name) this.$auth.$storage.setUniversal('userName', resp.data.data.name)
this.$auth.$storage.setUniversal('ID', resp.data.data.id)
this.$auth.$storage.setUniversal('loggedIn', 'true') this.$auth.$storage.setUniversal('loggedIn', 'true')
if (resp.status === 200) { if (resp.status === 200) {
this.$toast.success('Successfully authenticated', { this.$toast.success('Successfully authenticated', {
......
import Vue from 'vue'
export const eventBus = new Vue()
export const state = () => ({
currentCategory: ''
})
export const mutations = {
setCurrentCategory (state, category) {
state.currentCategory = category
}
}
import Vue from 'vue' import Vue from 'vue'
import Vuex from 'vuex' import Vuex from 'vuex'
Vue.use(Vuex) Vue.use(Vuex)
export const store = new Vuex.Store({ export const state = () => ({
modules: { products: []
}
}) })
export const mutations = {
setProducts (state, products) {
state.products = products
},
addProduct (state, product) {
state.products.push(product)
}
}
export const actions = {
async fetchProducts ({ commit }) {
// Lấy dữ liệu sản phẩm từ API
const products = await fetch('https://example.com/products')
.then(response => response.json())
.then(data => data)
// Lưu dữ liệu sản phẩm vào store Vuex
commit('setProducts', products)
}
}
export const getters = {
getProductById: state => (id) => {
return state.products.find(product => product.id === id)
}
}
export const strict = false
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment