restore composer.json, add mysqli extension
This commit is contained in:
70
resources/js/app.js
Executable file
70
resources/js/app.js
Executable file
@@ -0,0 +1,70 @@
|
||||
import "./bootstrap";
|
||||
|
||||
import Vue from "vue";
|
||||
|
||||
import CKEditor from "@ckeditor/ckeditor5-vue";
|
||||
import Multiselect from "vue-multiselect";
|
||||
import Vue2Filters from "vue2-filters";
|
||||
|
||||
import VueInternationalization from "vue-i18n";
|
||||
import Locale from "./vue-i18n-locales.generated";
|
||||
import Moment from "vue-moment";
|
||||
|
||||
Vue.use(Moment);
|
||||
|
||||
//Dashboard
|
||||
import ProductAdd from "./components/ProductStore.vue";
|
||||
import ProductEdit from "./components/ProductEdit.vue";
|
||||
import CompilationStore from "./components/Compilation/Store.vue";
|
||||
import CompilationUpdate from "./components/Compilation/Update.vue";
|
||||
import OrderUpdate from "./components/Order/Update.vue";
|
||||
import CategoryStore from "./components/Dashboard/Category/Store.vue";
|
||||
import CategoryUpdate from "./components/Dashboard/Category/Update.vue";
|
||||
import CategoryIndex from "./components/Dashboard/Category/Index.vue";
|
||||
|
||||
import VueFileAgent from "vue-file-agent";
|
||||
// import VueFileAgentStyles from "vue-file-agent/dist/vue-file-agent.css";
|
||||
import ProductPreviewImport from "./components/ProductPreviewImport.vue";
|
||||
import Logs from "./components/Dashboard/Logs.vue";
|
||||
import Statics from "./components/Dashboard/Statics.vue";
|
||||
import SliderView from "./components/Slider/SliderView.vue";
|
||||
|
||||
Vue.use(VueFileAgent);
|
||||
|
||||
Vue.component("product-add", ProductAdd);
|
||||
Vue.component("product-edit", ProductEdit);
|
||||
|
||||
Vue.component("order-edit", OrderUpdate);
|
||||
Vue.component("category-store", CategoryStore);
|
||||
Vue.component("category-update", CategoryUpdate);
|
||||
Vue.component("category-list", CategoryIndex);
|
||||
|
||||
Vue.component("compilation-store", CompilationStore);
|
||||
Vue.component("compilation-update", CompilationUpdate);
|
||||
Vue.component("product-preview", ProductPreviewImport);
|
||||
Vue.component("logs-block", Logs);
|
||||
|
||||
Vue.component("dashboard-statics", Statics);
|
||||
|
||||
Vue.component("multiselect", Multiselect);
|
||||
Vue.component("slider-view", SliderView);
|
||||
|
||||
Vue.use(CKEditor);
|
||||
|
||||
Vue.use(Vue2Filters);
|
||||
|
||||
Vue.use(VueInternationalization);
|
||||
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
|
||||
Vue.config.devtools = true;
|
||||
|
||||
const i18n = new VueInternationalization({
|
||||
locale: lang,
|
||||
messages: Locale,
|
||||
});
|
||||
|
||||
const app = new Vue({
|
||||
el: "#app",
|
||||
i18n,
|
||||
});
|
||||
20
resources/js/bootstrap.js
vendored
Executable file
20
resources/js/bootstrap.js
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
import axios from 'axios';
|
||||
window.axios = axios;
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
|
||||
// window._ = require('lodash');
|
||||
|
||||
/**
|
||||
* We'll load jQuery and the Bootstrap jQuery plugin which provides support
|
||||
* for JavaScript based Bootstrap features such as modals and tabs. This
|
||||
* code may be modified to fit the specific needs of your application.
|
||||
*/
|
||||
|
||||
try {
|
||||
window.Popper = require('popper.js').default;
|
||||
window.$ = window.jQuery = require('jquery');
|
||||
|
||||
require('bootstrap');
|
||||
} catch (e) {}
|
||||
83
resources/js/components/Auth/ChangePassword.vue
Executable file
83
resources/js/components/Auth/ChangePassword.vue
Executable file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="modal fade login" id="password-edit">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<button class="close" data-dismiss="modal">
|
||||
<i class="fal fa-times"></i>
|
||||
</button>
|
||||
|
||||
<!-- Изменить пароль-Password -->
|
||||
<div>
|
||||
<h4 class="text-center">{{ $t('vue.change_password.title') }}</h4>
|
||||
|
||||
<div class="alert alert-danger" v-if="error">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" :key="index">
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" :placeholder="$t('vue.change_password.enter_current')" v-model="user.current_password" id="login_password1" required />
|
||||
<label for="login_password1">{{ $t('vue.change_password.current') }}</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" :placeholder="$t('vue.login.enter_new_password')" v-model="user.password" id="login_password2" required />
|
||||
<label for="login_password2">{{ $t('vue.login.new_password') }}</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" :placeholder="$t('vue.login.enter_new_re_password')" v-model="user.password_confirmation" id="login_password3" required />
|
||||
<label for="login_password3">{{ $t('vue.login.new_re_password') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="submit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.change_password.save') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data: () => ({
|
||||
user: {
|
||||
current_password: null,
|
||||
password: null,
|
||||
password_confirmation: null,
|
||||
},
|
||||
|
||||
error: false,
|
||||
errors: []
|
||||
}),
|
||||
|
||||
methods: {
|
||||
async SendForm() {
|
||||
try {
|
||||
const { status } = await axios.post('/profile/password/update', this.user);
|
||||
|
||||
if (status === 200) {
|
||||
location.reload();
|
||||
}
|
||||
} catch (error) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
434
resources/js/components/Auth/Login.vue
Executable file
434
resources/js/components/Auth/Login.vue
Executable file
@@ -0,0 +1,434 @@
|
||||
<template>
|
||||
<div class="modal fade login" id="login">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<button class="close" data-dismiss="modal">
|
||||
<i class="fal fa-times"></i>
|
||||
</button>
|
||||
|
||||
<div v-if="step === 1">
|
||||
<h4>{{ $t('app.auth.title') }}</h4>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone" required>
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
|
||||
<button type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.next') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="step === 2">
|
||||
<h4 class="text-center">
|
||||
{{ $t('vue.login.regg') }}
|
||||
</h4>
|
||||
<div class="alert alert-danger" v-if="error">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" :key="index">
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" disabled v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone">
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" :placeholder="$t('vue.login.enter_password')" v-model="user.password" id="password" required />
|
||||
<label for="password">{{ $t('vue.login.password') }}</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" :placeholder="$t('vue.login.re_password')" v-model="user.password_confirmation" id="login_password" required />
|
||||
<label for="login_password">{{ $t('vue.login.re_password') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex justify-content-between reply">
|
||||
<div class="my-custom-control custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" checked id="customCheck" name="example1">
|
||||
<label class="custom-control-label" for="customCheck" v-html="$t('vue.login.policy')">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.reg') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div v-if="step === 3">
|
||||
<h4 class="text-center">{{ $t('vue.login.regg') }}</h4>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" disabled v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone">
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="text" :placeholder="$t('vue.login.enter_code')" v-model="user.verify" id="login_password" required />
|
||||
<label for="login_password"> {{ $t('vue.login.code') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="text-danger mt-1" v-if="password_error">
|
||||
{{ $t('vue.login.sms_empty') }}
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.confirm') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div v-if="step === 4">
|
||||
<h4 class="text-center">
|
||||
<h4>{{ $t('app.auth.title') }}</h4>
|
||||
</h4>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" disabled v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone">
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" v-model="user.password" :placeholder="$t('vue.login.password')" id="login_password" required />
|
||||
<label for="login_password"> {{ $t('vue.login.password') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="text-danger mt-1" v-if="password_error">
|
||||
{{ $t('vue.login.pass_err') }}
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex justify-content-between reply">
|
||||
<div class="my-custom-control custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="remember" v-model="user.remember" name="remember">
|
||||
<label class="custom-control-label" for="remember">
|
||||
{{ $t('vue.login.remember') }}
|
||||
</label>
|
||||
</div>
|
||||
<a href="#" @click="step = 5 " class="reset-password text-primary">
|
||||
{{ $t('vue.login.restore') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('app.layout.login') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div v-if="step === 5 || step === 6 || step === 7">
|
||||
<h4 class="text-center">
|
||||
{{ $t('vue.login.restore_pass') }}
|
||||
</h4>
|
||||
|
||||
<div class="alert alert-danger" v-if="error">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" :key="index">
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
|
||||
<div class="mt-4 my-form__group" v-if="step === 7">
|
||||
<input type="password" :placeholder="$t('vue.login.new_password')" v-model="user.password" id="password" required />
|
||||
<label for="password">
|
||||
{{ $t('vue.login.new_password') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group" v-if="step === 7">
|
||||
<input type="password" :placeholder="$t('vue.login.new_re_password')" v-model="user.password_confirmation" id="login_password" required />
|
||||
<label for="login_password">
|
||||
{{ $t('vue.login.new_re_password') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group" v-if="step === 5 || step === 6 ">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" disabled v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone">
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group" v-if="step === 6">
|
||||
<input type="text" :placeholder="$t('vue.login.enter_code')" v-model="user.verify" id="login_password" required />
|
||||
<label for="login_password">{{ $t('vue.login.code') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="text-danger mt-1" v-if="step === 6 && password_error">
|
||||
{{ $t('vue.login.sms_empty') }}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button v-if="step === 5" type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.next') }}
|
||||
</button>
|
||||
|
||||
<button v-if="step === 6" type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.confirm') }}
|
||||
</button>
|
||||
|
||||
<button v-if="step === 7" type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.restore_confirm') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Login",
|
||||
|
||||
props: ['url'],
|
||||
|
||||
data: () => ({
|
||||
user: {
|
||||
phone: null,
|
||||
verify: null,
|
||||
password: null,
|
||||
password_confirmation: null,
|
||||
remember: false
|
||||
},
|
||||
|
||||
step: 1,
|
||||
verify: false,
|
||||
|
||||
error: false,
|
||||
errors: [],
|
||||
password_error: false
|
||||
}),
|
||||
|
||||
|
||||
methods: {
|
||||
async SendForm () {
|
||||
|
||||
if (this.step === 1) {
|
||||
const { data } = await axios.post('/auth/login', {
|
||||
phone: this.user.phone
|
||||
});
|
||||
|
||||
this.step = data.step;
|
||||
// this.verify = true;
|
||||
} else if (this.step === 2) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/register', {
|
||||
phone: this.user.phone,
|
||||
password: this.user.password,
|
||||
password_confirmation: this.user.password_confirmation,
|
||||
});
|
||||
|
||||
this.step = data.step;
|
||||
} catch (error) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
} else if (this.step === 3) {
|
||||
try {
|
||||
let type;
|
||||
let action;
|
||||
|
||||
if (this.$cookie.get('product-credit')) {
|
||||
type = 'product-credit';
|
||||
action = this.$cookie.get('product-credit');
|
||||
} else if (this.$cookie.get('cart-preview')) {
|
||||
type = 'cart-preview';
|
||||
action = 'cart-preview';
|
||||
} else {
|
||||
type = 'auth';
|
||||
action = null;
|
||||
}
|
||||
|
||||
const { data } = await axios.post('/auth/verify', {
|
||||
phone: this.user.phone,
|
||||
code: this.user.verify,
|
||||
type: type,
|
||||
action: action
|
||||
//credit: this.$cookie.get('product-credit') ? this.$cookie.get('product-credit') : null,
|
||||
});
|
||||
if (data.status) {
|
||||
switch (data.action) {
|
||||
case 'cart-preview':
|
||||
window.location.href = data.url;
|
||||
this.$cookie.delete('cart-preview');
|
||||
break;
|
||||
case 'product-credit':
|
||||
window.location.href = data.url;
|
||||
this.$cookie.delete('product-credit');
|
||||
break;
|
||||
default:
|
||||
location.reload();
|
||||
this.$cookie.delete('product-credit');
|
||||
this.$cookie.delete('cart-preview');
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
this.password_error = true;
|
||||
}
|
||||
} else if (this.step === 4 ) {
|
||||
try {
|
||||
let type;
|
||||
let action;
|
||||
|
||||
if (this.$cookie.get('product-credit')) {
|
||||
type = 'product-credit';
|
||||
action = this.$cookie.get('product-credit');
|
||||
} else if (this.$cookie.get('cart-preview')) {
|
||||
type = 'cart-preview';
|
||||
action = 'cart-preview';
|
||||
} else {
|
||||
type = 'auth';
|
||||
action = null;
|
||||
}
|
||||
|
||||
const { data } = await axios.post('/auth/password', {
|
||||
phone: this.user.phone,
|
||||
password: this.user.password,
|
||||
type: type,
|
||||
action: action,
|
||||
remember: this.user.remember
|
||||
//credit: this.$cookie.get('product-credit') ? this.$cookie.get('product-credit') : null,
|
||||
});
|
||||
|
||||
if (data.status) {
|
||||
switch (data.action) {
|
||||
case 'cart-preview':
|
||||
window.location.href = data.url;
|
||||
this.$cookie.delete('cart-preview');
|
||||
break;
|
||||
case 'product-credit':
|
||||
window.location.href = data.url;
|
||||
this.$cookie.delete('product-credit');
|
||||
break;
|
||||
default:
|
||||
location.reload();
|
||||
this.$cookie.delete('product-credit');
|
||||
this.$cookie.delete('cart-preview');
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
this.password_error = true;
|
||||
}
|
||||
} else if (this.step === 5) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/restore', {
|
||||
phone: this.user.phone,
|
||||
});
|
||||
|
||||
this.step = data.step;
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
} else if (this.step === 6) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/restore/verify', {
|
||||
phone: this.user.phone,
|
||||
code: this.user.verify
|
||||
});
|
||||
|
||||
this.user.password = null;
|
||||
this.user.password_confirmation = null;
|
||||
|
||||
this.step = data.step;
|
||||
} catch (error) {
|
||||
this.password_error = true;
|
||||
}
|
||||
} else if (this.step === 7) {
|
||||
try {
|
||||
let type;
|
||||
let action;
|
||||
|
||||
if (this.$cookie.get('product-credit')) {
|
||||
type = 'product-credit';
|
||||
action = this.$cookie.get('product-credit');
|
||||
} else if (this.$cookie.get('cart-preview')) {
|
||||
type = 'cart-preview';
|
||||
action = 'cart-preview';
|
||||
} else {
|
||||
type = 'auth';
|
||||
action = null;
|
||||
}
|
||||
|
||||
const { data } = await axios.post('/auth/restore/confirm', {
|
||||
phone: this.user.phone,
|
||||
password: this.user.password,
|
||||
password_confirmation: this.user.password_confirmation,
|
||||
type: type,
|
||||
action: action
|
||||
//credit: this.$cookie.get('product-credit') ? this.$cookie.get('product-credit') : null,
|
||||
});
|
||||
if (data.status) {
|
||||
switch (data.action) {
|
||||
case 'cart-preview':
|
||||
window.location.href = data.url;
|
||||
this.$cookie.delete('cart-preview');
|
||||
break;
|
||||
case 'product-credit':
|
||||
window.location.href = data.url;
|
||||
this.$cookie.delete('product-credit');
|
||||
break;
|
||||
default:
|
||||
location.reload();
|
||||
this.$cookie.delete('product-credit');
|
||||
this.$cookie.delete('cart-preview');
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
async Resend () {
|
||||
if (this.verify) {
|
||||
await axios.post('/api/auth/login', {
|
||||
phone: this.user.phone
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
88
resources/js/components/Banners/HeaderSlider.vue
Executable file
88
resources/js/components/Banners/HeaderSlider.vue
Executable file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<swiper ref="mySwiperHeader" class="swiper-container swiper-header" :options="swiperOptions">
|
||||
<swiper-slide v-for="(slider, index) in sliderData" :key="index">
|
||||
<a :href="slider.link" class="w-100 h-100 d-block">
|
||||
<div class="swiper-header__item" :style="{ 'background-image' : 'url(/' + slider.image +')' }"></div>
|
||||
</a>
|
||||
</swiper-slide>
|
||||
|
||||
<!-- Add Arrows -->
|
||||
<div class="swiper-button-next swiper-button-next-header" slot="button-next"></div>
|
||||
<div class="swiper-button-prev swiper-button-prev-header" slot="button-prev"></div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-header" slot="pagination"></div>
|
||||
</swiper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
|
||||
// import "swiper/swiper-bundle.css";
|
||||
import 'swiper/css/swiper.css'
|
||||
|
||||
export default {
|
||||
props: ['sliderData'],
|
||||
|
||||
components: {
|
||||
Swiper,
|
||||
SwiperSlide,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
swiperOptions: {
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 0,
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next-header",
|
||||
prevEl: ".swiper-button-prev-header",
|
||||
},
|
||||
pagination: {
|
||||
el: ".swiper-pagination-header",
|
||||
clickable: true,
|
||||
},
|
||||
loop: true,
|
||||
effect: "fade",
|
||||
speed: 1000,
|
||||
autoplay: {
|
||||
delay: 6000,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
swiper() {
|
||||
return this.$refs.mySwiperHeader.$swiper;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$breakpoints: (
|
||||
"phone-smallest": 251px,
|
||||
"phone-small": 321px,
|
||||
"phone": 400px,
|
||||
"phone-wide": 480px,
|
||||
"phablet": 560px,
|
||||
"tablet-small": 640px,
|
||||
"tablet": 768px,
|
||||
"tablet-wide": 1024px,
|
||||
"desktop": 1248px,
|
||||
"desktop-wide": 1440px,
|
||||
"desktop-large": 2500px,
|
||||
);
|
||||
|
||||
@mixin mq($width, $type: min) {
|
||||
@if map_has_key($breakpoints, $width) {
|
||||
$width: map_get($breakpoints, $width);
|
||||
|
||||
@if $type==max {
|
||||
$width: $width - 1px;
|
||||
}
|
||||
|
||||
@media only screen and (#{$type}-width: $width) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
117
resources/js/components/BonusSection.vue
Executable file
117
resources/js/components/BonusSection.vue
Executable file
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="section-bonus">
|
||||
<div class="container">
|
||||
<div class="banner" v-if="bannersData.length === 1">
|
||||
<a :href="bannersData[0].link">
|
||||
<img :src="'/' + bannersData[0].image" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div v-if="bannersData.length > 1">
|
||||
<swiper
|
||||
ref="mySwiperBonus"
|
||||
class="swiper-container swiper-banners"
|
||||
:options="swiperOptions"
|
||||
>
|
||||
<swiper-slide v-for="(banner, index) in bannersData" :key="index">
|
||||
<div class="banner">
|
||||
<a :href="banner.link">
|
||||
<img :src="'/' + banner.image" />
|
||||
</a>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
|
||||
<!-- Add Arrows -->
|
||||
<div class="swiper-button-next swiper-button-next-product" slot="button-next"></div>
|
||||
<div class="swiper-button-prev swiper-button-prev-product" slot="button-prev"></div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-product" slot="pagination"></div>
|
||||
</swiper>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
|
||||
import "swiper/css/swiper.css";
|
||||
export default {
|
||||
props: ['bannersData'],
|
||||
components: {
|
||||
Swiper,
|
||||
SwiperSlide,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
swiperOptions: {
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 0,
|
||||
loop: true,
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next-product",
|
||||
prevEl: ".swiper-button-prev-product",
|
||||
},
|
||||
pagination: {
|
||||
el: ".swiper-pagination-product",
|
||||
clickable: true,
|
||||
dynamicBullets: true,
|
||||
},
|
||||
speed: 1000,
|
||||
autoplay: {
|
||||
delay: 4500,
|
||||
},
|
||||
},
|
||||
products: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
swiper() {
|
||||
return this.$refs.mySwiperBonus.$swiper;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$breakpoints: (
|
||||
"phone-smallest": 251px,
|
||||
"phone-small": 321px,
|
||||
"phone": 400px,
|
||||
"phone-wide": 480px,
|
||||
"phablet": 560px,
|
||||
"tablet-small": 640px,
|
||||
"tablet": 768px,
|
||||
"tablet-wide": 1024px,
|
||||
"desktop": 1248px,
|
||||
"desktop-wide": 1440px,
|
||||
"desktop-large": 2500px,
|
||||
);
|
||||
|
||||
@mixin mq($width, $type: min) {
|
||||
@if map_has_key($breakpoints, $width) {
|
||||
$width: map_get($breakpoints, $width);
|
||||
|
||||
@if $type==max {
|
||||
$width: $width - 1px;
|
||||
}
|
||||
|
||||
@media only screen and (#{$type}-width: $width) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-banners {
|
||||
padding: 75px 0 0px;
|
||||
margin-top: -50px;
|
||||
|
||||
@include mq("tablet", max) {
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
64
resources/js/components/BrandView.vue
Executable file
64
resources/js/components/BrandView.vue
Executable file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="section-categories">
|
||||
<div class="container">
|
||||
<h2 class="section-title">{{ getName(brandData.name) }}</h2>
|
||||
|
||||
<div class="aksiya">
|
||||
<div class="alert alert-info w-100" v-if="products.length === 0">
|
||||
<i class="fa fa-info-circle"></i> {{ $t('app.no_product') }}
|
||||
</div>
|
||||
|
||||
<Product v-for="(product, index) in products" :key="index" :product="product" :login-info="loginInfo"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Product from './Products/Product.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
productsData: {},
|
||||
loginInfo: {},
|
||||
brandData: {}
|
||||
},
|
||||
|
||||
components: {
|
||||
Product
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
products: this.productsData.data
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
// console.log(value);
|
||||
return value;
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
286
resources/js/components/Cart/CartList.vue
Executable file
286
resources/js/components/Cart/CartList.vue
Executable file
@@ -0,0 +1,286 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="section-checkout">
|
||||
<div class="container">
|
||||
<!-- <h2 class="section-title">Оформление заказа</h2>-->
|
||||
|
||||
<ul class="steps steps-one">
|
||||
<li class="steps-item">
|
||||
<a href="#">
|
||||
{{ $t('vue.cart.step_1')}}
|
||||
</a>
|
||||
</li>
|
||||
<li class="steps-item">
|
||||
<a href="/checkout">
|
||||
{{ $t('vue.cart.step_2')}}
|
||||
</a>
|
||||
</li>
|
||||
<li class="steps-item">
|
||||
<a href="/checkout">
|
||||
{{ $t('vue.cart.step_3')}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section-basket">
|
||||
<div class="container">
|
||||
<div class="d-flex align-items-md-center justify-content-between py-3 flex-md-row flex-column">
|
||||
<h2 class="section-title">{{ $t('app.cart.title') }}</h2>
|
||||
</div>
|
||||
|
||||
<p class="mb-3 " v-if="products.length === 0">
|
||||
{{ $t('app.no_product') }}
|
||||
</p>
|
||||
|
||||
<div class="row" v-if="products.length > 0">
|
||||
<div class="col-lg-12 col-md-6">
|
||||
<div class="product my-3">
|
||||
<div class="row align-items-center" v-for="(product, index) in products">
|
||||
<div class="col-lg-2">
|
||||
<div class="product-img">
|
||||
<img :src="'/' + product.product.product.poster_thumb" :alt="getName(product.product.product.name)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<h3 class="product-title">
|
||||
{{ getName(product.product.product.name) }}
|
||||
</h3>
|
||||
<div class="product-address">{{ $t('app.product.article_number') }}: {{ product.product.product.article_number }}</div>
|
||||
<div class="product-price_and_checkout mt-2">
|
||||
<div class="product-price-by-count mr-3">{{ $t('app.price') }} {{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum_sht') }}</div>
|
||||
<button class="my-btn my-btn__orange my-btn__orange--small" v-if="product.product.product.discountPrice > 0 && product.price_discount">{{ $t('app.discount') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-2">
|
||||
<div class="product-count__title">
|
||||
{{ $t('vue.cart.count_by') }}
|
||||
</div>
|
||||
<div class="product-count">
|
||||
<span class="decrement" @click="CountMinus(product)"><i class="fal fa-minus"></i></span>
|
||||
<input type="text" v-model="product.count" min="0" readonly>
|
||||
<span class="increment" @click="CountAdd(product)"><i class="fal fa-plus"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-2">
|
||||
<div class="product-price">
|
||||
<div class="title-price">{{ $t('app.price') }}</div>
|
||||
<div class="old-price mb-1" v-if="product.price_discount"> {{ product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</div>
|
||||
<div class="new-price">{{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="product-buttons">
|
||||
<button class="product-to_favorite__thin" data-target="#login" data-toggle="modal" v-if="!loginInfo">
|
||||
<i class="far fa-heart"></i>
|
||||
<span>{{ $t('app.favorites.in_favorite') }}</span>
|
||||
</button>
|
||||
|
||||
<button class="product-to_favorite__thin" :class="product.product.product.isFavorite ? 'product-to_favorite__thin is-active' : 'product-to_favorite__thin'" @click="Favorite(product.product.product)" v-if="loginInfo">
|
||||
<i class="far fa-heart"></i>
|
||||
<span>{{ $t('app.favorites.in_favorite') }}</span>
|
||||
</button>
|
||||
|
||||
<div class="v-line">|</div>
|
||||
<button class="product-to_delete" @click="removeProduct(product, index)">
|
||||
<i class="fal fa-times fa-2x"></i>
|
||||
<span>{{ $t('app.delete') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="basket__footer" v-if="products.length > 0">
|
||||
<div class="basket__footer--left">
|
||||
<!-- <form action="index.html" class="my-form my-form__auth">-->
|
||||
<!-- <div class="d-flex align-items-xl-center flex-xl-row flex-column align-items-center align-items-md-start">-->
|
||||
<!-- <div class="my-form__group">-->
|
||||
<!-- <input type="text" placeholder="Промокод" id="login_password" required>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="">-->
|
||||
<!-- <button type="sbumit" class="my-btn my-btn__gray ml-xl-3 mt-xl-0 mt-3">-->
|
||||
<!-- {{ $t('vue.cart.get_discount') }}-->
|
||||
<!-- </button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="mt-4 d-flex justify-content-md-start align-items-center align-items-md-start justify-content-center">-->
|
||||
<!-- <a href="javascript:void(0)" class="reset-password">-->
|
||||
<!-- {{ $t('vue.cart.get_promocode') }}-->
|
||||
<!-- </a>-->
|
||||
<!-- <a href="javascript:void(0)" class="reset-password d-none">-->
|
||||
<!-- {{ $t('vue.cart.another_promocode') }}-->
|
||||
<!-- </a>-->
|
||||
<!-- </div>-->
|
||||
<!-- </form>-->
|
||||
</div>
|
||||
|
||||
<div class="basket__footer--right">
|
||||
<div class="sum-of-products">
|
||||
<h3>{{ $t('vue.cart.total_amount') }}: <span>{{ prices | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</span></h3>
|
||||
<h5>{{ $t('vue.cart.saving') }}: <span>0 сум</span></h5>
|
||||
<h2>{{ $t('vue.cart.total_cost') }}: <span>{{ prices | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</span></h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="basket__footer" v-if="products.length > 0">
|
||||
<a href="/" class="btn-links btn-links__one">{{ $t('vue.cart.continue_shopping') }}</a>
|
||||
<div class="basket__footer--right mt-3 mt-md-0">
|
||||
<button @click="removeAllProducts" class="btn-links btn-links__three mr-md-2 my-3 my-md-0">{{ $t('vue.cart.reset_cart') }}</button>
|
||||
<a href="/cart/oncredit/" v-if="loginInfo && creditInfo" class="btn-links btn-links__one bg__green mr-md-2 my-3 my-md-0">
|
||||
{{ $t('vue.cart.credit') }}
|
||||
</a>
|
||||
|
||||
<a href="javascript:" v-if="!loginInfo && creditInfo" data-target="#login" data-toggle="modal" data-dismiss="modal" @click="CreditCookie" class="btn-links btn-links__one bg__green mr-md-2 my-3 my-md-0">
|
||||
{{ $t('vue.cart.credit') }}
|
||||
</a>
|
||||
|
||||
<a href="/checkout" class="btn-links btn-links__two">{{ $t('vue.cart.checkout_product') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
cartData: {},
|
||||
loginInfo: {},
|
||||
pricesData: {},
|
||||
creditInfo: {}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
products: this.cartData,
|
||||
prices: this.pricesData
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
},
|
||||
|
||||
async removeAllProducts() {
|
||||
const { data } = await axios.delete('/cart/remove/all');
|
||||
|
||||
if (data.status) {
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
this.prices = data.prices;
|
||||
this.products = [];
|
||||
}
|
||||
},
|
||||
|
||||
async CountMinus(product) {
|
||||
if (product.product.product.count >= product.count) {
|
||||
if (product.count <= 1) {
|
||||
product.count = 1;
|
||||
} else {
|
||||
product.count -= 1;
|
||||
}
|
||||
} else {
|
||||
product.count = product.product.product.count;
|
||||
}
|
||||
|
||||
const fields = {
|
||||
product_id: product.product_id,
|
||||
count: product.count
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/cart/update', fields);
|
||||
|
||||
if (data.status) {
|
||||
product.isCart = true;
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
this.prices = data.prices;
|
||||
product.product.product.count = data.max_count;
|
||||
}
|
||||
},
|
||||
|
||||
CreditCookie() {
|
||||
this.$cookie.delete('product-credit');
|
||||
this.$cookie.set('cart-preview', 1);
|
||||
},
|
||||
|
||||
async CountAdd(product) {
|
||||
if (product.product.product.count > product.count){
|
||||
product.count += 1;
|
||||
|
||||
const fields = {
|
||||
product_id: product.product_id,
|
||||
count: product.count
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/cart/update', fields);
|
||||
|
||||
if (data.status) {
|
||||
product.isCart = true;
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
this.prices = data.prices;
|
||||
product.product.product.count = data.max_count;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async Favorite(product) {
|
||||
var field = document.getElementById("favorite-count");
|
||||
var count = field.value;
|
||||
|
||||
if (product.isFavorite === false) {
|
||||
const { data } = await axios.get('/favorites/store/' + product.id);
|
||||
product.isFavorite = true;
|
||||
field.value = parseInt(count) + 1;
|
||||
} else {
|
||||
const { data } = await axios.get('/favorites/delete/' + product.id);
|
||||
product.isFavorite = false;
|
||||
field.value = parseInt(count) - 1;
|
||||
}
|
||||
},
|
||||
|
||||
async removeProduct(product, index) {
|
||||
const { data } = await axios.delete('/cart/delete/' + product.product_id);
|
||||
|
||||
if (data.status) {
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
this.prices = data.prices;
|
||||
this.products.splice(index, 1)
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
228
resources/js/components/Cart/CartPreview.vue
Executable file
228
resources/js/components/Cart/CartPreview.vue
Executable file
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<div class="balance-link">
|
||||
<a href="javascript:" data-target="#basket_modal" data-toggle="modal" @click="getCart" class="basket">
|
||||
<i class="fas fa-shopping-basket"></i>
|
||||
<div class="basket-count">
|
||||
<input type="text" id="basket-count" readonly v-model="basket">
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="modal fade basket-modal" id="basket_modal">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<button class="close" data-dismiss="modal">
|
||||
<i class="fal fa-times"></i>
|
||||
</button>
|
||||
|
||||
<h4>{{ $t('vue.cart_preview.basket_title') }}</h4>
|
||||
|
||||
<p class="mb-3 " v-if="products.length === 0">
|
||||
{{ $t('app.no_product') }}
|
||||
</p>
|
||||
|
||||
<form action="#" class="my-form my-form__auth">
|
||||
<div class="product" v-for="(product, index) in products">
|
||||
<div class="row align-items-center">
|
||||
|
||||
<div class="col-lg-2">
|
||||
<div class="product-img">
|
||||
<img :src="'/' + product.product.product.poster_thumb" :alt="getName(product.product.product.name)">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-5">
|
||||
<h3 class="product-title">{{ getName(product.product.product.name) }}</h3>
|
||||
<div class="product-price_and_checkout mt-2">
|
||||
<div class="product-price-by-count mr-3">{{ $t('app.price') }} {{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum_sht') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-2 mx-auto">
|
||||
<div class="product-count mb-md-0 mx-auto my-3 my-md-0">
|
||||
<span class="decrement" @click="CountMinus(product)"><i class="fal fa-minus"></i></span>
|
||||
<input type="text" v-model="product.count" min="0" class="h-auto" readonly>
|
||||
<span class="increment" @click="CountAdd(product)"><i class="fal fa-plus"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="product-buttons">
|
||||
<button type="button" class="product-to_delete" @click="removeProduct(product, index)">
|
||||
<i class="fal fa-times fa-2x"></i>
|
||||
<span>{{ $t('app.delete') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr v-if="products.length > 0">
|
||||
<div class="sum-of-products d-flex justify-content-end my-4" v-if="products.length > 0">
|
||||
<h3>{{ $t('vue.cart.total_amount') }}: <span>{{ prices | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</span></h3>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center flex-md-row flex-column" v-if="products.length > 0">
|
||||
<a href="/cart" class="my-btn my-btn__orange d-flex justift-content-center align-items-center text-white">{{ $t('vue.cart_preview.basket_checkout') }}</a>
|
||||
<div class="product-buttons mb-0 ml-md-3" v-if="on_credit">
|
||||
<a href="javascript:" v-if="!loginInfo" data-target="#login" data-toggle="modal" data-dismiss="modal" @click="CreditCookie" class="btn-links btn-links__one bg__green">
|
||||
{{ $t('vue.cart.credit') }}
|
||||
</a>
|
||||
|
||||
<a href="/cart/oncredit/" v-if="loginInfo" class="btn-links btn-links__one bg__green">
|
||||
{{ $t('vue.cart.credit') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
props: {
|
||||
loginInfo: {}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
products: [],
|
||||
prices: 0,
|
||||
|
||||
basket: 0,
|
||||
on_credit: 0
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$eventBus.$on('cart-preview', this.getPreviews);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.getCount()
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
getPreviews() {
|
||||
this.getCart();
|
||||
},
|
||||
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
},
|
||||
|
||||
|
||||
async CountMinus(product) {
|
||||
if (product.product.product.count >= product.count) {
|
||||
if (product.count <= 1) {
|
||||
product.count = 1;
|
||||
} else {
|
||||
product.count -= 1;
|
||||
}
|
||||
} else {
|
||||
product.count = product.product.product.count;
|
||||
}
|
||||
|
||||
const fields = {
|
||||
product_id: product.product_id,
|
||||
count: product.count
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/cart/update', fields);
|
||||
|
||||
if (data.status) {
|
||||
product.isCart = true;
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
this.prices = data.prices;
|
||||
product.product.product.count = data.max_count;
|
||||
}
|
||||
},
|
||||
|
||||
async CountAdd(product) {
|
||||
if (product.product.product.count > product.count){
|
||||
product.count += 1;
|
||||
|
||||
const fields = {
|
||||
product_id: product.product_id,
|
||||
count: product.count
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/cart/update', fields);
|
||||
|
||||
if (data.status) {
|
||||
product.isCart = true;
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
this.prices = data.prices;
|
||||
product.product.product.count = data.max_count;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async getCount() {
|
||||
const { data } = await axios.get('/cart/basket/');
|
||||
|
||||
if (data.status) {
|
||||
this.basket = data.basket;
|
||||
}
|
||||
},
|
||||
|
||||
async getCart() {
|
||||
const { data } = await axios.get('/cart/preview/');
|
||||
|
||||
if (data.status) {
|
||||
this.basket = data.products.length;
|
||||
this.products = data.products;
|
||||
this.prices = data.prices;
|
||||
this.on_credit = data.on_credit
|
||||
}
|
||||
},
|
||||
|
||||
CreditCookie() {
|
||||
this.$cookie.delete('product-credit');
|
||||
this.$cookie.set('cart-preview', 1);
|
||||
},
|
||||
|
||||
async removeProduct(product, index) {
|
||||
const { data } = await axios.delete('/cart/delete/' + product.product_id);
|
||||
|
||||
if (data.status) {
|
||||
this.basket = data.count;
|
||||
this.prices = data.prices;
|
||||
this.products.splice(index, 1)
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
377
resources/js/components/Catalog/CatalogShow.vue
Executable file
377
resources/js/components/Catalog/CatalogShow.vue
Executable file
@@ -0,0 +1,377 @@
|
||||
<template>
|
||||
<section :class="products.length === 0 ? 'section-categories no-product-section' : 'section-categories'">
|
||||
<div class="container">
|
||||
<h1 class="section-title">
|
||||
{{ getName(category.name) }}
|
||||
</h1>
|
||||
|
||||
<div class="my-form my-form__checkout my-form__countBy mb-3 d-block d-md-none">
|
||||
<div class="my-form__group d-flex flex-row justify-content-end">
|
||||
<p class="mr-3">{{ $t('vue.catalog.view_by') }}</p>
|
||||
<select @change="SendFilterParams" v-model="page_products" class="custom-select">
|
||||
<option value="12">12</option>
|
||||
<option value="24">24</option>
|
||||
<option value="48">48</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Catalog on Mobile -->
|
||||
<div class="catalog-on-mobile" v-if="mobile">
|
||||
<ul class="outer-ul" :class="menu">
|
||||
|
||||
<li class="catalog" v-if="categories.length > 0">
|
||||
{{ $t('vue.catalog.catalog_title') }} <i class="fas fa-caret-down"></i>
|
||||
<ul class="inner-ul">
|
||||
<li v-for="(category, index) in categories" v-if="category.published" :key="index">
|
||||
<a :href="category.link">
|
||||
{{ getName(category.name) }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="filtr" v-if="characteristics.length > 0">
|
||||
{{ $t('vue.catalog.catalog_filter') }} <i class="fas fa-caret-down"></i>
|
||||
</li>
|
||||
|
||||
<ul class="inner-ul filtr-inner-ul" v-if="characteristics.length > 0">
|
||||
|
||||
<form action="#" @submit.prevent="SendFilterParams">
|
||||
<div class="categories">
|
||||
|
||||
<div class="card" v-if="characteristics.length > 0" v-for="(char, index) in characteristics" :key="index">
|
||||
<div class="card-header">
|
||||
<a class="card-link" data-toggle="collapse" :href="'#collapse-'+ char.id">
|
||||
{{ getName(char.name) }}
|
||||
</a>
|
||||
</div>
|
||||
<div :id="'collapse-'+ char.id" class="collapse show" :data-parent="'#collapse-'+ char.id">
|
||||
<div class="card-body">
|
||||
<div class="card-content brand">
|
||||
<div class="custom-control custom-checkbox" v-for="(attr, indexx) in char.attributes" :key="indexx">
|
||||
<input type="checkbox" class="custom-control-input" v-model="filters" :id="'check'+char.id+indexx" name="filter" :value="{id: char.id, name: char.name, type: char.type, attribute: attr}">
|
||||
<label class="custom-control-label" :for="'check'+char.id+indexx" v-if="char.type === 'checkbox'">
|
||||
<span v-if="attr === 'true'">
|
||||
{{ $t('app.exist') }}
|
||||
</span>
|
||||
<span v-if="attr === 'false'">
|
||||
{{ $t('app.no') }}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label class="custom-control-label" :for="'check'+char.id+indexx" v-else>
|
||||
{{ attr }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category-buttons pb-2 mt-4" v-if="characteristics.length > 0">
|
||||
<button type="submit" class="my-btn my-btn__apply my-3 apply_mobile" >{{ $t('vue.catalog.catalog_accept') }}</button>
|
||||
<button type="button" @click="removeAllFilter" class="my-btn my-btn__cancel my-3">{{ $t('vue.catalog.catalog_reset') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</ul>
|
||||
|
||||
<li class="view">
|
||||
{{ $t('vue.catalog.view_by') }} <i class="fas fa-caret-down"></i>
|
||||
<ul class="inner-ul">
|
||||
<li><a :class="orderby === 'all' ? 'active' : ''" @click="orderByChange('all')" href="#javascript:">{{ $t('vue.catalog.view_by_all') }}</a></li>
|
||||
<li><a :class="orderby === 'new' ? 'active' : ''" @click="orderByChange('new')" href="#javascript:">{{ $t('vue.catalog.new') }}</a></li>
|
||||
<li><a :class="orderby === 'cheap' ? 'active' : ''" href="javascript:" @click="orderByChange('cheap')">{{ $t('vue.catalog.view_by_cheap') }}</a></li>
|
||||
<li><a :class="orderby === 'expensive' ? 'active' : ''" href="javascript:" @click="orderByChange('expensive')">{{ $t('vue.catalog.view_by_expensive') }}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div :class="categories.length > 0 || characteristics.length > 0 ? 'row row-outer' : 'row-outer'" >
|
||||
<div v-if="!mobile && categories.length > 0 || !mobile && characteristics.length > 0" class="col-md-4 col-lg-3">
|
||||
|
||||
<form action="#" @submit.prevent="SendFilterParams" class="h-100 d-md-block d-none">
|
||||
<div class="categories sticky-top">
|
||||
<div :class="characteristics.length === 0 ? 'card border-bottom-0' : 'card'" v-if="categories.length > 0">
|
||||
<div class="card-header">
|
||||
<a class="card-link" data-toggle="collapse" href="#collapse-1111">
|
||||
{{ $t('vue.catalog.catalog_title') }}
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapse-1111" class="collapse show" data-parent="#collapse-1111">
|
||||
<div class="card-body">
|
||||
<div class="card-content category">
|
||||
<ul>
|
||||
<li v-for="(category, index) in categories" v-if="category.published" :key="index">
|
||||
<a :href="category.link">
|
||||
{{ getName(category.name) }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" v-if="characteristics.length > 0" v-for="(char, index) in characteristics" :key="index">
|
||||
<div class="card-header">
|
||||
<a class="card-link" data-toggle="collapse" :href="'#collapse-'+ char.id">
|
||||
{{ getName(char.name) }}
|
||||
</a>
|
||||
</div>
|
||||
<div :id="'collapse-'+ char.id" class="collapse show" :data-parent="'#collapse-'+ char.id">
|
||||
<div class="card-body">
|
||||
<div class="card-content brand">
|
||||
<div class="custom-control custom-checkbox" v-for="(attr, indexx) in char.attributes" :key="indexx">
|
||||
<input type="checkbox" class="custom-control-input" v-model="filters" :id="'check'+char.id+indexx" name="filter" :value="{id: char.id, name: char.name, type: char.type, attribute: attr}">
|
||||
<label class="custom-control-label" :for="'check'+char.id+indexx" v-if="char.type === 'checkbox'">
|
||||
<span v-if="attr === 'true'">
|
||||
{{ $t('app.exist') }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ $t('app.no') }}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label class="custom-control-label" :for="'check'+char.id+indexx" v-else>
|
||||
{{ attr }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category-buttons pb-2 mt-4" v-if="characteristics.length > 0">
|
||||
<button type="submit" class="my-btn my-btn__apply my-3" >{{ $t('vue.catalog.catalog_accept') }}</button>
|
||||
<button type="button" @click="removeAllFilter" class="my-btn my-btn__cancel my-3">{{ $t('vue.catalog.catalog_reset') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div :class="categories.length > 0 || characteristics.length > 0 ? 'col-md-8 col-lg-9' : 'col-12'">
|
||||
<div class="d-md-block d-none" v-if="products.length > 0">
|
||||
<div class="d-flex justify-content-between">
|
||||
<ul class="sorting">
|
||||
<li class="sorting-item"><a :class="orderby === 'all' ? 'active' : ''" @click="orderByChange('all')" href="#javascript:">{{ $t('vue.catalog.view_by_all') }}</a></li>
|
||||
<li class="sorting-item"><a :class="orderby === 'new' ? 'active' : ''" @click="orderByChange('new')" href="#javascript:">{{ $t('vue.catalog.new') }}</a></li>
|
||||
<li class="sorting-item"><a :class="orderby === 'cheap' ? 'active' : ''" href="javascript:" @click="orderByChange('cheap')">{{ $t('vue.catalog.view_by_cheap') }}</a></li>
|
||||
<li class="sorting-item"><a :class="orderby === 'expensive' ? 'active' : ''" href="javascript:" @click="orderByChange('expensive')">{{ $t('vue.catalog.view_by_expensive') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="my-form my-form__checkout my-form__countBy">
|
||||
<div class="my-form__group">
|
||||
<select @change="SendFilterParams" v-model="page_products" class="custom-select">
|
||||
<option disabled selected>{{ $t('vue.catalog.view_byy') }}</option>
|
||||
<option value="12">12</option>
|
||||
<option value="24">24</option>
|
||||
<option value="48">48</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="selected-tags" v-if="filters.length > 0">
|
||||
<ul>
|
||||
<li v-for="(attr, index) in filters" :key="index">
|
||||
<span v-if="attr.attribute === 'true'">
|
||||
{{ getName(attr.name) }}: {{ $t('app.exist') }}
|
||||
</span>
|
||||
<span v-else-if="attr.attribute === 'false'">
|
||||
{{ getName(attr.name) }}: {{ $t('app.no') }}
|
||||
</span>
|
||||
|
||||
<span v-else>
|
||||
{{ attr.attribute }}
|
||||
</span>
|
||||
<span class="close" @click="removeFilter(index)"><i class="fal fa-times"></i></span>
|
||||
</li>
|
||||
|
||||
<li class="clear-all" @click="removeAllFilter" id="clear_all">{{ $t('vue.catalog.catalog_reset') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-inner">
|
||||
|
||||
<div v-if="products.length === 0">
|
||||
{{ $t('app.no_category_product') }}
|
||||
</div>
|
||||
|
||||
<div class="aksiya w-100 mt-0" v-if="categories.length === 0 && characteristics.length === 0">
|
||||
<product-item v-for="(product, index) in products" :key="index" :product="product" :login-info="loginInfo"/>
|
||||
</div>
|
||||
|
||||
<div v-if="categories.length > 0 || characteristics.length > 0" class="col-md-6 col-lg-4 col-xl-3 my-2" v-for="(product, index) in products">
|
||||
<product-item :product="product" :login-info="loginInfo"></product-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<paginate v-if="product_count > 12"
|
||||
v-model="page_current"
|
||||
:pageCount="pageCount"
|
||||
:clickHandler="PageCallBack"
|
||||
:prevText="'<i class=\'far fa-long-arrow-left \'></i>'"
|
||||
:nextText="'<i class=\'far fa-long-arrow-right \'></i>'"
|
||||
:container-class="'pagination d-flex justify-content-center align-items-center flex-wrap mt-4'"
|
||||
:page-class="'page-item'"
|
||||
:page-link-class="'page-link'"
|
||||
:next-class="'page-item'"
|
||||
:prev-class="'page-item'"
|
||||
:prev-link-class="'page-link'"
|
||||
:next-link-class="'page-link'">
|
||||
</paginate>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Product from '../Products/Product';
|
||||
import { isMobileOnly } from "mobile-device-detect";
|
||||
import Paginate from 'vuejs-paginate'
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.MenuLiCount();
|
||||
if (localStorage.url_filter == window.location) {
|
||||
this.filters = JSON.parse(localStorage.filter);
|
||||
} else {
|
||||
localStorage.removeItem('url_filter');
|
||||
localStorage.removeItem('filter');
|
||||
}
|
||||
|
||||
let url = new URL(window.location.href);
|
||||
let page = url.searchParams.get("page");
|
||||
|
||||
this.page_current = page;
|
||||
|
||||
if (this.page_current > 1) {
|
||||
this.SendFilterParams()
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
productsData: {},
|
||||
categoriesData: {},
|
||||
loginInfo: {},
|
||||
characteristicsData: {},
|
||||
categoryData: {},
|
||||
page: {}
|
||||
},
|
||||
|
||||
components: {
|
||||
'product-item': Product,
|
||||
'paginate': Paginate
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
products: this.productsData.data,
|
||||
categories: this.categoriesData,
|
||||
characteristics: this.characteristicsData,
|
||||
category: this.categoryData,
|
||||
|
||||
filters: [],
|
||||
orderby: 'all',
|
||||
|
||||
menu: 'three-li',
|
||||
mobile: isMobileOnly ? true : false,
|
||||
|
||||
pageCount: this.productsData.last_page,
|
||||
page_current: 1,
|
||||
product_count: this.productsData.total,
|
||||
paginate: false,
|
||||
|
||||
page_products: 12,
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
filters: function (newVal) {
|
||||
this.SendFilterParams();
|
||||
localStorage.filter = JSON.stringify(this.filters);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
PageCallBack(pageNum) {
|
||||
this.page_current = pageNum;
|
||||
window.scrollTo(0,0);
|
||||
this.SendFilterParams();
|
||||
},
|
||||
|
||||
async SendFilterParams() {
|
||||
const fields = {
|
||||
order_by: this.orderby,
|
||||
filter: this.filters,
|
||||
page: this.page,
|
||||
paginate: this.page_products
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/category/filter/' + this.category.slug + '?page='+ this.page_current, fields);
|
||||
|
||||
localStorage.url_filter = window.location;
|
||||
|
||||
window.history.pushState({page: 1}, 'page', '?page=' + this.page_current);
|
||||
// window.document.title = response.data.post.name
|
||||
|
||||
this.pageCount = data.page;
|
||||
this.products = data.products;
|
||||
this.product_count = data.count;
|
||||
},
|
||||
|
||||
removeFilter(index) {
|
||||
this.filters.splice(index, 1);
|
||||
},
|
||||
|
||||
orderByChange(type) {
|
||||
this.orderby = type;
|
||||
|
||||
this.SendFilterParams()
|
||||
},
|
||||
|
||||
MenuLiCount() {
|
||||
if (this.categories.length > 0 && this.characteristics.length > 0) {
|
||||
this.menu = 'three-li';
|
||||
} else if (this.categories.length === 0 ^ this.characteristics.length === 0) {
|
||||
this.menu = 'two-li';
|
||||
} else {
|
||||
this.menu = 'one-li';
|
||||
}
|
||||
},
|
||||
|
||||
removeAllFilter() {
|
||||
this.filters = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
77
resources/js/components/CategoriesBlock.vue
Executable file
77
resources/js/components/CategoriesBlock.vue
Executable file
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<ul class="nav">
|
||||
<li class="nav-item checkout">
|
||||
<a href="/stocks" class="dropbtn"><span v-html="$t('vue.cat_sales')"></span></a>
|
||||
</li>
|
||||
<li class="nav-item" v-for="(category, index) in categories" @mouseover="category.hover = true" @mouseleave="category.hover = false">
|
||||
<a :href="'/category/' + category.slug" class="dropbtn">
|
||||
<span>
|
||||
{{ getName(category.name) }}
|
||||
</span>
|
||||
</a>
|
||||
<i class="fal fa-chevron-down"></i>
|
||||
<div class="nav-item-content" v-if="category.hover"> <!--v-if="category.hover"-->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xl-2 col-lg-3 mb-lg-3 mb-1" v-for="(parent, index) in category.parents" v-if="parent.published">
|
||||
<h3 class="nav-item-content__title">
|
||||
<img v-if="parent.image" :src="'/' + parent.image">
|
||||
<a :href="'/category/' + category.slug + '/' + parent.slug">
|
||||
{{ getName(parent.name) }}
|
||||
</a>
|
||||
<i class="fal fa-plus"></i>
|
||||
</h3>
|
||||
<div class="nav-item-content__toggle">
|
||||
<a v-for="(child, index) in parent.parents" :href="'/category/' + category.slug + '/' + parent.slug + '/' + child.slug" v-if="child.published">
|
||||
{{ getName(child.name) }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
categoriesData: {}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
categories: this.categoriesData
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
// console.log(value);
|
||||
return value;
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
723
resources/js/components/Checkout/CheckoutView.vue
Executable file
723
resources/js/components/Checkout/CheckoutView.vue
Executable file
@@ -0,0 +1,723 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="section-checkout">
|
||||
<div class="container">
|
||||
<h2 class="section-title">{{ $t('vue.cart.checkout_product') }}</h2>
|
||||
|
||||
<ul class="steps" :class="!login && step === 2 ? 'steps-two' : 'steps-three'">
|
||||
<li class="steps-item">
|
||||
<a href="/cart">
|
||||
{{ $t('vue.cart.step_1') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="steps-item">
|
||||
<a href="javascript:void(0)" >
|
||||
{{ $t('vue.cart.step_2') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="steps-item">
|
||||
<a href="javascript:void(0)" >
|
||||
{{ $t('vue.cart.step_3') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section-basket" v-if="step === 2">
|
||||
<div class="container">
|
||||
<div class="basket__footer">
|
||||
|
||||
<div class="col-md-5" v-if="user.step === 1">
|
||||
<h4>{{ $t('app.auth.title') }}</h4>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone" required>
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
|
||||
<button type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.next') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-5" v-if="user.step === 2">
|
||||
<h4 class="text-center">
|
||||
{{ $t('vue.login.regg') }}
|
||||
</h4>
|
||||
<div class="alert alert-danger" v-if="error">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" :key="index">
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" disabled v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone">
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" :placeholder="$t('vue.login.enter_password')" v-model="user.password" id="password" required />
|
||||
<label for="password">{{ $t('vue.login.password') }}</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" :placeholder="$t('vue.login.re_password')" v-model="user.password_confirmation" id="login_password" required />
|
||||
<label for="login_password">{{ $t('vue.login.re_password') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex justify-content-between reply">
|
||||
<div class="my-custom-control custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" checked id="customCheck" name="example1">
|
||||
<label class="custom-control-label" for="customCheck" v-html="$t('vue.login.policy')">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.reg') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5" v-if="user.step === 3">
|
||||
<h4 class="text-center">{{ $t('vue.login.regg') }}</h4>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" disabled v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone">
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="text" :placeholder="$t('vue.login.enter_code')" v-model="user.verify" id="login_password" required />
|
||||
<label for="login_password"> {{ $t('vue.login.code') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="text-danger mt-1" v-if="password_error">
|
||||
{{ $t('vue.login.sms_empty') }}
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.confirm') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5" v-if="user.step === 4">
|
||||
<h4 class="text-center">
|
||||
<h4>{{ $t('app.auth.title') }}</h4>
|
||||
</h4>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" disabled v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone">
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="password" v-model="user.password" :placeholder="$t('vue.login.password')" id="login_password" required />
|
||||
<label for="login_password"> {{ $t('vue.login.password') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="text-danger mt-1" v-if="password_error">
|
||||
{{ $t('vue.login.pass_err') }}
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex justify-content-between reply">
|
||||
<div class="my-custom-control custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="remember" v-model="user.remember" name="remember">
|
||||
<label class="custom-control-label" for="remember">
|
||||
{{ $t('vue.login.remember') }}
|
||||
</label>
|
||||
</div>
|
||||
<a href="#" @click="user.step = 5 " class="reset-password text-primary">
|
||||
{{ $t('vue.login.restore') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('app.layout.login') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5" v-if="user.step === 5 || user.step === 6 || user.step === 7">
|
||||
<h4 class="text-center">
|
||||
{{ $t('vue.login.restore_pass') }}
|
||||
</h4>
|
||||
|
||||
<div class="alert alert-danger" v-if="error">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" :key="index">
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
|
||||
<div class="mt-4 my-form__group" v-if="user.step === 5 || user.step === 6 || user.step === 7 ">
|
||||
<input type="tel" :placeholder="$t('app.auth.enter_phone')" disabled v-mask="'+998 (##) ###-##-##'" v-model="user.phone" id="login_phone">
|
||||
<label for="login_phone">{{ $t('app.auth.phone') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 my-form__group" v-if="user.step === 7">
|
||||
<input type="password" :placeholder="$t('vue.login.new_password')" v-model="user.password" id="sss" required />
|
||||
<label for="sss">
|
||||
{{ $t('vue.login.new_password') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group" v-if="user.step === 7">
|
||||
<input type="password" :placeholder="$t('vue.login.new_re_password')" v-model="user.password_confirmation" id="new_re_password" required />
|
||||
<label for="new_re_password">
|
||||
{{ $t('vue.login.new_re_password') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="mt-4 my-form__group" v-if="user.step === 6">
|
||||
<input type="text" :placeholder="$t('vue.login.enter_code')" v-model="user.verify" id="login_password" required />
|
||||
<label for="login_password">{{ $t('vue.login.code') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="text-danger mt-1" v-if="user.step === 6 && password_error">
|
||||
{{ $t('vue.login.sms_empty') }}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button v-if="user.step === 5" type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.next') }}
|
||||
</button>
|
||||
|
||||
<button v-if="user.step === 6" type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.confirm') }}
|
||||
</button>
|
||||
|
||||
<button v-if="user.step === 7" type="sumbit" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('vue.login.restore_confirm') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
<section class="section-checkout" v-if="step === 3">
|
||||
<div class="container">
|
||||
<div class="col-12" v-if="!deliveryInfo && !pickupInfo">
|
||||
<div class="row">
|
||||
<div class="alert alert-info w-100">
|
||||
<i class="fa fa-info-circle"></i> {{ $t('vue.checkout.no_ordered') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form @submit.prevent="SendOrder" class="my-form my-form__checkout" v-if="pickupInfo || deliveryInfo">
|
||||
<div class="row mb-5">
|
||||
<div class="col-md-7">
|
||||
<h3 class="mt-4 mb-3">{{ $t('vue.checkout.delivery_title') }}</h3>
|
||||
<div class="form-payment">
|
||||
<div class="custom-control custom-radio custom-control-inline" v-if="pickupInfo">
|
||||
<input type="radio" class="custom-control-input" id="delivery1" name="delivery" v-model="order.delivery_type" value="pickup">
|
||||
<label class="custom-control-label" for="delivery1">{{ $t('vue.checkout.delivery_pickup') }}</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline" v-if="deliveryInfo">
|
||||
<input type="radio" class="custom-control-input" id="delivery2" name="delivery" v-model="order.delivery_type" value="delivery">
|
||||
<label class="custom-control-label" for="delivery2">{{ $t('vue.checkout.delivery_courier') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="order.delivery_type === 'delivery' && deliveryInfo">
|
||||
|
||||
|
||||
|
||||
<h3 class="mt-4 mb-3">{{ $t('vue.checkout.delivery_about') }}</h3>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5 align-items-start justify-content-center d-flex flex-column">
|
||||
<h4>{{ $t('vue.checkout.first_name') }}</h4>
|
||||
</div>
|
||||
<div class="col-md-7 my-form__group">
|
||||
<input type="text" placeholder="" required v-model="address.first_name" id="first_name">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5 align-items-start justify-content-center d-flex flex-column">
|
||||
<h4>{{ $t('vue.checkout.delivery_region') }}</h4>
|
||||
</div>
|
||||
<div class="col-md-7 my-form__group">
|
||||
<select name="regions" class="custom-select" @change="changeRegion($event)" v-model="address.region_id">
|
||||
<option v-for="(region, index) in regions" :value="index" :selected="index === 0 ? 'selected' : false" >
|
||||
{{ getName(region.name) }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5 align-items-start justify-content-center d-flex flex-column">
|
||||
<h4>{{ $t('vue.checkout.delivery_city') }}</h4>
|
||||
</div>
|
||||
<div class="col-md-7 my-form__group">
|
||||
<select name="cities" class="custom-select" v-model="address.city_id">
|
||||
<option v-for="(city, index) in cities" :value="city.id" :selected="index === 0 ? 'selected' : false">
|
||||
{{ getName(city.name) }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5 align-items-start justify-content-center d-flex flex-column">
|
||||
<h4>{{ $t('vue.checkout.delivery_address') }}</h4>
|
||||
</div>
|
||||
<div class="col-md-7 my-form__group">
|
||||
<input type="text" placeholder="" v-model="address.address" required id="your_address">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5 align-items-start justify-content-center d-flex flex-column">
|
||||
<h4>{{ $t('vue.checkout.delivery_additional_info') }}</h4>
|
||||
</div>
|
||||
<div class="col-md-7 my-form__group">
|
||||
<input type="text" placeholder="" v-mask="'+998 (##) ###-##-##'" v-model="address.other_phone" id="your_contact">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5">
|
||||
<h4>{{ $t('vue.checkout.delivery_cemments') }}</h4>
|
||||
</div>
|
||||
<div class="col-md-7 my-form__group">
|
||||
<textarea cols="30" v-model="address.comment" rows="5"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="order.delivery_type === 'pickup' && pickupInfo">
|
||||
<div class="alert alert-info" v-html="getName(pickupText)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-5" >
|
||||
<div class="all_sum">
|
||||
<div class="row mb-3 mb-md-0">
|
||||
<div class="col-md-6 mb-md-2">
|
||||
<span>{{ $t('vue.checkout.delivery_total_cost') }}</span>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-right">
|
||||
<span>{{ prices | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="row mb-3 mb-md-0">-->
|
||||
<!-- <div class="col-md-6 mb-md-2">-->
|
||||
<!-- <span>Промокод:</span>-->
|
||||
<!-- <a href="#" class="d-block">Ввести другой промокод</a>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="col-md-6 text-md-right">-->
|
||||
<!-- <span>RY38990</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="row mb-3 mb-md-0">-->
|
||||
<!-- <div class="col-md-6 mb-md-2">-->
|
||||
<!-- <span>Скидка по промокоду:</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="col-md-6 text-md-right">-->
|
||||
<!-- <span>56 000 сум</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<div class="row mb-3 mb-md-0" v-if="order.delivery_type === 'delivery' && deliveryInfo && order.delivery_price > 0">
|
||||
<div class="col-md-6 mb-md-2">
|
||||
<span>{{ $t('vue.checkout.delivery_price') }}:</span>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-right">
|
||||
<span>{{ order.delivery_price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 mb-md-0">
|
||||
<div class="col-md-6 mb-md-2">
|
||||
<span>{{ $t('vue.checkout.delivery_total_amount') }}:</span>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-right">
|
||||
<span>{{ order.delivery_type === 'delivery' ? prices + order.delivery_price : prices | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="mt-4 mb-3">{{ $t('vue.checkout.delivery_about_price') }}</h3>
|
||||
<div class="form-payment">
|
||||
<div class="custom-control custom-radio custom-control-inline" v-if="cash">
|
||||
<input type="radio" class="custom-control-input" id="payment-1" name="payment_type" value="cash" v-model="order.payment_type" checked="">
|
||||
<label class="custom-control-label" for="payment-1">{{ $t('vue.checkout.delivery_in_cash') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input" id="payment-2" value="apelsin" v-model="order.payment_type" name="payment_type">
|
||||
<label class="custom-control-label" for="payment-2">Apelsin</label>
|
||||
</div>
|
||||
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input" id="payment-3" value="payme" v-model="order.payment_type" name="payment_type">
|
||||
<label class="custom-control-label" for="payment-3">Payme</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input" id="payment-4" value="click" v-model="order.payment_type" name="payment_type">
|
||||
<label class="custom-control-label" for="payment-4">Click</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" v-if="error">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" v-if="error_type === 'available'" :key="index">
|
||||
{{ error }}
|
||||
</li>
|
||||
|
||||
<li v-for="(error, index) in errors" v-if="error_type === 'validation'" :key="index">
|
||||
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-md-start justify-content-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange">{{ $t('vue.cart.checkout_product') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
cartData: {},
|
||||
loginInfo: {},
|
||||
pricesData: {},
|
||||
regionsData: {},
|
||||
deliveryPrice: {},
|
||||
pickupInfo: {},
|
||||
deliveryInfo: {},
|
||||
pickupText: {},
|
||||
firstName: {},
|
||||
addressData: {}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'order.delivery_type': function (newVal, oldVal) {
|
||||
this.order.delivery_type = newVal;
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
user: {
|
||||
phone: null,
|
||||
verify: null,
|
||||
password: null,
|
||||
password_confirmation: null,
|
||||
remember: false,
|
||||
step: 1,
|
||||
},
|
||||
|
||||
prices: this.pricesData,
|
||||
|
||||
address: {
|
||||
first_name: this.firstName,
|
||||
region_id: 0,
|
||||
city_id: null,
|
||||
address: this.addressData,
|
||||
other_phone: null,
|
||||
comment: null
|
||||
},
|
||||
|
||||
order: {
|
||||
delivery_type: this.deliveryInfo ? 'delivery' : 'pickup',
|
||||
delivery_price: this.deliveryInfo ? this.deliveryPrice : 0,
|
||||
payment_type: 'cash'
|
||||
},
|
||||
|
||||
regions: this.regionsData,
|
||||
cities: [],
|
||||
|
||||
verify: false,
|
||||
|
||||
step: this.loginInfo ? 3 : 2,
|
||||
|
||||
error: false,
|
||||
errors: [],
|
||||
error_type: null,
|
||||
|
||||
password_error: false,
|
||||
cash: true,
|
||||
|
||||
login: this.loginInfo
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.cities = this.regions[0].cities;
|
||||
this.address.city_id = this.cities[0] ? this.cities[0].id : null;
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
async SendForm () {
|
||||
|
||||
if (this.user.step === 1) {
|
||||
const { data } = await axios.post('/auth/login', {
|
||||
phone: this.user.phone
|
||||
});
|
||||
|
||||
this.user.step = data.step;
|
||||
// this.verify = true;
|
||||
} else if (this.user.step === 2) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/register', {
|
||||
phone: this.user.phone,
|
||||
password: this.user.password,
|
||||
password_confirmation: this.user.password_confirmation,
|
||||
});
|
||||
|
||||
this.user.step = data.step;
|
||||
} catch (error) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
} else if (this.user.step === 3) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/verify', {
|
||||
phone: this.user.phone,
|
||||
code: this.user.verify,
|
||||
//type: type,
|
||||
//action: action
|
||||
//credit: this.$cookie.get('product-credit') ? this.$cookie.get('product-credit') : null,
|
||||
});
|
||||
if (data.status) {
|
||||
this.login = true;
|
||||
this.step = 3;
|
||||
this.error = false;
|
||||
this.address.first_name = data.first_name;
|
||||
this.address.address = data.address
|
||||
}
|
||||
} catch (error) {
|
||||
this.password_error = true;
|
||||
}
|
||||
} else if (this.user.step === 4 ) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/password', {
|
||||
phone: this.user.phone,
|
||||
password: this.user.password,
|
||||
//type: type,
|
||||
//action: action,
|
||||
remember: this.user.remember
|
||||
//credit: this.$cookie.get('product-credit') ? this.$cookie.get('product-credit') : null,
|
||||
});
|
||||
|
||||
if (data.status) {
|
||||
this.login = true;
|
||||
this.step = 3;
|
||||
this.error = false;
|
||||
this.address.first_name = data.first_name;
|
||||
this.address.address = data.address
|
||||
}
|
||||
} catch (error) {
|
||||
this.password_error = true;
|
||||
}
|
||||
} else if (this.user.step === 5) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/restore', {
|
||||
phone: this.user.phone,
|
||||
});
|
||||
|
||||
this.user.step = data.step;
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
} else if (this.user.step === 6) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/restore/verify', {
|
||||
phone: this.user.phone,
|
||||
code: this.user.verify
|
||||
});
|
||||
|
||||
this.user.password = null;
|
||||
this.user.password_confirmation = null;
|
||||
|
||||
this.user.step = data.step;
|
||||
} catch (error) {
|
||||
this.password_error = true;
|
||||
}
|
||||
} else if (this.user.step === 7) {
|
||||
try {
|
||||
const { data } = await axios.post('/auth/restore/confirm', {
|
||||
phone: this.user.phone,
|
||||
password: this.user.password,
|
||||
password_confirmation: this.user.password_confirmation,
|
||||
//type: type,
|
||||
//action: action
|
||||
//credit: this.$cookie.get('product-credit') ? this.$cookie.get('product-credit') : null,
|
||||
});
|
||||
if (data.status) {
|
||||
this.login = true;
|
||||
this.step = 3;
|
||||
this.error = false;
|
||||
this.address.first_name = data.first_name;
|
||||
this.address.address = data.address
|
||||
}
|
||||
} catch (error) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
// async LoginSend() {
|
||||
// if (!this.verify) {
|
||||
// const { data } = await axios.post('/auth/login', {
|
||||
// phone: this.user.phone
|
||||
// });
|
||||
//
|
||||
// this.verify = true;
|
||||
// } else {
|
||||
//
|
||||
// try {
|
||||
// const { data } = await axios.post('/auth/verify', this.user);
|
||||
// if (data.status) {
|
||||
// this.login = true;
|
||||
// this.step = 3;
|
||||
// this.error = false;
|
||||
// this.address.first_name = data.first_name;
|
||||
// this.address.address = data.address
|
||||
// }
|
||||
// } catch (error) {
|
||||
// this.error = true;
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
|
||||
async Resend () {
|
||||
if (this.verify) {
|
||||
await axios.post('/api/auth/login', {
|
||||
phone: this.user.phone
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
},
|
||||
|
||||
async SendOrder() {
|
||||
var product_id = [];
|
||||
|
||||
for (var i = 0; i < this.cartData.length; i++) {
|
||||
product_id.push(this.cartData[i].id);
|
||||
}
|
||||
|
||||
const fields = {
|
||||
delivery_type: this.order.delivery_type,
|
||||
delivery_price: this.order.delivery_price,
|
||||
payment_type: this.order.payment_type,
|
||||
products: product_id,
|
||||
|
||||
address: this.address,
|
||||
};
|
||||
|
||||
try {
|
||||
const { data } = await axios.post('/checkout', fields);
|
||||
if (data.status) {
|
||||
window.location.href = data.url
|
||||
} else {
|
||||
this.error = true;
|
||||
this.errors = data.errors;
|
||||
this.error_type = 'available';
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.response.status === 422) {
|
||||
this.error = true;
|
||||
this.errors = err.response.data.errors;
|
||||
this.error_type = 'validation';
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
changeRegion(event) {
|
||||
let index = parseInt(event.target.value);
|
||||
this.cash = this.regions[index].cash;
|
||||
|
||||
if (this.cash) {
|
||||
this.order.payment_type = 'cash'
|
||||
} else {
|
||||
this.order.payment_type = 'payme'
|
||||
}
|
||||
|
||||
this.cities = this.regions[index].cities;
|
||||
|
||||
this.address.city_id = this.cities[0] ? this.cities[0].id : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
27
resources/js/components/Comment/CommentList.vue
Executable file
27
resources/js/components/Comment/CommentList.vue
Executable file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="media msg">
|
||||
<div class="media-body">
|
||||
<small class="pull-right time">
|
||||
<i class="fas fa-calendar-alt mr-2"></i> {{ comment.created_at }}
|
||||
</small>
|
||||
<h5 class="media-heading">{{ comment.first_name }}</h5>
|
||||
<small v-html="comment.body"></small>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['commentData'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
comment: this.commentData
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
224
resources/js/components/Compilation/Store.vue
Executable file
224
resources/js/components/Compilation/Store.vue
Executable file
@@ -0,0 +1,224 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="col-md-12 col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Добавить</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<form class="form form-vertical" @submit.prevent="Store">
|
||||
<div class="card-body">
|
||||
<div class="form-body">
|
||||
<p>Все поля обозначенные * обязательные</p>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="ru">Названия RU *</label>
|
||||
<input type="text" id="ru" class="form-control" v-model="title.ru"placeholder="Названия RU *">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="uz">Названия UZ *</label>
|
||||
<input type="text" id="uz" class="form-control" v-model="title.uz" placeholder="Названия UZ *">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория</label>
|
||||
<select id="category" class="form-control" v-model="category_id">
|
||||
<option value="0">Все</option>
|
||||
<option v-for="category in categories" :value="category.id">
|
||||
{{ category.name.ru }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label>Продукты *</label>
|
||||
|
||||
<multiselect v-model="compilations"
|
||||
placeholder="Искать"
|
||||
label="name"
|
||||
track-by="name"
|
||||
:options="products"
|
||||
:option-height="104"
|
||||
:custom-label="customLabel"
|
||||
:show-labels="false"
|
||||
@search-change="SearchProduct"
|
||||
:multiple="true"
|
||||
>
|
||||
|
||||
<template slot="singleLabel" slot-scope="props">
|
||||
<img class="option__image" :src="props.option.poster" width="50" alt="No Man’s Sky">
|
||||
<span class="option__desc">
|
||||
<span class="option__title">{{ props.option.name }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template slot="option" slot-scope="props">
|
||||
<img class="option__image" :src="props.option.poster" width="50" alt="No Man’s Sky">
|
||||
<div class="option__desc">
|
||||
<span class="option__title">{{ props.option.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</multiselect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label>Выбранные продукты</label>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
|
||||
<tbody>
|
||||
<tr v-for="(product, index) in compilations">
|
||||
<td>
|
||||
<img :src="product.poster" width="100" >
|
||||
</td>
|
||||
<td>
|
||||
{{ product.name }}
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" @click="Delete(index)" class="btn btn-danger btn-sm btn-icon">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="col-12">-->
|
||||
<!-- <fieldset>-->
|
||||
<!-- <div class="vs-checkbox-con vs-checkbox-primary">-->
|
||||
<!-- <input type="checkbox" v-model="published">-->
|
||||
<!-- <span class="vs-checkbox">-->
|
||||
<!-- <span class="vs-checkbox--check">-->
|
||||
<!-- <i class="vs-icon feather icon-check"></i>-->
|
||||
<!-- </span>-->
|
||||
<!-- </span>-->
|
||||
|
||||
<!-- <span class="">Публиковать</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </fieldset>-->
|
||||
<!-- </div>-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="col-12 mb-0">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<button type="submit" class="btn btn-primary mr-1 mb-1 waves-effect waves-light btn-icon">
|
||||
<i class="feather icon-save"></i> {{ $t('admin.save') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-9">
|
||||
<a href="/dashboard/compilations" class="btn btn-danger mr-1 mb-1 waves-effect waves-light btn-icon pull-right">
|
||||
<i class="feather icon-x-circle"></i> {{ $t('admin.cancel') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['categories'],
|
||||
|
||||
data: () => ({
|
||||
title: {
|
||||
ru: null,
|
||||
uz: null
|
||||
},
|
||||
products: [],
|
||||
|
||||
published: false,
|
||||
|
||||
category_id: null,
|
||||
|
||||
compilations: [],
|
||||
|
||||
}),
|
||||
|
||||
mounted() {
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
customLabel ({ name }) {
|
||||
return `${name}`
|
||||
},
|
||||
|
||||
async Store() {
|
||||
const array = {
|
||||
title: this.title,
|
||||
products: this.compilations,
|
||||
published: this.published,
|
||||
category_id: this.category_id
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/dashboard/compilations/store', array);
|
||||
|
||||
if (data.status) {
|
||||
window.location.href = "/dashboard/compilations";
|
||||
}
|
||||
},
|
||||
|
||||
async SearchProduct(query) {
|
||||
let name = query;
|
||||
|
||||
if (name.length > 0) {
|
||||
axios.post('/dashboard/compilations/product/search', { name: name})
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
this.products = response.data.products;
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log(query);
|
||||
},
|
||||
|
||||
Delete(index) {
|
||||
this.compilations.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
225
resources/js/components/Compilation/Update.vue
Executable file
225
resources/js/components/Compilation/Update.vue
Executable file
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="col-md-12 col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Добавить</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<form class="form form-vertical" @submit.prevent="Update">
|
||||
<div class="card-body">
|
||||
<div class="form-body">
|
||||
<p>Все поля обозначенные * обязательные</p>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="ru">Названия RU *</label>
|
||||
<input type="text" id="ru" class="form-control" v-model="title.ru"placeholder="Названия RU *">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="uz">Названия UZ *</label>
|
||||
<input type="text" id="uz" class="form-control" v-model="title.uz" placeholder="Названия UZ *">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория</label>
|
||||
<select id="category" class="form-control" v-model="category_id">
|
||||
<option value="0">Все</option>
|
||||
<option v-for="category in categories" :value="category.id">
|
||||
{{ category.name.ru }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label>Продукты *</label>
|
||||
|
||||
<multiselect v-model="compilations"
|
||||
placeholder="Искать"
|
||||
label="name"
|
||||
track-by="name"
|
||||
:options="products"
|
||||
:option-height="104"
|
||||
:custom-label="customLabel"
|
||||
:show-labels="false"
|
||||
@search-change="SearchProduct"
|
||||
:multiple="true"
|
||||
>
|
||||
|
||||
<template slot="singleLabel" slot-scope="props">
|
||||
<img class="option__image" :src="props.option.poster" width="50" alt="No Man’s Sky">
|
||||
<span class="option__desc">
|
||||
<span class="option__title">{{ props.option.name }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template slot="option" slot-scope="props">
|
||||
<img class="option__image" :src="props.option.poster" width="50" alt="No Man’s Sky">
|
||||
<div class="option__desc">
|
||||
<span class="option__title">{{ props.option.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</multiselect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label>Выбранные продукты</label>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
|
||||
<tbody>
|
||||
<tr v-for="(product, index) in compilations">
|
||||
<td>
|
||||
<img :src="product.poster" width="100" >
|
||||
</td>
|
||||
<td>
|
||||
{{ product.name }}
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" @click="Delete(index)" class="btn btn-danger btn-sm btn-icon">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="col-12">-->
|
||||
<!-- <fieldset>-->
|
||||
<!-- <div class="vs-checkbox-con vs-checkbox-primary">-->
|
||||
<!-- <input type="checkbox" v-model="published">-->
|
||||
<!-- <span class="vs-checkbox">-->
|
||||
<!-- <span class="vs-checkbox--check">-->
|
||||
<!-- <i class="vs-icon feather icon-check"></i>-->
|
||||
<!-- </span>-->
|
||||
<!-- </span>-->
|
||||
|
||||
<!-- <span class="">Публиковать</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </fieldset>-->
|
||||
<!-- </div>-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="col-12 mb-0">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<button type="submit" class="btn btn-primary mr-1 mb-1 waves-effect waves-light btn-icon">
|
||||
<i class="feather icon-save"></i> {{ $t('admin.save') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-9">
|
||||
<a href="/dashboard/compilations" class="btn btn-danger mr-1 mb-1 waves-effect waves-light btn-icon pull-right">
|
||||
<i class="feather icon-x-circle"></i> {{ $t('admin.cancel') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
compilation: {},
|
||||
categories: {}
|
||||
},
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
title: {
|
||||
ru: this.compilation.title.ru,
|
||||
uz: this.compilation.title.uz,
|
||||
},
|
||||
published: this.compilation.published,
|
||||
|
||||
compilations: this.compilation.products,
|
||||
category_id: this.compilation.category_id,
|
||||
|
||||
products: []
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
customLabel ({ name }) {
|
||||
return `${name}`
|
||||
},
|
||||
|
||||
async Update() {
|
||||
const array = {
|
||||
title: this.title,
|
||||
products: this.compilations,
|
||||
published: this.published,
|
||||
category_id: this.category_id
|
||||
};
|
||||
const { data } = await axios.post('/dashboard/compilations/update/' + this.compilation.id, array);
|
||||
|
||||
if (data.status) {
|
||||
window.location.href = "/dashboard/compilations";
|
||||
}
|
||||
},
|
||||
|
||||
async SearchProduct(query) {
|
||||
let name = query;
|
||||
|
||||
if (name.length > 0) {
|
||||
axios.post('/dashboard/compilations/product/search', { name: name})
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
this.products = response.data.products;
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log(query);
|
||||
},
|
||||
|
||||
Delete(index) {
|
||||
this.compilations.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
306
resources/js/components/Dashboard/Category/Index.vue
Executable file
306
resources/js/components/Dashboard/Category/Index.vue
Executable file
@@ -0,0 +1,306 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div
|
||||
class="card"
|
||||
style="
|
||||
border-radius: 0;
|
||||
box-shadow: 0 -1px 4px 0 rgb(0 0 0 / 15%);
|
||||
"
|
||||
>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="">Категория</label>
|
||||
<select
|
||||
v-model="category"
|
||||
@change="handleMainCategory"
|
||||
class="form-control"
|
||||
>
|
||||
<option :value="null">---</option>
|
||||
<option
|
||||
v-for="category in mainCategories"
|
||||
:value="category"
|
||||
>
|
||||
{{ category.category }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="">Подкатегория</label>
|
||||
<select
|
||||
v-model="subCategory"
|
||||
@change="handleSubCategory"
|
||||
class="form-control"
|
||||
>
|
||||
<option :value="null">---</option>
|
||||
<option
|
||||
v-for="category in subCategories"
|
||||
:value="category"
|
||||
>
|
||||
{{ category.category }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Tree
|
||||
:data="categories"
|
||||
@change="Change"
|
||||
draggable="draggable"
|
||||
cross-tree="cross-tree"
|
||||
>
|
||||
<div slot-scope="{ data, store }">
|
||||
<template v-if="!data.isDragPlaceHolder">
|
||||
<div class="d-flex justify-content-start">
|
||||
<b
|
||||
v-if="data.children && data.children.length"
|
||||
@click="store.toggleOpen(data)"
|
||||
>
|
||||
<i
|
||||
:class="
|
||||
data.open
|
||||
? 'fa fa-minus-square'
|
||||
: 'fa fa-plus-square'
|
||||
"
|
||||
></i>
|
||||
|
||||
</b>
|
||||
<span>
|
||||
<b>ID: {{ data.id }} </b>
|
||||
{{ data.category }}
|
||||
</span>
|
||||
|
||||
<div class="ml-auto">
|
||||
<a
|
||||
:href="
|
||||
'/dashboard/categories/update/' +
|
||||
data.id
|
||||
"
|
||||
class="btn-primary btn btn-icon btn-sm"
|
||||
>
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
|
||||
<a
|
||||
:href="
|
||||
'/dashboard/categories/delete/' +
|
||||
data.id
|
||||
"
|
||||
onclick="return confirm('Вы действително хотите удалить')"
|
||||
class="btn-danger btn btn-icon btn-sm"
|
||||
>
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</Tree>
|
||||
<div class="mt-2 mb-3">
|
||||
<button class="btn btn-primary" @click="SendForm">
|
||||
<i class="fa fa-save"></i> Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { DraggableTree } from "vue-draggable-nested-tree";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
categoriesData: {},
|
||||
},
|
||||
|
||||
components: {
|
||||
Tree: DraggableTree,
|
||||
},
|
||||
|
||||
mounted() {
|
||||
console.log(this.categoriesData);
|
||||
this.Change();
|
||||
},
|
||||
|
||||
data() {
|
||||
console.log(this.categoriesData);
|
||||
return {
|
||||
categories: this.categoriesData,
|
||||
mainCategories: this.categoriesData,
|
||||
subCategories: [],
|
||||
category: null,
|
||||
subCategory: null,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
async SendForm() {
|
||||
const formData = new FormData();
|
||||
for (var i = 0; i < this.categories.length; i++) {
|
||||
formData.append(
|
||||
"categories[" + i + "][id]",
|
||||
this.categories[i].id
|
||||
);
|
||||
formData.append(
|
||||
"categories[" + i + "][position]",
|
||||
this.categories[i].position
|
||||
);
|
||||
formData.append(
|
||||
"categories[" + i + "][parent_id]",
|
||||
this.categories[i].parent_id
|
||||
);
|
||||
if (this.categories[i].children.length > 0) {
|
||||
for (
|
||||
var c = 0;
|
||||
c < this.categories[i].children.length;
|
||||
c++
|
||||
) {
|
||||
formData.append(
|
||||
"categories[" + i + "][children][" + c + "][id]",
|
||||
this.categories[i].children[c].id
|
||||
);
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][position]",
|
||||
this.categories[i].children[c].position
|
||||
);
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][parent_id]",
|
||||
this.categories[i].children[c].parent_id
|
||||
);
|
||||
if (
|
||||
this.categories[i].children[c].children.length > 0
|
||||
) {
|
||||
for (
|
||||
var w = 0;
|
||||
w <
|
||||
this.categories[i].children[c].children.length;
|
||||
w++
|
||||
) {
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][children][" +
|
||||
w +
|
||||
"][id]",
|
||||
this.categories[i].children[c].children[w]
|
||||
.id
|
||||
);
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][children][" +
|
||||
w +
|
||||
"][position]",
|
||||
this.categories[i].children[c].children[w]
|
||||
.position
|
||||
);
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][children][" +
|
||||
w +
|
||||
"][parent_id]",
|
||||
this.categories[i].children[c].children[w]
|
||||
.parent_id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { data } = await axios.post(
|
||||
"/dashboard/categories/position",
|
||||
formData
|
||||
);
|
||||
|
||||
if (data.status) {
|
||||
// window.location.href = "/dashboard/categories";
|
||||
}
|
||||
},
|
||||
|
||||
Change() {
|
||||
for (var i = 0; i < this.categories.length; i++) {
|
||||
var num = i + 1;
|
||||
|
||||
this.categories[i].position = num;
|
||||
this.categories[i].droppable = true;
|
||||
|
||||
if (this.categories[i].children.length > 0) {
|
||||
for (
|
||||
var c = 0;
|
||||
c < this.categories[i].children.length;
|
||||
c++
|
||||
) {
|
||||
var numm = c + 1;
|
||||
this.categories[i].children[c].position = numm;
|
||||
this.categories[i].children[c].parent_id =
|
||||
this.categories[i].id;
|
||||
this.categories[i].children[c].droppable = true;
|
||||
|
||||
if (
|
||||
this.categories[i].children[c].children.length > 0
|
||||
) {
|
||||
for (
|
||||
var w = 0;
|
||||
w <
|
||||
this.categories[i].children[c].children.length;
|
||||
w++
|
||||
) {
|
||||
var nummm = w + 1;
|
||||
|
||||
this.categories[i].children[c].children[
|
||||
w
|
||||
].position = nummm;
|
||||
this.categories[i].children[c].children[
|
||||
w
|
||||
].parent_id = this.categories[i].children[c].id;
|
||||
this.categories[i].children[c].children[
|
||||
w
|
||||
].droppable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleMainCategory() {
|
||||
if (this.category) {
|
||||
this.categories = this.category.children;
|
||||
this.subCategories = this.category.children;
|
||||
} else {
|
||||
this.categories = this.categoriesData;
|
||||
this.subCategories = null;
|
||||
}
|
||||
},
|
||||
|
||||
handleSubCategory() {
|
||||
if (this.subCategory) this.categories = this.subCategory.children;
|
||||
else this.categories = this.category.children;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
821
resources/js/components/Dashboard/Category/Store.vue
Executable file
821
resources/js/components/Dashboard/Category/Store.vue
Executable file
@@ -0,0 +1,821 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<form
|
||||
class="form form-vertical w-100"
|
||||
@submit.prevent="saveForm"
|
||||
action="#"
|
||||
enctype="multipart/form-data"
|
||||
method="post"
|
||||
>
|
||||
<div class="col-md-12 col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">{{ $t("admin.add") }}</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="form-body">
|
||||
<p>{{ $t("admin.all_fields_with") }}</p>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label
|
||||
for="first-name-vertical"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.name"
|
||||
)
|
||||
}}
|
||||
UZ *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="first-name-vertical"
|
||||
v-model="
|
||||
category.name.uz
|
||||
"
|
||||
required
|
||||
class="form-control"
|
||||
name="name[uz]"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.name'
|
||||
) + ' UZ'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="nameru"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.name"
|
||||
)
|
||||
}}
|
||||
RU *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="nameru"
|
||||
required
|
||||
v-model="
|
||||
category.name.ru
|
||||
"
|
||||
class="form-control"
|
||||
name="name[ru]"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.name'
|
||||
) + ' RU'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="position"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.position"
|
||||
)
|
||||
}}
|
||||
*</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="position"
|
||||
required
|
||||
class="form-control"
|
||||
v-model="category.position"
|
||||
name="position"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.position'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-file">
|
||||
<input
|
||||
id="uploadImage"
|
||||
class="custom-file-input"
|
||||
type="file"
|
||||
name="image"
|
||||
@change="ImageFile($event)"
|
||||
onchange="PreviewImage();"
|
||||
/>
|
||||
<label
|
||||
class="custom-file-label"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.image"
|
||||
)
|
||||
}}</label
|
||||
>
|
||||
</div>
|
||||
<br />
|
||||
<div class="text-center">
|
||||
<img
|
||||
id="uploadPreview"
|
||||
style="
|
||||
width: 300px;
|
||||
height: auto;
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label
|
||||
>{{
|
||||
$t("admin.brands.title")
|
||||
}}
|
||||
*</label
|
||||
>
|
||||
|
||||
<multiselect
|
||||
:options="brandsData"
|
||||
v-model="category.brands"
|
||||
:multiple="true"
|
||||
:taggable="true"
|
||||
label="name"
|
||||
track-by="name"
|
||||
></multiselect>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<h3>Характеристики</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div
|
||||
class="col-12"
|
||||
v-for="(char, index) in char"
|
||||
:key="index"
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<div class="form-group">
|
||||
<label
|
||||
:for="
|
||||
'first-name-vertical-uz' +
|
||||
index
|
||||
"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.char.name"
|
||||
)
|
||||
}}
|
||||
UZ *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
:id="
|
||||
'first-name-vertical-uz' +
|
||||
index
|
||||
"
|
||||
v-model="
|
||||
char.name.uz
|
||||
"
|
||||
required
|
||||
class="form-control"
|
||||
name="name[uz]"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.name'
|
||||
) + ' UZ'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="form-group">
|
||||
<label
|
||||
:for="
|
||||
'first-name-vertical-ru' +
|
||||
index
|
||||
"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.char.name"
|
||||
)
|
||||
}}
|
||||
RU *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
:id="
|
||||
'first-name-vertical-ru' +
|
||||
index
|
||||
"
|
||||
v-model="
|
||||
char.name.ru
|
||||
"
|
||||
required
|
||||
class="form-control"
|
||||
name="name[uz]"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.name'
|
||||
) + ' RU'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label
|
||||
:for="
|
||||
'type' +
|
||||
index
|
||||
"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.char.type"
|
||||
)
|
||||
}}
|
||||
*</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
:id="
|
||||
'type' +
|
||||
index
|
||||
"
|
||||
v-model="
|
||||
char.type
|
||||
"
|
||||
>
|
||||
<option
|
||||
value="text"
|
||||
>
|
||||
Text
|
||||
</option>
|
||||
<option
|
||||
value="number"
|
||||
>
|
||||
Number
|
||||
</option>
|
||||
<option
|
||||
value="checkbox"
|
||||
>
|
||||
checkbox
|
||||
</option>
|
||||
<option
|
||||
value="select"
|
||||
>
|
||||
select
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-1">
|
||||
<fieldset>
|
||||
<label
|
||||
>Фильтр</label
|
||||
>
|
||||
<div
|
||||
class="vs-checkbox-con vs-checkbox-primary"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="
|
||||
char.filter
|
||||
"
|
||||
/>
|
||||
<span
|
||||
class="vs-checkbox"
|
||||
>
|
||||
<span
|
||||
class="vs-checkbox--check"
|
||||
>
|
||||
<i
|
||||
class="vs-icon feather icon-check"
|
||||
></i>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-1">
|
||||
<button
|
||||
@click="
|
||||
removeChar(
|
||||
index
|
||||
)
|
||||
"
|
||||
class="btn btn-danger mt-2"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="fa fa-trash"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-warning"
|
||||
@click="addChar"
|
||||
>
|
||||
<i class="fa fa-plus"></i> Добавить
|
||||
характеристики
|
||||
</button>
|
||||
|
||||
<div class="controls mt-1">
|
||||
<button
|
||||
id="add_cat"
|
||||
type="button"
|
||||
class="btn btn-outline-primary w-100"
|
||||
>
|
||||
{{
|
||||
$t(
|
||||
"admin.categories.add_cat"
|
||||
)
|
||||
}}
|
||||
</button>
|
||||
<button
|
||||
id="remove_cat"
|
||||
type="button"
|
||||
class="btn btn-secondary w-100"
|
||||
>
|
||||
{{
|
||||
$t(
|
||||
"admin.categories.remove_cat"
|
||||
)
|
||||
}}
|
||||
</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div id="sub_cat" class="controls">
|
||||
<label>{{
|
||||
$t(
|
||||
"admin.categories.sub_category"
|
||||
)
|
||||
}}</label>
|
||||
<select
|
||||
class="form-control"
|
||||
v-model="category.parent_id"
|
||||
>
|
||||
<option value="0">
|
||||
{{
|
||||
$t(
|
||||
"admin.categories.choose_cat"
|
||||
)
|
||||
}}
|
||||
</option>
|
||||
|
||||
<option
|
||||
v-for="(
|
||||
category, index
|
||||
) in categoriesData"
|
||||
:key="index"
|
||||
:value="category.id"
|
||||
>
|
||||
{{
|
||||
getName(
|
||||
category.name
|
||||
)
|
||||
}}
|
||||
<span
|
||||
v-if="
|
||||
category.parent
|
||||
"
|
||||
>
|
||||
(
|
||||
{{
|
||||
getName(
|
||||
category
|
||||
.parent
|
||||
.name
|
||||
)
|
||||
}}
|
||||
)
|
||||
</span>
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">SEO</h4>
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="nameru"
|
||||
>Title Seo RU *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
v-model="category.title_seo.ru"
|
||||
id="nameru"
|
||||
class="form-control"
|
||||
placeholder="Title Seo RU *"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="name">Title Seo UZ *</label>
|
||||
<input
|
||||
type="text"
|
||||
v-model="category.title_seo.uz"
|
||||
id="name"
|
||||
class="form-control"
|
||||
placeholder="Title Seo UZ *"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-md-6 float-left">
|
||||
<fieldset class="form-label-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
v-model="
|
||||
category.keywords.ru
|
||||
"
|
||||
id="label-keywords-ru"
|
||||
rows="3"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.settings.keywords'
|
||||
) + ' RU'
|
||||
"
|
||||
></textarea>
|
||||
<label for="label-keywords-ru"
|
||||
>{{
|
||||
$t(
|
||||
"admin.settings.keywords"
|
||||
)
|
||||
}}
|
||||
RU *</label
|
||||
>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 float-left">
|
||||
<fieldset class="form-label-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
v-model="
|
||||
category.keywords.uz
|
||||
"
|
||||
id="label-keywords"
|
||||
rows="3"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.settings.keywords'
|
||||
) + ' UZ'
|
||||
"
|
||||
></textarea>
|
||||
<label for="label-keywords"
|
||||
>{{
|
||||
$t(
|
||||
"admin.settings.keywords"
|
||||
)
|
||||
}}
|
||||
UZ *</label
|
||||
>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-md-6 float-left">
|
||||
<fieldset class="form-label-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
v-model="
|
||||
category.descriptions.ru
|
||||
"
|
||||
id="label-description-ru"
|
||||
rows="3"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.settings.description'
|
||||
) + ' RU'
|
||||
"
|
||||
></textarea>
|
||||
<label
|
||||
for="label-description-ru"
|
||||
>{{
|
||||
$t(
|
||||
"admin.settings.description"
|
||||
)
|
||||
}}
|
||||
RU *</label
|
||||
>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 float-left">
|
||||
<fieldset class="form-label-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
v-model="
|
||||
category.descriptions.uz
|
||||
"
|
||||
id="label-description"
|
||||
rows="3"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.settings.description'
|
||||
) + ' UZ'
|
||||
"
|
||||
></textarea>
|
||||
<label for="label-description"
|
||||
>{{
|
||||
$t(
|
||||
"admin.settings.description"
|
||||
)
|
||||
}}
|
||||
UZ *</label
|
||||
>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12" v-if="error">
|
||||
<div class="alert alert-danger mt-2">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" :key="index">
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="form-group mt-1">
|
||||
<fieldset class="checkbox">
|
||||
<div
|
||||
class="vs-checkbox-con vs-checkbox-primary"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
value="1"
|
||||
name="popular"
|
||||
v-model="category.published"
|
||||
/>
|
||||
<span class="vs-checkbox">
|
||||
<span class="vs-checkbox--check">
|
||||
<i
|
||||
class="vs-icon feather icon-check"
|
||||
></i>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class=""> Опубликовать </span>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="checkbox">
|
||||
<div
|
||||
class="vs-checkbox-con vs-checkbox-primary"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
value="1"
|
||||
name="is_filter_power"
|
||||
v-model="category.is_filter_power"
|
||||
/>
|
||||
<span class="vs-checkbox">
|
||||
<span class="vs-checkbox--check">
|
||||
<i
|
||||
class="vs-icon feather icon-check"
|
||||
></i>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="">
|
||||
Сортировать по kW
|
||||
</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer pb-0 pl-0 pt-1">
|
||||
<div class="col-12 mb-0">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary mr-1 mb-1 waves-effect waves-light btn-icon"
|
||||
>
|
||||
<i class="feather icon-save"></i>
|
||||
{{ $t("admin.save") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-9">
|
||||
<a
|
||||
href="/dashboard/categories"
|
||||
class="btn btn-danger mr-1 mb-1 waves-effect waves-light btn-icon pull-right"
|
||||
>
|
||||
<i
|
||||
class="feather icon-x-circle"
|
||||
></i>
|
||||
{{ $t("admin.cancel") }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["brandsData", "categoriesData"],
|
||||
|
||||
data() {
|
||||
return {
|
||||
category: {
|
||||
name: {
|
||||
uz: "",
|
||||
ru: "",
|
||||
},
|
||||
|
||||
published: true,
|
||||
position: 0,
|
||||
brands: [],
|
||||
is_filter_power: false,
|
||||
|
||||
parent_id: 0,
|
||||
|
||||
descriptions: {
|
||||
uz: "",
|
||||
ru: "",
|
||||
},
|
||||
|
||||
keywords: {
|
||||
uz: "",
|
||||
ru: "",
|
||||
},
|
||||
|
||||
title_seo: {
|
||||
uz: "",
|
||||
ru: "",
|
||||
},
|
||||
|
||||
image: null,
|
||||
},
|
||||
|
||||
char: [],
|
||||
|
||||
error: false,
|
||||
errors: [],
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = "";
|
||||
|
||||
if (lang) {
|
||||
switch (lang) {
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
async saveForm() {
|
||||
const header = {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
};
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("name[ru]", this.category.name.ru);
|
||||
formData.append("name[uz]", this.category.name.uz);
|
||||
|
||||
formData.append("position", this.category.position);
|
||||
formData.append("parent_id", this.category.parent_id);
|
||||
if (this.category.image)
|
||||
formData.append("image", this.category.image);
|
||||
formData.append("published", this.category.published);
|
||||
formData.append("is_filter_power", this.category.is_filter_power);
|
||||
formData.append("descriptions[ru]", this.category.descriptions.ru);
|
||||
formData.append("descriptions[uz]", this.category.descriptions.uz);
|
||||
formData.append("keywords[ru]", this.category.keywords.ru);
|
||||
formData.append("keywords[uz]", this.category.keywords.uz);
|
||||
formData.append("title_seo[ru]", this.category.title_seo.ru);
|
||||
formData.append("title_seo[uz]", this.category.title_seo.uz);
|
||||
|
||||
for (var i = 0; i < this.category.brands.length; i++) {
|
||||
formData.append(
|
||||
"brands[" + i + "]",
|
||||
this.category.brands[i].id
|
||||
);
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.char.length; i++) {
|
||||
formData.append(
|
||||
"char[" + i + "][name][ru]",
|
||||
this.char[i].name.ru
|
||||
);
|
||||
formData.append(
|
||||
"char[" + i + "][name][uz]",
|
||||
this.char[i].name.uz
|
||||
);
|
||||
formData.append("char[" + i + "][type]", this.char[i].type);
|
||||
formData.append("char[" + i + "][filter]", this.char[i].filter);
|
||||
}
|
||||
|
||||
axios
|
||||
.post("/dashboard/categories/store", formData, header)
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
window.location.href = "/dashboard/categories";
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ImageFile(event) {
|
||||
this.category.image = event.target.files[0];
|
||||
},
|
||||
|
||||
addChar() {
|
||||
this.char.push({
|
||||
name: {
|
||||
ru: "",
|
||||
uz: "",
|
||||
},
|
||||
type: "text",
|
||||
filter: false,
|
||||
});
|
||||
},
|
||||
|
||||
removeChar(index) {
|
||||
this.char.splice(index, 1);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
|
||||
<style scoped></style>
|
||||
836
resources/js/components/Dashboard/Category/Update.vue
Executable file
836
resources/js/components/Dashboard/Category/Update.vue
Executable file
@@ -0,0 +1,836 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<form
|
||||
class="form form-vertical w-100"
|
||||
@submit.prevent="saveForm"
|
||||
action="#"
|
||||
enctype="multipart/form-data"
|
||||
method="post"
|
||||
>
|
||||
<div class="col-md-12 col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">{{ $t("admin.edit") }}</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="form-body">
|
||||
<p>{{ $t("admin.all_fields_with") }}</p>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label
|
||||
for="first-name-vertical"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.name"
|
||||
)
|
||||
}}
|
||||
UZ *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="first-name-vertical"
|
||||
v-model="
|
||||
category.name.uz
|
||||
"
|
||||
required
|
||||
class="form-control"
|
||||
name="name[uz]"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.name'
|
||||
) + ' UZ'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="nameru"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.name"
|
||||
)
|
||||
}}
|
||||
RU *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="nameru"
|
||||
required
|
||||
v-model="
|
||||
category.name.ru
|
||||
"
|
||||
class="form-control"
|
||||
name="name[ru]"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.name'
|
||||
) + ' RU'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="position"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.position"
|
||||
)
|
||||
}}
|
||||
*</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="position"
|
||||
required
|
||||
class="form-control"
|
||||
v-model="category.position"
|
||||
name="position"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.position'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-file">
|
||||
<input
|
||||
id="uploadImage"
|
||||
class="custom-file-input"
|
||||
type="file"
|
||||
name="image"
|
||||
@change="ImageFile($event)"
|
||||
onchange="PreviewImage();"
|
||||
/>
|
||||
<label
|
||||
class="custom-file-label"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.image"
|
||||
)
|
||||
}}</label
|
||||
>
|
||||
</div>
|
||||
<br />
|
||||
<div class="text-center">
|
||||
<img
|
||||
id="uploadPreview"
|
||||
style="
|
||||
width: 300px;
|
||||
height: auto;
|
||||
"
|
||||
:src="category.image"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label
|
||||
>{{
|
||||
$t("admin.brands.title")
|
||||
}}
|
||||
*</label
|
||||
>
|
||||
|
||||
<multiselect
|
||||
:options="brandsData"
|
||||
v-model="category.brands"
|
||||
:multiple="true"
|
||||
:taggable="true"
|
||||
label="name"
|
||||
track-by="name"
|
||||
></multiselect>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<h3>Характеристики</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div
|
||||
class="col-12"
|
||||
v-for="(
|
||||
char, index
|
||||
) in category.characteristics"
|
||||
:key="index"
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<div class="form-group">
|
||||
<label
|
||||
:for="
|
||||
'first-name-vertical-uz' +
|
||||
index
|
||||
"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.char.name"
|
||||
)
|
||||
}}
|
||||
UZ *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
:id="
|
||||
'first-name-vertical-uz' +
|
||||
index
|
||||
"
|
||||
v-model="
|
||||
char.name.uz
|
||||
"
|
||||
required
|
||||
class="form-control"
|
||||
name="name[uz]"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.name'
|
||||
) + ' UZ'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="form-group">
|
||||
<label
|
||||
:for="
|
||||
'first-name-vertical-ru' +
|
||||
index
|
||||
"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.char.name"
|
||||
)
|
||||
}}
|
||||
RU *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
:id="
|
||||
'first-name-vertical-ru' +
|
||||
index
|
||||
"
|
||||
v-model="
|
||||
char.name.ru
|
||||
"
|
||||
required
|
||||
class="form-control"
|
||||
name="name[uz]"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.categories.name'
|
||||
) + ' RU'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label
|
||||
:for="
|
||||
'type' +
|
||||
index
|
||||
"
|
||||
>{{
|
||||
$t(
|
||||
"admin.categories.char.type"
|
||||
)
|
||||
}}
|
||||
*</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
:id="
|
||||
'type' +
|
||||
index
|
||||
"
|
||||
v-model="
|
||||
char.type
|
||||
"
|
||||
>
|
||||
<option
|
||||
value="text"
|
||||
>
|
||||
Text
|
||||
</option>
|
||||
<option
|
||||
value="number"
|
||||
>
|
||||
Number
|
||||
</option>
|
||||
<option
|
||||
value="checkbox"
|
||||
>
|
||||
checkbox
|
||||
</option>
|
||||
<option
|
||||
value="select"
|
||||
>
|
||||
select
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-1">
|
||||
<fieldset>
|
||||
<label
|
||||
>Фильтр</label
|
||||
>
|
||||
<div
|
||||
class="vs-checkbox-con vs-checkbox-primary"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="
|
||||
char.filter
|
||||
"
|
||||
/>
|
||||
<span
|
||||
class="vs-checkbox"
|
||||
>
|
||||
<span
|
||||
class="vs-checkbox--check"
|
||||
>
|
||||
<i
|
||||
class="vs-icon feather icon-check"
|
||||
></i>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-1">
|
||||
<button
|
||||
@click="
|
||||
removeChar(
|
||||
index,
|
||||
char
|
||||
)
|
||||
"
|
||||
class="btn btn-danger mt-2"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="fa fa-trash"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-warning"
|
||||
@click="addChar"
|
||||
>
|
||||
<i class="fa fa-plus"></i> Добавить
|
||||
характеристики
|
||||
</button>
|
||||
|
||||
<div class="controls mt-1">
|
||||
<button
|
||||
id="add_cat"
|
||||
type="button"
|
||||
class="btn btn-outline-primary w-100"
|
||||
>
|
||||
{{
|
||||
$t(
|
||||
"admin.categories.add_cat"
|
||||
)
|
||||
}}
|
||||
</button>
|
||||
<button
|
||||
id="remove_cat"
|
||||
type="button"
|
||||
class="btn btn-secondary w-100"
|
||||
>
|
||||
{{
|
||||
$t(
|
||||
"admin.categories.remove_cat"
|
||||
)
|
||||
}}
|
||||
</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div id="sub_cat" class="controls">
|
||||
<label>{{
|
||||
$t(
|
||||
"admin.categories.sub_category"
|
||||
)
|
||||
}}</label>
|
||||
<select
|
||||
class="form-control"
|
||||
v-model="category.parent_id"
|
||||
>
|
||||
<option value="0">
|
||||
{{
|
||||
$t(
|
||||
"admin.categories.choose_cat"
|
||||
)
|
||||
}}
|
||||
</option>
|
||||
|
||||
<option
|
||||
v-for="(
|
||||
category, index
|
||||
) in categoriesData"
|
||||
:key="index"
|
||||
:value="category.id"
|
||||
>
|
||||
{{
|
||||
getName(
|
||||
category.name
|
||||
)
|
||||
}}
|
||||
<span
|
||||
v-if="
|
||||
category.parent
|
||||
"
|
||||
>
|
||||
(
|
||||
{{
|
||||
getName(
|
||||
category
|
||||
.parent
|
||||
.name
|
||||
)
|
||||
}}
|
||||
)
|
||||
</span>
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12" v-if="error">
|
||||
<div class="alert alert-danger mt-2">
|
||||
<ul>
|
||||
<li
|
||||
v-for="(
|
||||
error, index
|
||||
) in errors"
|
||||
:key="index"
|
||||
>
|
||||
<span
|
||||
v-for="msg in error"
|
||||
:key="msg"
|
||||
>
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">SEO</h4>
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="nameru"
|
||||
>Title Seo RU *</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
v-model="category.title_seo.ru"
|
||||
id="nameru"
|
||||
class="form-control"
|
||||
placeholder="Title Seo RU *"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="name">Title Seo UZ *</label>
|
||||
<input
|
||||
type="text"
|
||||
v-model="category.title_seo.uz"
|
||||
id="name"
|
||||
class="form-control"
|
||||
placeholder="Title Seo UZ *"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-md-6 float-left">
|
||||
<fieldset class="form-label-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
v-model="
|
||||
category.keywords.ru
|
||||
"
|
||||
id="label-keywords-ru"
|
||||
rows="3"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.settings.keywords'
|
||||
) + ' RU'
|
||||
"
|
||||
></textarea>
|
||||
<label for="label-keywords-ru"
|
||||
>{{
|
||||
$t(
|
||||
"admin.settings.keywords"
|
||||
)
|
||||
}}
|
||||
RU *</label
|
||||
>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 float-left">
|
||||
<fieldset class="form-label-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
v-model="
|
||||
category.keywords.uz
|
||||
"
|
||||
id="label-keywords"
|
||||
rows="3"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.settings.keywords'
|
||||
) + ' UZ'
|
||||
"
|
||||
></textarea>
|
||||
<label for="label-keywords"
|
||||
>{{
|
||||
$t(
|
||||
"admin.settings.keywords"
|
||||
)
|
||||
}}
|
||||
UZ *</label
|
||||
>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-md-6 float-left">
|
||||
<fieldset class="form-label-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
v-model="
|
||||
category.descriptions.ru
|
||||
"
|
||||
id="label-description-ru"
|
||||
rows="3"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.settings.description'
|
||||
) + ' RU'
|
||||
"
|
||||
></textarea>
|
||||
<label
|
||||
for="label-description-ru"
|
||||
>{{
|
||||
$t(
|
||||
"admin.settings.description"
|
||||
)
|
||||
}}
|
||||
RU *</label
|
||||
>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 float-left">
|
||||
<fieldset class="form-label-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
v-model="
|
||||
category.descriptions.uz
|
||||
"
|
||||
id="label-description"
|
||||
rows="3"
|
||||
:placeholder="
|
||||
$t(
|
||||
'admin.settings.description'
|
||||
) + ' UZ'
|
||||
"
|
||||
></textarea>
|
||||
<label for="label-description"
|
||||
>{{
|
||||
$t(
|
||||
"admin.settings.description"
|
||||
)
|
||||
}}
|
||||
UZ *</label
|
||||
>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<fieldset class="checkbox">
|
||||
<div
|
||||
class="vs-checkbox-con vs-checkbox-primary"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
value="1"
|
||||
name="popular"
|
||||
v-model="category.published"
|
||||
/>
|
||||
<span class="vs-checkbox">
|
||||
<span class="vs-checkbox--check">
|
||||
<i
|
||||
class="vs-icon feather icon-check"
|
||||
></i>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class=""> Опубликовать </span>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="checkbox">
|
||||
<div
|
||||
class="vs-checkbox-con vs-checkbox-primary"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
value="1"
|
||||
name="is_filter_power"
|
||||
v-model="category.is_filter_power"
|
||||
/>
|
||||
<span class="vs-checkbox">
|
||||
<span class="vs-checkbox--check">
|
||||
<i
|
||||
class="vs-icon feather icon-check"
|
||||
></i>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="">
|
||||
Сортировать по kW
|
||||
</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer pb-0 pl-0 pt-1">
|
||||
<div class="col-12 mb-0">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary mr-1 mb-1 waves-effect waves-light btn-icon"
|
||||
>
|
||||
<i class="feather icon-save"></i>
|
||||
{{ $t("admin.save") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-9">
|
||||
<a
|
||||
href="/dashboard/categories"
|
||||
class="btn btn-danger mr-1 mb-1 waves-effect waves-light btn-icon pull-right"
|
||||
>
|
||||
<i class="feather icon-x-circle"></i>
|
||||
{{ $t("admin.cancel") }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
brandsData: {},
|
||||
categoriesData: {},
|
||||
categoryData: {},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
category: this.categoryData,
|
||||
|
||||
char: [],
|
||||
file: null,
|
||||
|
||||
error: false,
|
||||
errors: [],
|
||||
|
||||
deleted: {
|
||||
char: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = "";
|
||||
|
||||
if (lang) {
|
||||
switch (lang) {
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
async saveForm() {
|
||||
const header = {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
};
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("name[ru]", this.category.name.ru);
|
||||
formData.append("name[uz]", this.category.name.uz);
|
||||
|
||||
formData.append("position", this.category.position);
|
||||
|
||||
//formData.append('brands', this.category.brands);
|
||||
formData.append("parent_id", this.category.parent_id);
|
||||
formData.append("published", this.category.published);
|
||||
formData.append("is_filter_power", this.category.is_filter_power);
|
||||
formData.append("image", this.file);
|
||||
formData.append("descriptions[ru]", this.category.descriptions.ru);
|
||||
formData.append("descriptions[uz]", this.category.descriptions.uz);
|
||||
formData.append("keywords[ru]", this.category.keywords.ru);
|
||||
formData.append("keywords[uz]", this.category.keywords.uz);
|
||||
|
||||
formData.append("title_seo[ru]", this.category.title_seo.ru);
|
||||
formData.append("title_seo[uz]", this.category.title_seo.uz);
|
||||
|
||||
for (var i = 0; i < this.category.brands.length; i++) {
|
||||
formData.append(
|
||||
"brands[" + i + "]",
|
||||
this.category.brands[i].id
|
||||
);
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.category.characteristics.length; i++) {
|
||||
formData.append(
|
||||
"char[" + i + "][name][ru]",
|
||||
this.category.characteristics[i].name.ru
|
||||
);
|
||||
formData.append(
|
||||
"char[" + i + "][name][uz]",
|
||||
this.category.characteristics[i].name.uz
|
||||
);
|
||||
formData.append(
|
||||
"char[" + i + "][type]",
|
||||
this.category.characteristics[i].type
|
||||
);
|
||||
formData.append(
|
||||
"char[" + i + "][filter]",
|
||||
this.category.characteristics[i].filter
|
||||
);
|
||||
formData.append(
|
||||
"char[" + i + "][id]",
|
||||
this.category.characteristics[i].id
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.deleted.char.length; i++) {
|
||||
formData.append(
|
||||
"deletes[char][" + i + "]",
|
||||
this.deleted.char[i]
|
||||
);
|
||||
}
|
||||
|
||||
axios
|
||||
.post(
|
||||
"/dashboard/categories/update/" + this.category.id,
|
||||
formData,
|
||||
header
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
window.location.href = "/dashboard/categories";
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ImageFile(event) {
|
||||
this.file = event.target.files[0];
|
||||
},
|
||||
|
||||
addChar() {
|
||||
this.category.characteristics.push({
|
||||
id: null,
|
||||
name: {
|
||||
ru: "",
|
||||
uz: "",
|
||||
},
|
||||
type: "text",
|
||||
filter: false,
|
||||
});
|
||||
},
|
||||
|
||||
removeChar(index, char) {
|
||||
if (char.id != null) this.deleted.char.push(char.id);
|
||||
|
||||
this.category.characteristics.splice(index, 1);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped></style>
|
||||
533
resources/js/components/Dashboard/Logs.vue
Executable file
533
resources/js/components/Dashboard/Logs.vue
Executable file
@@ -0,0 +1,533 @@
|
||||
<template>
|
||||
<div>
|
||||
<ul class="activity-timeline timeline-left list-unstyled" :key="index">
|
||||
<!-- v-if="log.log_name != 'products' && log.decription != 'created' && log.properties.attributes.name != null"-->
|
||||
<li v-for="(log, index) in logs" :key="index">
|
||||
<div class="timeline-icon bg-primary" v-if="log.description == 'updated'">
|
||||
<i class="feather icon-edit font-medium-2 align-middle"></i>
|
||||
</div>
|
||||
|
||||
<div class="timeline-icon bg-danger" v-if="log.description == 'deleted'">
|
||||
<i class="feather icon-trash-2 font-medium-2 align-middle"></i>
|
||||
</div>
|
||||
|
||||
<div class="timeline-icon bg-success" v-if="log.description == 'created'">
|
||||
<i class="feather icon-plus-circle font-medium-2 align-middle"></i>
|
||||
</div>
|
||||
|
||||
<div class="timeline-info">
|
||||
<p class="font-weight-bold mb-0">
|
||||
|
||||
<i :class="getIcon(log)"></i> {{ getType(log) }}
|
||||
|
||||
</p>
|
||||
<span class="font-small-3" v-html="getMessage(log)">
|
||||
</span>
|
||||
<a href="#" @click="getData(log)" data-toggle="modal" data-target="#exampleModalLong">
|
||||
подробнее
|
||||
</a>
|
||||
</div>
|
||||
<small class="text-muted">
|
||||
{{ log.created_at | moment("HH:mm, DD.MM.YYYY") }} | ID: {{ log.causer.id }} | Пользователь: <b>{{ log.causer.username }}</b>
|
||||
</small>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="modal fade" id="exampleModalLong" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLongTitle">Подробнее</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" v-if="log_modal">
|
||||
<fieldset class="form-group">
|
||||
<label for="basicInput">Пользователь</label>
|
||||
<input type="text" class="form-control" disabled :value="log.causer.username" id="basicInput">
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group">
|
||||
<label for="basicInput">ID</label>
|
||||
<input type="text" class="form-control" disabled :value="log.subject_id" id="basicInput" >
|
||||
</fieldset>
|
||||
|
||||
<div v-if="log.log_name === 'products'">
|
||||
<div v-if="log.description">
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.name">
|
||||
<label for="basicInput">Названия Ru</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.name.ru" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.name.ru : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.name">
|
||||
<label for="basicInput">Названия Uz</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.name.uz" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.name.uz : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.price">
|
||||
<label for="basicInput">Цена</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.price" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.price : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.price_discount">
|
||||
<label for="basicInput">Цена со скидкой</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.price_discount" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.price_discount : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.count <= 0">
|
||||
<label for="basicInput">Количество товаров на складе</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.count" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.count : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.article_number">
|
||||
<label for="basicInput">Артикул</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.article_number" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.article_number : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.published === false || log.properties.attributes.published">
|
||||
<label for="basicInput">Публиковать</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.published" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.published : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.available === false || log.properties.attributes.available">
|
||||
<label for="basicInput">В наличии</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.available" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.available : '' }}
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="log.log_name === 'orders'">
|
||||
<div v-if="log.description">
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.status">
|
||||
<label for="basicInput">Статус</label>
|
||||
<input type="text" class="form-control" disabled :value="getStatus(log.properties.attributes.status)" id="basicInput" >
|
||||
Было: {{ getStatus(log.properties.old.status) }}
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="log.log_name === 'staffs'">
|
||||
<div v-if="log.description">
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.username">
|
||||
<label for="basicInput">Логин</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.username" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.username : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.password">
|
||||
<label for="basicInput">Пароль</label>
|
||||
<input type="password" class="form-control" disabled :value="log.properties.attributes.password" id="basicInput" >
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.role.name">
|
||||
<label for="basicInput">Роль</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.role.name" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.role.name : '' }}
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="log.log_name === 'roles'">
|
||||
<div v-if="log.description">
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.name">
|
||||
<label for="basicInput">Названия</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.name" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.name : '' }}
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="log.log_name != 'products'">
|
||||
<div v-if="log.description">
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.name">
|
||||
<label for="basicInput">Названия Ru</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.name.ru" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.name.ru : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.name">
|
||||
<label for="basicInput">Названия Uz</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.name.uz" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.name.uz : '' }}
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="log.log_name === 'special_offer'">
|
||||
<div v-if="log.description">
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.description">
|
||||
<label for="basicInput">Описания Ru</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.description.ru" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.name.ru : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.description">
|
||||
<label for="basicInput">Описания Uz</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.description.uz" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.description.uz : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.link">
|
||||
<label for="basicInput">Ccылка</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.link" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.link : '' }}
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="log.log_name === 'settings'">
|
||||
<div v-if="log.description">
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.title">
|
||||
<label for="basicInput">Названия Ru</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.title.ru" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.title.ru : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.title">
|
||||
<label for="basicInput">Названия Uz</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.title.uz" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.title.uz : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.phone">
|
||||
<label for="basicInput">Телефон</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.phone.default" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.phone.default : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.phone">
|
||||
<label for="basicInput">Телефон другой</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.phone.other" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.phone.other : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.address">
|
||||
<label for="basicInput">Адрес Ru</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.address.ru" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.address.ru : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.address">
|
||||
<label for="basicInput">Адрес Uz</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.address.uz" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.address.uz : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.socials">
|
||||
<label for="basicInput">Телеграм</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.socials.telegram" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.socials.telegram : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.socials">
|
||||
<label for="basicInput">Facebook</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.socials.facebook" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.socials.facebook : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.socials">
|
||||
<label for="basicInput">Instagram</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.socials.instagram" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.socials.instagram : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.socials">
|
||||
<label for="basicInput">Youtube</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.socials.youtube" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.socials.youtube : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.socials">
|
||||
<label for="basicInput">Ok.ru</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.socials.okru" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.socials.okru : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.email">
|
||||
<label for="basicInput">Email</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.email" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.email : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.landmark">
|
||||
<label for="basicInput">Ориентер Ru</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.landmark.ru" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.landmark.ru : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.address">
|
||||
<label for="basicInput">Ориентер Uz</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.landmark.uz" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.landmark.uz : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.day_delivery">
|
||||
<label for="basicInput">Время доставки</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.day_delivery" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.day_delivery : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.price_delivery">
|
||||
<label for="basicInput">Стоимость доставки</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.price_delivery" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.day_delivery : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.pickup === false || log.properties.attributes.pickup">
|
||||
<label for="basicInput">Самовывоз</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.pickup" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.pickup : '' }}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form-group" v-if="log.properties.attributes.delivery === false || log.properties.attributes.delivery">
|
||||
<label for="basicInput">Доставка курьером</label>
|
||||
<input type="text" class="form-control" disabled :value="log.properties.attributes.delivery" id="basicInput" >
|
||||
Было: {{ log.properties.old ? log.properties.old.delivery : '' }}
|
||||
</fieldset>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Закрыть</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
logsData: {}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
logs: this.logsData.data,
|
||||
|
||||
log_modal: false,
|
||||
log: {}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getType(log) {
|
||||
let message;
|
||||
switch (log.log_name) {
|
||||
case 'roles':
|
||||
message = 'Роли';
|
||||
break;
|
||||
case 'products':
|
||||
message = 'Продукты';
|
||||
break;
|
||||
case 'orders':
|
||||
message = 'Заказы';
|
||||
break;
|
||||
case 'staffs':
|
||||
message = 'Стаф';
|
||||
break;
|
||||
case 'users':
|
||||
message = 'Пользователи';
|
||||
break;
|
||||
case 'posts':
|
||||
message = 'Посты';
|
||||
break;
|
||||
case 'sliders':
|
||||
message = 'Баннеры';
|
||||
break;
|
||||
case 'categories':
|
||||
message = 'Категории';
|
||||
break;
|
||||
case 'billings':
|
||||
message = 'История оплаты';
|
||||
break;
|
||||
case 'regions':
|
||||
message = 'Регионы';
|
||||
break;
|
||||
case 'cities':
|
||||
message = 'Города';
|
||||
break;
|
||||
case 'settings':
|
||||
message = 'Настройки';
|
||||
break;
|
||||
case 'addresses':
|
||||
message = 'Адрес';
|
||||
break;
|
||||
case 'brand':
|
||||
message = 'Бренды';
|
||||
break;
|
||||
case 'pages':
|
||||
message = 'Страницы';
|
||||
break;
|
||||
case 'special_offer':
|
||||
message = 'Спецпредложения';
|
||||
break;
|
||||
}
|
||||
|
||||
// addresses, brand, pages, special_offer
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
getIcon(log) {
|
||||
let icon;
|
||||
switch (log.log_name) {
|
||||
case 'roles':
|
||||
icon = 'feather icon-check-circle';
|
||||
break;
|
||||
case 'products':
|
||||
icon = 'feather icon-box';
|
||||
break;
|
||||
case 'orders':
|
||||
icon = 'feather icon-shopping-cart';
|
||||
break;
|
||||
case 'staffs':
|
||||
icon = 'feather icon-users';
|
||||
break;
|
||||
case 'users':
|
||||
icon = 'feather icon-users';
|
||||
break;
|
||||
case 'posts':
|
||||
icon = 'feather icon-align-center';
|
||||
break;
|
||||
case 'sliders':
|
||||
icon = 'feather icon-align-center';
|
||||
break;
|
||||
case 'categories':
|
||||
icon = 'feather icon-tag';
|
||||
break;
|
||||
case 'billings':
|
||||
icon = 'feather icon-credit-card';
|
||||
break;
|
||||
case 'regions':
|
||||
icon = 'feather icon-database';
|
||||
break;
|
||||
case 'cities':
|
||||
icon = 'feather icon-layers';
|
||||
break;
|
||||
case 'settings':
|
||||
icon = 'feather icon-settings';
|
||||
break;
|
||||
case 'addresses':
|
||||
icon = 'feather icon-home';
|
||||
break;
|
||||
case 'brand':
|
||||
icon = 'feather icon-cast';
|
||||
break;
|
||||
case 'pages':
|
||||
icon = 'feather icon-align-center';
|
||||
break;
|
||||
case 'special_offer':
|
||||
icon = 'feather icon-command';
|
||||
break;
|
||||
}
|
||||
|
||||
return icon;
|
||||
},
|
||||
|
||||
getMessage(log) {
|
||||
let message;
|
||||
switch (log.description) {
|
||||
case 'created':
|
||||
message = '<b>ID: ' + log.subject_id + '</b> успешно создано';
|
||||
break;
|
||||
case 'deleted':
|
||||
message = '<b>ID: ' + log.subject_id + '</b> успешно удалено';
|
||||
break;
|
||||
case 'updated':
|
||||
message = '<b>ID: ' + log.subject_id + '</b> успешно редактировано';
|
||||
break;
|
||||
}
|
||||
|
||||
return message;
|
||||
// switch (log.log_name) {
|
||||
// case 'products':
|
||||
// switch (log.description) {
|
||||
// case 'created':
|
||||
// message = 'Продукт <b>ID: ' + log.subject_id + '</b> успешно создано';
|
||||
// break;
|
||||
// case 'deleted':
|
||||
// message = 'Продукт <b>ID: ' + log.subject_id + '</b> успешно удалено';
|
||||
// break;
|
||||
// case 'updated':
|
||||
// message = 'Продукт <b>ID: ' + log.subject_id + '</b> успешно редактировано';
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// case 'orders':
|
||||
// switch (log.description) {
|
||||
// case 'deleted':
|
||||
// message = 'Заказ <b>ID: ' + log.subject_id + '</b> успешно удалено';
|
||||
// break;
|
||||
// case 'updated':
|
||||
// message = 'Заказ <b>ID: ' + log.subject_id + '</b> успешно редактировано';
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// return message;
|
||||
},
|
||||
|
||||
getStatus(status) {
|
||||
let message;
|
||||
switch (status) {
|
||||
case 'processing':
|
||||
message = 'В обработке';
|
||||
break;
|
||||
case 'collected':
|
||||
message = 'Собран';
|
||||
break;
|
||||
case 'waiting_buyer':
|
||||
message = 'Ожидает покупателя';
|
||||
break;
|
||||
case 'in_way':
|
||||
message = 'В пути';
|
||||
break;
|
||||
case 'closed':
|
||||
message = 'Закрыт';
|
||||
break;
|
||||
case 'cancelled':
|
||||
message = 'Отменен';
|
||||
break;
|
||||
case 'replacement':
|
||||
message = 'Замена';
|
||||
break;
|
||||
}
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
getData(log) {
|
||||
this.log_modal = true;
|
||||
this.log = log;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
0
resources/js/components/Dashboard/Statics.vue
Executable file
0
resources/js/components/Dashboard/Statics.vue
Executable file
23
resources/js/components/ExampleComponent.vue
Executable file
23
resources/js/components/ExampleComponent.vue
Executable file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">Example Component</div>
|
||||
|
||||
<div class="card-body">
|
||||
I'm an example component.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
console.log('Component mounted.')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
238
resources/js/components/Favorites/FavoriteBlock.vue
Executable file
238
resources/js/components/Favorites/FavoriteBlock.vue
Executable file
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<div>
|
||||
<section v-if="!mobile" class="section-favorite d-md-block d-none">
|
||||
<div class="container">
|
||||
<h3 class="mb-3 section-title-small">{{ $t('app.favorites.title') }}</h3>
|
||||
<p class="mb-3 " v-if="favorites.length === 0">
|
||||
{{ $t('app.no_product') }}
|
||||
</p>
|
||||
|
||||
<div class="row" v-if="favorites.length > 0">
|
||||
<div v-for="(product, index) in favorites" class="col-lg-12 col-md-6">
|
||||
<div class="product my-3">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-2">
|
||||
<div class="product-img">
|
||||
<img :src="'/' + product.poster_thumb" :alt="getName(product.name)" :class="!product.isAvailable ? 'no-product-img' : ''" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<h3 class="product-title">
|
||||
<a :href="'/product/show/' + product.id + '-' + product.slug">
|
||||
{{ getName(product.name) }}
|
||||
</a>
|
||||
</h3>
|
||||
<div class="product-address">{{ $t('app.product.article_number') }}: {{ product.article_number }}</div>
|
||||
<div class="product-price_and_checkout mt-2">
|
||||
<div class="product-price-by-count mr-3">{{ $t('app.price') }} {{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum_sht') }}</div>
|
||||
<button class="my-btn my-btn__orange my-btn__orange--small" v-if="product.discountPrice > 0 && product.price_discount">{{ $t('app.discount') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-xl-2">
|
||||
<div class="product-price">
|
||||
<div class="title-price">{{ $t('app.price') }}</div>
|
||||
<div class="old-price mb-1" v-if="product.price_discount">
|
||||
{{ product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}
|
||||
</div>
|
||||
<div class="new-price">{{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-xl-4">
|
||||
<div class="product-buttons">
|
||||
<div class="product-to_cart">
|
||||
<button v-if="!product.isCart" :class="product.isCart ? 'product-to_basket is-active is-actived' : 'product-to_basket is-actived'" @click="AddToCart(product)">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span>{{ $t('app.to_cart') }}</span>
|
||||
|
||||
<div class="added-to-basket" v-html="$t('vue.favorite.added_to_basket')">
|
||||
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button v-if="product.isCart && product.isAvailable" :class="product.isCart ? 'product-to_basket is-active is-actived' : 'product-to_basket is-actived'" @click="AddToCart(product)">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span>{{ $t('app.to_cart') }}</span>
|
||||
|
||||
|
||||
</button>
|
||||
|
||||
<!-- <a href="balance.html" class="product-balance_link">-->
|
||||
<!-- <button class="product-to_compares">-->
|
||||
<!-- <i class="fas fa-balance-scale"></i>-->
|
||||
<!-- </button>-->
|
||||
<!-- <span>{{ $t('app.compare') }}</span>-->
|
||||
<!-- </a>-->
|
||||
</div>
|
||||
<div class="v-line">|</div>
|
||||
<button @click="removeProduct(product, index)" class="product-to_delete">
|
||||
<i class="fal fa-times fa-2x"></i>
|
||||
<span>{{ $t('app.delete') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Избранные товары -->
|
||||
<section v-if="mobile" class="section-products d-block d-md-none section-favorite">
|
||||
<div class="container">
|
||||
<h3 class="section-title-small">
|
||||
{{ $t('app.favorites.title') }}
|
||||
</h3>
|
||||
|
||||
<p class="mb-3 " v-if="favorites.length === 0">
|
||||
{{ $t('app.no_product') }}
|
||||
</p>
|
||||
|
||||
<div class="swiper-container swiper-product swiper-favorite">
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-slide" v-for="(product, index) in favorites">
|
||||
<div class="product">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-2">
|
||||
<div class="product-img">
|
||||
<img :src="'/' + product.poster_thumb" :alt="getName(product.name)" :class="!product.isAvailable ? 'no-product-img' : ''" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<h3 class="product-title">{{ getName(product.name) }}</h3>
|
||||
<div class="product-address">{{ $t('app.product.article_number') }}: {{ product.article_number }}</div>
|
||||
<div class="product-price_and_checkout mt-2">
|
||||
<div class="product-price-by-count mr-3">{{ $t('app.price') }} {{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum_sht') }}</div>
|
||||
<button class="my-btn my-btn__orange my-btn__orange--small">{{ $t('app.discount') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-xl-2">
|
||||
<div class="product-price">
|
||||
<div class="title-price">{{ $t('app.price') }}</div>
|
||||
<div class="old-price mb-1" v-if="product.price_discount">
|
||||
{{ product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}
|
||||
</div>
|
||||
<div class="new-price">{{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-xl-4">
|
||||
<div class="product-buttons">
|
||||
<div class="product-to_cart">
|
||||
|
||||
<button v-if="product.isCart && product.isAvailable" :class="product.isCart ? 'product-to_basket is-active is-actived' : 'product-to_basket is-actived'" @click="AddToCart(product)">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span>{{ $t('app.to_cart') }}</span>
|
||||
|
||||
|
||||
</button>
|
||||
|
||||
<!-- <a href="balance.html" class="product-balance_link">-->
|
||||
<!-- <button class="product-to_compares">-->
|
||||
<!-- <i class="fas fa-balance-scale"></i>-->
|
||||
<!-- </button>-->
|
||||
<!-- <span>{{ $t('app.compare') }}</span>-->
|
||||
<!-- </a>-->
|
||||
</div>
|
||||
<div class="v-line">|</div>
|
||||
<button @click="removeProduct(product, index)" class="product-to_delete">
|
||||
<i class="fal fa-times fa-2x"></i>
|
||||
<span>{{ $t('app.delete') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Add Arrows -->
|
||||
<div class="swiper-button-next swiper-button-next-product"></div>
|
||||
<div class="swiper-button-prev swiper-button-prev-product"></div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-product"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isMobile } from 'mobile-device-detect';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
products: {},
|
||||
loginInfo: {}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
mobile: isMobile ? true : false,
|
||||
favorites: this.products.data
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
},
|
||||
|
||||
async removeProduct(product, index) {
|
||||
var field = document.getElementById("favorite-count");
|
||||
var count = field.value;
|
||||
|
||||
const { data } = await axios.get('/favorites/delete/' + product.id);
|
||||
|
||||
if (data.status) {
|
||||
this.favorites.splice(index, 1);
|
||||
field.value = parseInt(count) - 1;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
async AddToCart(product) {
|
||||
if (product.isCart) {
|
||||
this.$eventBus.$emit('cart-preview');
|
||||
return;
|
||||
}
|
||||
|
||||
const fields = {
|
||||
product_id: product.children.id,
|
||||
count: 1
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/cart/store', fields);
|
||||
|
||||
if (data.status) {
|
||||
product.isCart = true;
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
195
resources/js/components/FeaturesSection.vue
Executable file
195
resources/js/components/FeaturesSection.vue
Executable file
@@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Category -->
|
||||
<section class="section-category">
|
||||
<div class="container">
|
||||
<div class="category" v-if="!mobile">
|
||||
<a :href="settingData.links.one" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img1.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_1') }}</h3>
|
||||
</a>
|
||||
<a :href="settingData.links.two" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img2.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_2') }}</h3>
|
||||
</a>
|
||||
<a :href="settingData.links.three" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img3.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_3') }}</h3>
|
||||
</a>
|
||||
<a :href="settingData.links.four" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img4.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_4') }}</h3>
|
||||
</a>
|
||||
<a :href="settingData.links.five" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img5.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_5') }}</h3>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<swiper
|
||||
ref="mySwiperCategory"
|
||||
class="swiper-container swiper-product swiper-category"
|
||||
:options="swiperOptions"
|
||||
v-if="mobile"
|
||||
>
|
||||
<swiper-slide>
|
||||
<a :href="settingData.links.one" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img1.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_1') }}</h3>
|
||||
</a>
|
||||
</swiper-slide>
|
||||
<swiper-slide>
|
||||
<a :href="settingData.links.two" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img2.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_2') }}</h3>
|
||||
</a>
|
||||
</swiper-slide>
|
||||
<swiper-slide>
|
||||
<a :href="settingData.links.three" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img3.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_3') }}</h3>
|
||||
</a>
|
||||
</swiper-slide>
|
||||
<swiper-slide>
|
||||
<a :href="settingData.links.four" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img4.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_4') }}</h3>
|
||||
</a>
|
||||
</swiper-slide>
|
||||
<swiper-slide>
|
||||
<a :href="settingData.links.five" class="category-item">
|
||||
<div class="category-item__logo">
|
||||
<img src="/vendor/site/img/category_img5.png" alt />
|
||||
</div>
|
||||
<h3 class="category-item__title">{{ $t('vue.feature.feature_title_5') }}</h3>
|
||||
</a>
|
||||
</swiper-slide>
|
||||
|
||||
<!-- Add Arrows -->
|
||||
<div class="swiper-button-next swiper-button-next-product" slot="button-next"></div>
|
||||
<div class="swiper-button-prev swiper-button-prev-product" slot="button-prev"></div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-product" slot="pagination"></div>
|
||||
</swiper>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
|
||||
// import "swiper/swiper-bundle.css";
|
||||
import "swiper/css/swiper.css";
|
||||
import { isMobileOnly } from "mobile-device-detect";
|
||||
export default {
|
||||
props: {
|
||||
settingData: {}
|
||||
},
|
||||
|
||||
components: {
|
||||
Swiper,
|
||||
SwiperSlide,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
swiperOptions: {
|
||||
spaceBetween: 20,
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next-product",
|
||||
prevEl: ".swiper-button-prev-product",
|
||||
},
|
||||
pagination: {
|
||||
el: ".swiper-pagination-product",
|
||||
dynamicBullets: true,
|
||||
},
|
||||
breakpoints: {
|
||||
1200: {
|
||||
slidesPerView: 6,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 4,
|
||||
},
|
||||
576: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
0: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
},
|
||||
autoplay: {
|
||||
delay: 5500,
|
||||
},
|
||||
},
|
||||
products: [],
|
||||
mobile: isMobileOnly ? true : false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
swiper() {
|
||||
return this.$refs.mySwiperCategory.$swiper;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$breakpoints: (
|
||||
"phone-smallest": 251px,
|
||||
"phone-small": 321px,
|
||||
"phone": 400px,
|
||||
"phone-wide": 480px,
|
||||
"phablet": 560px,
|
||||
"tablet-small": 640px,
|
||||
"tablet": 768px,
|
||||
"tablet-wide": 1024px,
|
||||
"desktop": 1248px,
|
||||
"desktop-wide": 1440px,
|
||||
"desktop-large": 2500px,
|
||||
);
|
||||
|
||||
@mixin mq($width, $type: min) {
|
||||
@if map_has_key($breakpoints, $width) {
|
||||
$width: map_get($breakpoints, $width);
|
||||
|
||||
@if $type==max {
|
||||
$width: $width - 1px;
|
||||
}
|
||||
|
||||
@media only screen and (#{$type}-width: $width) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-product {
|
||||
padding: 75px 0 20px;
|
||||
margin-top: -50px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
|
||||
@include mq("tablet", max) {
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
146
resources/js/components/Home.vue
Executable file
146
resources/js/components/Home.vue
Executable file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-sm-6 col-12">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex flex-column align-items-start pb-0">
|
||||
<div class="avatar bg-rgba-primary p-50 m-0">
|
||||
<div class="avatar-content">
|
||||
<i class="feather icon-users text-primary font-medium-5"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="text-bold-700 mt-1">{{ users }}</h2>
|
||||
<p class="mb-0">Пользователи</p>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-sm-6 col-12">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex flex-column align-items-start pb-0">
|
||||
<div class="avatar bg-rgba-success p-50 m-0">
|
||||
<div class="avatar-content">
|
||||
<i class="feather icon-credit-card text-success font-medium-5"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="text-bold-700 mt-1">{{ revenue | getRevenue }}</h2>
|
||||
<p class="mb-0">Доход</p>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-sm-6 col-12">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex flex-column align-items-start pb-0">
|
||||
<div class="avatar bg-rgba-warning p-50 m-0">
|
||||
<div class="avatar-content">
|
||||
<i class="feather icon-package text-warning font-medium-5"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="text-bold-700 mt-1">
|
||||
{{ orders }}
|
||||
</h2>
|
||||
<p class="mb-0">Заказы</p>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Количество заказов</h4>
|
||||
|
||||
<div class="btn-group dropdown mr-1 mb-1">
|
||||
<button type="button" class="btn btn-outline-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Primary
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#">Option 1</a>
|
||||
<a class="dropdown-item active" href="#">Option 2</a>
|
||||
<a class="dropdown-item" href="#">Option 3</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#">Separated link</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-body pl-0">
|
||||
<div class="height-300">
|
||||
<canvas id="count-chart" :data-data="{content}"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Стоимость заказа</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-body pl-0" >
|
||||
<div class="height-300" >
|
||||
<canvas id="price-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
users: {},
|
||||
orders: {},
|
||||
revenue: {},
|
||||
orderData: {}
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
content: []
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
Event.$on("document-was-processed", content => {
|
||||
this.content = JSON.parse(this.props.orderData);
|
||||
});
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
},
|
||||
|
||||
filters: {
|
||||
getRevenue(revenue) {
|
||||
let sum = revenue / 1000;
|
||||
|
||||
if (sum < 1000) {
|
||||
return sum + 'k'
|
||||
} else if (sum <= 10000) {
|
||||
return sum / 1000 + 'M'
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
40
resources/js/components/News/News.vue
Executable file
40
resources/js/components/News/News.vue
Executable file
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="news">
|
||||
<a :href="'/blog/news/' + postData.id + '-' + postData.slug" class="news-img">
|
||||
<img :src="'/' + postData.image" :alt="postData.name" />
|
||||
</a>
|
||||
<div class="news-content">
|
||||
<div class="news-date">
|
||||
{{ postData.date }}
|
||||
</div>
|
||||
<h3 class="news-title">
|
||||
<a :href="'/blog/news/' + postData.id + '-' + postData.slug">
|
||||
{{ postData.name }}
|
||||
</a>
|
||||
</h3>
|
||||
<p class="news-subtitle" v-html="postData.content.replace(/<\/?[^>]+>/ig, '')">
|
||||
|
||||
</p>
|
||||
|
||||
<a :href="'/blog/news/' + postData.id + '-' + postData.slug" class="news-link">
|
||||
{{ $t('vue.news.news_read_more') }}
|
||||
<i class="fal fa-chevron-right ml-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['postData'],
|
||||
|
||||
methods: {
|
||||
htmlStrip() {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
60
resources/js/components/News/NewsSection.vue
Executable file
60
resources/js/components/News/NewsSection.vue
Executable file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="section-news">
|
||||
<div class="container">
|
||||
<h2 class="section-title"><a title="Open another news" href="/blog/news">{{ $t('vue.news.news_title') }}</a></h2>
|
||||
<!-- News on desktop -->
|
||||
<div class="row mt-3 outer-row" v-if="!mobile">
|
||||
<div class="col-lg-5" v-if="topPost">
|
||||
<News :post-data="topPost" />
|
||||
</div>
|
||||
|
||||
<div class="col-lg-7 mt-lg-0 mt-3" >
|
||||
<div class="row inner-row">
|
||||
<div class="col-md-4 col-sm-6 mb-md-0 mb-3" v-for="(post, index) in postsData" :key="index">
|
||||
<News :post-data="post" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NewsSlider :posts-data="postsSlider" v-if="mobile" />
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import News from "./News";
|
||||
import NewsSlider from './NewsSlider';
|
||||
import { isMobileOnly } from 'mobile-device-detect';
|
||||
|
||||
export default {
|
||||
props: ['postsData', 'topPost'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
mobile: isMobileOnly ? true : false,
|
||||
postsSlider: this.postsData
|
||||
};
|
||||
},
|
||||
components: {
|
||||
News,
|
||||
NewsSlider
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.setPostData();
|
||||
},
|
||||
|
||||
methods: {
|
||||
setPostData() {
|
||||
this.postsSlider.unshift(this.topPost);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
114
resources/js/components/News/NewsSlider.vue
Executable file
114
resources/js/components/News/NewsSlider.vue
Executable file
@@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<swiper ref="mySwiperNews" class="swiper-container swiper-product swiper-news" :options="swiperOptions">
|
||||
<swiper-slide v-for="post in postsData" v-bind:key="post.id">
|
||||
<News :post-data="post" />
|
||||
</swiper-slide>
|
||||
|
||||
<!-- Add Arrows -->
|
||||
<div class="swiper-button-next swiper-button-next-news" slot="button-next"></div>
|
||||
<div class="swiper-button-prev swiper-button-prev-news" slot="button-prev"></div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-news" slot="pagination"></div>
|
||||
</swiper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
|
||||
import 'swiper/css/swiper.css'
|
||||
import News from "./News";
|
||||
|
||||
export default {
|
||||
props: ['postsData'],
|
||||
|
||||
components: {
|
||||
Swiper,
|
||||
SwiperSlide,
|
||||
News
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
swiperOptions: {
|
||||
spaceBetween: 20,
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next-news",
|
||||
prevEl: ".swiper-button-prev-news",
|
||||
},
|
||||
pagination: {
|
||||
el: ".swiper-pagination-news",
|
||||
dynamicBullets: true,
|
||||
},
|
||||
breakpoints: {
|
||||
1200: {
|
||||
slidesPerView: 5,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 4,
|
||||
},
|
||||
768: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
576: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
0: {
|
||||
slidesPerView: 1.3,
|
||||
},
|
||||
},
|
||||
autoplay: {
|
||||
delay: 3500,
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
swiper() {
|
||||
return this.$refs.mySwiperNews.$swiper;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$breakpoints: (
|
||||
"phone-smallest": 251px,
|
||||
"phone-small": 321px,
|
||||
"phone": 400px,
|
||||
"phone-wide": 480px,
|
||||
"phablet": 560px,
|
||||
"tablet-small": 640px,
|
||||
"tablet": 768px,
|
||||
"tablet-wide": 1024px,
|
||||
"desktop": 1248px,
|
||||
"desktop-wide": 1440px,
|
||||
"desktop-large": 2500px,
|
||||
);
|
||||
|
||||
@mixin mq($width, $type: min) {
|
||||
@if map_has_key($breakpoints, $width) {
|
||||
$width: map_get($breakpoints, $width);
|
||||
|
||||
@if $type==max {
|
||||
$width: $width - 1px;
|
||||
}
|
||||
|
||||
@media only screen and (#{$type}-width: $width) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-product {
|
||||
padding: 75px 0 20px;
|
||||
margin-top: -50px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
|
||||
@include mq("tablet", max) {
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
735
resources/js/components/Order/Update.vue
Executable file
735
resources/js/components/Order/Update.vue
Executable file
@@ -0,0 +1,735 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-12">
|
||||
<form class="form form-vertical" @submit.prevent="UpdateProduct">
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Редактировать Заказ №{{ order.id }}</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="form-body">
|
||||
<p>Все поля обозначенные * обязательные</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="col-12">
|
||||
<h3>
|
||||
Товары
|
||||
</h3>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
|
||||
<thead>
|
||||
<th>
|
||||
Фото
|
||||
</th>
|
||||
<th width="300">
|
||||
Названия
|
||||
</th>
|
||||
<th>
|
||||
Цена
|
||||
</th>
|
||||
|
||||
<th>
|
||||
Скидка
|
||||
</th>
|
||||
|
||||
<th>
|
||||
Размер
|
||||
</th>
|
||||
|
||||
<th>
|
||||
Кол-во
|
||||
</th>
|
||||
|
||||
|
||||
<th>
|
||||
Действия
|
||||
</th>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr v-for="(product, index) in orders.products">
|
||||
<td>
|
||||
<img :src="'/' + product.product.poster_thumb" width="100" >
|
||||
</td>
|
||||
<td width="300">
|
||||
{{ product.product.name.ru }}
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="product.product.price_discount">
|
||||
<strike>
|
||||
{{ product.product.price }} сум
|
||||
</strike>
|
||||
<br>
|
||||
|
||||
<span v-if="product.discount">
|
||||
{{ product.product.price_discount }}
|
||||
</span>
|
||||
|
||||
сум
|
||||
|
||||
</span>
|
||||
|
||||
<span v-else>
|
||||
{{ product.product.price }} сум
|
||||
</span>
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span v-if="product.discount">
|
||||
{{ product.discount }}
|
||||
</span>
|
||||
|
||||
<span v-else>
|
||||
{{ product.product.discount }}
|
||||
</span>
|
||||
%
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ product.size }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ product.count }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<button type="button" @click="Edit(index)" class="btn btn-primary btn-sm btn-icon">
|
||||
<i class="fa fa-edit"></i>
|
||||
</button>
|
||||
|
||||
<button type="button" @click="Delete(index)" class="btn btn-danger btn-sm btn-icon">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" @click="addProduct" class="btn btn-info btn-icon">
|
||||
<i class="fa fa-plus"></i> Добавить товар
|
||||
</button>
|
||||
|
||||
<div class="col-12 mt-1" v-if="actions.store">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h3>
|
||||
Добавить продукт
|
||||
</h3>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<multiselect v-model="actions.product"
|
||||
placeholder="Искать"
|
||||
label="name"
|
||||
track-by="name"
|
||||
:options="actions.products"
|
||||
:option-height="104"
|
||||
:custom-label="customLabel"
|
||||
:show-labels="false"
|
||||
@search-change="SearchProduct"
|
||||
>
|
||||
<template slot="singleLabel" slot-scope="props">
|
||||
<img class="option__image" :src="props.option.poster" width="50" alt="No Man’s Sky">
|
||||
<span class="option__desc">
|
||||
<span class="option__title">{{ props.option.name }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template slot="option" slot-scope="props">
|
||||
<img class="option__image" :src="props.option.poster" width="50" alt="No Man’s Sky">
|
||||
<div class="option__desc">
|
||||
<span class="option__title">{{ props.option.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</multiselect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12" v-if="store.product">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="count">Кол-во</label>
|
||||
<input type="number" id="count" class="form-control" v-model.number="store.count" placeholder="Кол-во">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-12">
|
||||
<button type="button" @click="SaveProductStore" class="btn btn-success btn-icon">
|
||||
<i class="fa fa-save"></i> Добавить
|
||||
</button>
|
||||
|
||||
<button type="button" @click="CancelProduct('store')" class="btn btn-default btn-icon">
|
||||
Отменить
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-1" v-if="actions.edit">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h3>
|
||||
Редактировать продукт
|
||||
</h3>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="count">Кол-во</label>
|
||||
<input type="number" id="count" class="form-control" v-model="product.data.count" placeholder="Адрес">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="col-12">
|
||||
<button type="button" @click="SaveProduct" class="btn btn-success btn-icon">
|
||||
<i class="fa fa-save"></i> Сохранить
|
||||
</button>
|
||||
|
||||
<button type="button" @click="CancelProduct('edit')" class="btn btn-default btn-icon">
|
||||
Отменить
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Цены</h4>
|
||||
<button type="button" class="btn btn-info" @click="TotalDiscount()"><i class="fa fa-refresh"></i> Пересчитать</button>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="price">Продукты</label>
|
||||
<input type="number" disabled id="price" class="form-control" v-model="product_total" placeholder="Цена Продуты">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12" v-if="orders.type_delivery == 1">
|
||||
<div class="form-group">
|
||||
<label for="delivery_price">Цена за доставку</label>
|
||||
<input type="number" id="delivery_price" class="form-control" v-model="orders.price_delivery" placeholder="Цена за доставку">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="discount">Скидка %</label>
|
||||
<input type="number" id="discount" class="form-control" v-model="orders.discount" placeholder="Скидка">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="total">Итого</label>
|
||||
<input type="number" disabled v-model="total" id="total" class="form-control" >
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" v-if="actions.error">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" :key="index">
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="col-12 mb-0">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<button type="submit" class="btn btn-primary mr-1 mb-1 waves-effect waves-light btn-icon">
|
||||
<i class="feather icon-save"></i> {{ $t('admin.save') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-9">
|
||||
<a href="/dashboard/orders" class="btn btn-danger mr-1 mb-1 waves-effect waves-light btn-icon pull-right">
|
||||
<i class="feather icon-x-circle"></i> {{ $t('admin.cancel') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
order: {},
|
||||
branches: {},
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
orders: this.order,
|
||||
|
||||
product: {
|
||||
index: null,
|
||||
data: {}
|
||||
},
|
||||
|
||||
store: {
|
||||
count: 1,
|
||||
color: null,
|
||||
color_id: null,
|
||||
product: null,
|
||||
discount: null,
|
||||
order_id: this.order.id,
|
||||
product_id: null,
|
||||
size: "",
|
||||
},
|
||||
|
||||
actions: {
|
||||
error: false,
|
||||
edit: false,
|
||||
store: false,
|
||||
product: null,
|
||||
products: []
|
||||
},
|
||||
|
||||
product_total: 0,
|
||||
total: 0,
|
||||
|
||||
colors: [],
|
||||
sizes: [],
|
||||
errors: [],
|
||||
|
||||
deletes: {
|
||||
products: []
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.TotalDiscount();
|
||||
},
|
||||
|
||||
watch: {
|
||||
'orders.price_total': function(newVal, oldVal) {
|
||||
this.total = parseInt(this.orders.price_total) + parseInt(this.orders.price_delivery);
|
||||
},
|
||||
|
||||
'orders.discount': function (newVal, oldVal) {
|
||||
if (newVal === "" || newVal === 0) {
|
||||
this.orders.discount = null;
|
||||
} else {
|
||||
if (this.orders.discount > 0) {
|
||||
this.orders.discount = newVal;
|
||||
}
|
||||
}
|
||||
this.TotalDiscount();
|
||||
},
|
||||
|
||||
'orders.price_delivery': function (newVal, oldVal) {
|
||||
if (newVal === "" || newVal === 0) {
|
||||
this.orders.price_delivery = null;
|
||||
} else {
|
||||
if (this.orders.price_delivery > 0) {
|
||||
this.orders.price_delivery = newVal;
|
||||
}
|
||||
}
|
||||
this.TotalDiscount();
|
||||
},
|
||||
|
||||
'product.data.discount' : function (newVal, oldVal) {
|
||||
if (newVal === "" || newVal === 0) {
|
||||
this.product.data.discount = null;
|
||||
this.product.data.product.price_discount = null;
|
||||
} else {
|
||||
if (oldVal) {
|
||||
if (this.product.data.discount > 0) {
|
||||
this.product.data.product.price_discount = Math.round(this.product.data.product.price - parseInt(this.product.data.product.price) * parseFloat(this.product.data.discount) / 100);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
'store.discount': function (newVal, oldVal) {
|
||||
if (newVal === "" || newVal === 0) {
|
||||
this.store.discount = null;
|
||||
this.store.product.price_discount = null;
|
||||
} else {
|
||||
if (this.store.discount > 0) {
|
||||
this.store.product.price_discount = this.store.product.price - parseInt(this.store.product.price) * parseFloat(this.store.discount) / 100;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'actions.product': function () {
|
||||
this.getProductInfo();
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
MathRound(number, precision) {
|
||||
"use strict";
|
||||
|
||||
var nativeRound = Math.round,
|
||||
castNumber = +number,
|
||||
castPrecision = +precision,
|
||||
scaledNumber, eSplit, eString;
|
||||
|
||||
// If the exp is undefined or zero, just use native rounding
|
||||
if( typeof precision === "undefined" || 0 === castPrecision ) {
|
||||
return nativeRound( number );
|
||||
}
|
||||
|
||||
// If the value is not a number or the exp is not an integer...
|
||||
if( isNaN( castNumber ) || !(typeof castPrecision === "number" && 0 === castPrecision % 1) ) {
|
||||
return NaN;
|
||||
}
|
||||
|
||||
// In case the number is already in scientific when casted to string, split off the exponent
|
||||
eSplit = ("" + castNumber).split( "e" );
|
||||
|
||||
// Increase the exponent by the given precision and create a scientific notion string
|
||||
eString = (eSplit[0] + "e" + (eSplit[1] ? (+eSplit[1] + castPrecision) : castPrecision));
|
||||
|
||||
// Cast to number and round
|
||||
scaledNumber = nativeRound( +eString );
|
||||
|
||||
// Do the same as before, backwards
|
||||
eSplit = ("" + scaledNumber).split( "e" );
|
||||
eString = (eSplit[0] + "e" + (eSplit[1] ? (+eSplit[1] - castPrecision) : -castPrecision));
|
||||
|
||||
return +eString;
|
||||
},
|
||||
|
||||
UpdateProduct() {
|
||||
const data = {
|
||||
products: this.orders.products,
|
||||
product_total: this.product_total,
|
||||
total: this.total
|
||||
};
|
||||
|
||||
axios.post('/dashboard/orders/update/' + this.order.id, data).then((response) => {
|
||||
if (response.data.status) {
|
||||
window.location.href = "/dashboard/orders/view/"+ this.order.id;
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.actions.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
Edit(index) {
|
||||
this.actions.edit = true;
|
||||
this.product.index = index;
|
||||
|
||||
this.product.data = {...this.order.products[index]};
|
||||
|
||||
axios.get('/dashboard/orders/products/' + this.product.data.product_id).then((response) => {
|
||||
if (response.data.status) {
|
||||
this.colors = response.data.product.childrens;
|
||||
|
||||
for (let i = 0; i < this.colors.length; i++) {
|
||||
if (this.colors[i].id === this.product.data.color_id) {
|
||||
if (this.colors[i].sizes) {
|
||||
this.sizes = this.colors[i].sizes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
SaveProduct() {
|
||||
this.actions.edit = false;
|
||||
|
||||
this.orders.products[this.product.index] = this.product.data;
|
||||
|
||||
this.product.index = null;
|
||||
|
||||
this.sizes = [];
|
||||
this.colors = [];
|
||||
this.product.data = {};
|
||||
|
||||
setTimeout(this.TotalDiscount(), 1000);
|
||||
},
|
||||
|
||||
CancelProduct(type) {
|
||||
if (type === 'edit') {
|
||||
this.actions.edit = false;
|
||||
|
||||
this.product.index = null;
|
||||
|
||||
this.product.data = {};
|
||||
} else {
|
||||
this.actions.store = false;
|
||||
|
||||
this.store = {
|
||||
count: null,
|
||||
color: null,
|
||||
color_id: null,
|
||||
product: null,
|
||||
discount: null,
|
||||
order_id: this.order.id,
|
||||
product_id: null,
|
||||
size: "",
|
||||
};
|
||||
|
||||
this.actions.products = [];
|
||||
this.actions.product = null;
|
||||
}
|
||||
|
||||
|
||||
this.sizes = [];
|
||||
this.colors = [];
|
||||
|
||||
this.TotalDiscount();
|
||||
},
|
||||
|
||||
SaveProductStore() {
|
||||
this.actions.store = false;
|
||||
|
||||
this.orders.products.push({...this.store});
|
||||
|
||||
this.store = {
|
||||
count: 1,
|
||||
color: null,
|
||||
color_id: null,
|
||||
product: null,
|
||||
discount: null,
|
||||
order_id: this.order.id,
|
||||
product_id: null,
|
||||
size: "",
|
||||
};
|
||||
|
||||
this.sizes = [];
|
||||
this.colors = [];
|
||||
|
||||
this.actions.products = [];
|
||||
this.actions.product = null;
|
||||
|
||||
this.TotalDiscount();
|
||||
},
|
||||
|
||||
ChangeColor(event) {
|
||||
let value;
|
||||
|
||||
if (event.target.value) {
|
||||
value = event.target.value;
|
||||
} else {
|
||||
value = event;
|
||||
}
|
||||
|
||||
const val = parseInt(value);
|
||||
|
||||
this.colors.forEach((color, index) => {
|
||||
if (color.id === val) {
|
||||
if (color.sizes.length > 0) {
|
||||
this.product.data.color_id = color.id;
|
||||
this.product.data.color = color;
|
||||
this.sizes = color.sizes;
|
||||
} else {
|
||||
this.sizes = [];
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ChangeColorStore(event) {
|
||||
let value;
|
||||
|
||||
if (event.target.value) {
|
||||
value = event.target.value;
|
||||
} else {
|
||||
value = event;
|
||||
}
|
||||
|
||||
const val = parseInt(value);
|
||||
|
||||
this.colors.forEach((color, index) => {
|
||||
if (color.id === val) {
|
||||
if (color.sizes.length > 0) {
|
||||
this.store.color_id = color.id;
|
||||
this.store.color = color;
|
||||
this.sizes = color.sizes;
|
||||
} else {
|
||||
this.sizes = [];
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
TotalDiscount() {
|
||||
let price = [];
|
||||
let price_discount = [];
|
||||
|
||||
if (this.orders.address_id == null) {
|
||||
this.orders.address = {
|
||||
first_name: '',
|
||||
phone: ''
|
||||
}
|
||||
}
|
||||
|
||||
this.orders.products.forEach(function (product, index) {
|
||||
if (product.discount === null && product.product.discountPrice === 0) { //|| product.product.price_discount === null
|
||||
console.log(1);
|
||||
price.push(parseInt(product.product.price) * product.count);
|
||||
} else {
|
||||
console.log(2);
|
||||
//console.log(product.product.price_discount)
|
||||
price_discount.push(parseInt(product.product.price_discount) * product.count);
|
||||
}
|
||||
});
|
||||
|
||||
//console.log(3);
|
||||
//console.log(price_discount);
|
||||
let total_price = price.reduce(function(total, num){ return total + num }, 0);
|
||||
// console.log('price ' + total_price);
|
||||
let total_discount = price_discount.reduce(function(total, num){ return total + num }, 0);
|
||||
// console.log('dis ' + total_discount);
|
||||
|
||||
|
||||
this.product_total = parseInt(total_price) + parseInt(total_discount);
|
||||
let discount = this.orders.discount == null ? 0 : this.orders.discount;
|
||||
|
||||
total_price = parseInt(total_price) - parseInt(total_price) * parseInt(discount) / 100;
|
||||
|
||||
let delivery;
|
||||
|
||||
if (this.orders.type_delivery == 1) {
|
||||
delivery = this.orders.price_delivery == null ? 0 : this.orders.price_delivery;
|
||||
} else {
|
||||
this.orders.price_delivery = 0;
|
||||
delivery = 0;
|
||||
}
|
||||
|
||||
this.total = parseInt(total_price) + parseInt(total_discount) + parseInt(delivery);
|
||||
|
||||
},
|
||||
|
||||
addProduct() {
|
||||
this.actions.store = true;
|
||||
},
|
||||
|
||||
Delete(index) {
|
||||
//console.log(index);
|
||||
|
||||
this.deletes.products.push(this.orders.products[index].product_id);
|
||||
this.orders.products.splice(index, 1);
|
||||
|
||||
this.TotalDiscount();
|
||||
},
|
||||
|
||||
async getProductInfo() {
|
||||
if (this.actions.product) {
|
||||
const { data } = await axios.post('/dashboard/orders/product/info/' + this.actions.product.id);
|
||||
|
||||
if (data.product.price_discount) {
|
||||
this.store.discount = 100 - parseInt(data.product.price_discount) * 100 / parseInt(data.product.price);
|
||||
} else {
|
||||
this.store.discount = null;
|
||||
}
|
||||
|
||||
this.store.product = data.product;
|
||||
this.store.product_id = data.product.id;
|
||||
|
||||
axios.get('/dashboard/orders/products/' + data.product.id).then((response) => {
|
||||
if (response.data.status) {
|
||||
this.colors = response.data.product.childrens;
|
||||
this.store.color_id = response.data.product.childrens[0].id
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.store.product = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async SearchProduct(query) {
|
||||
let name = query;
|
||||
|
||||
if (name.length > 0) {
|
||||
axios.post('/dashboard/orders/product/search', { name: name})
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
this.actions.products = response.data.products;
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.actions.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//console.log(query);
|
||||
},
|
||||
|
||||
customLabel ({ name }) {
|
||||
return `${name}`
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
121
resources/js/components/Partners/PartnerSlider.vue
Executable file
121
resources/js/components/Partners/PartnerSlider.vue
Executable file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<swiper
|
||||
ref="mySwiperBrand"
|
||||
class="swiper-container swiper-product"
|
||||
:options="swiperOptions"
|
||||
>
|
||||
<swiper-slide v-for="(partner, index) in partnersData" :key="index">
|
||||
<div class="partner">
|
||||
<div class="partner-logo">
|
||||
<a :href="'/brand/' + partner.slug">
|
||||
<img :src="'/' + partner.image" :alt="partner.name" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
|
||||
|
||||
<!-- Add Arrows -->
|
||||
<div class="swiper-button-next swiper-button-next-product" slot="button-next"></div>
|
||||
<div class="swiper-button-prev swiper-button-prev-product" slot="button-prev"></div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-product" slot="pagination"></div>
|
||||
</swiper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
|
||||
// import "swiper/swiper-bundle.css";
|
||||
import 'swiper/css/swiper.css'
|
||||
|
||||
export default {
|
||||
props: ['partnersData'],
|
||||
|
||||
components: {
|
||||
Swiper,
|
||||
SwiperSlide,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
swiperOptions: {
|
||||
spaceBetween: 20,
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next-product",
|
||||
prevEl: ".swiper-button-prev-product",
|
||||
},
|
||||
pagination: {
|
||||
el: ".swiper-pagination-product",
|
||||
dynamicBullets: true,
|
||||
},
|
||||
breakpoints: {
|
||||
1200: {
|
||||
slidesPerView: 6,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 4,
|
||||
},
|
||||
576: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
0: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
},
|
||||
autoplay: {
|
||||
delay: 5500,
|
||||
},
|
||||
},
|
||||
products: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
swiper() {
|
||||
return this.$refs.mySwiperBrand.$swiper;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$breakpoints: (
|
||||
"phone-smallest": 251px,
|
||||
"phone-small": 321px,
|
||||
"phone": 400px,
|
||||
"phone-wide": 480px,
|
||||
"phablet": 560px,
|
||||
"tablet-small": 640px,
|
||||
"tablet": 768px,
|
||||
"tablet-wide": 1024px,
|
||||
"desktop": 1248px,
|
||||
"desktop-wide": 1440px,
|
||||
"desktop-large": 2500px,
|
||||
);
|
||||
|
||||
@mixin mq($width, $type: min) {
|
||||
@if map_has_key($breakpoints, $width) {
|
||||
$width: map_get($breakpoints, $width);
|
||||
|
||||
@if $type==max {
|
||||
$width: $width - 1px;
|
||||
}
|
||||
|
||||
@media only screen and (#{$type}-width: $width) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-product {
|
||||
padding: 75px 0 20px;
|
||||
margin-top: -50px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
|
||||
@include mq("tablet", max) {
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
1489
resources/js/components/ProductEdit.vue
Executable file
1489
resources/js/components/ProductEdit.vue
Executable file
File diff suppressed because it is too large
Load Diff
191
resources/js/components/ProductPreviewImport.vue
Executable file
191
resources/js/components/ProductPreviewImport.vue
Executable file
@@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<div class="row" id="table-head">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-content ">
|
||||
<div class="table-responsive table-responsive-xl" >
|
||||
<table class="table mb-0">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th scope="col">{{ $t('admin.products.name') }} RU</th>
|
||||
<th scope="col">{{ $t('admin.products.name') }} Uz</th>
|
||||
<th scope="col" width="150">Артикул</th>
|
||||
<th scope="col" width="170">{{ $t('admin.products.price') }}</th>
|
||||
<th scope="col">{{ $t('admin.products.brand') }}</th>
|
||||
<th scope="col">Лидеры продаж</th>
|
||||
<th scope="col">Популярные товары</th>
|
||||
<th scope="col">Х-рка</th>
|
||||
<th scope="col">{{ $t('admin.actions') }}</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-if="products.length == 0">
|
||||
<td class="text-center" colspan="9">
|
||||
{{ $t('admin.no_data') }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr v-for="(product, index) in products" :key="index">
|
||||
<td>
|
||||
{{ product.name.ru }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ product.name.uz }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ product.article_number }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span v-if="product.price_discount">
|
||||
<strike>{{ product.price }}</strike>
|
||||
{{ $t('admin.ye') }}
|
||||
<br>
|
||||
{{ product.price_discount }}
|
||||
{{ $t('admin.ye') }}
|
||||
</span>
|
||||
|
||||
<span v-else>
|
||||
{{ product.price }} {{ $t('admin.ye') }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ product.brand }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ product.leader_of_sales }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ product.popular }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<button type="button" @click="charView(product)" class="btn btn-primary btn-icon" data-toggle="modal" data-target="#large">
|
||||
<i class="fa fa-eye"></i>
|
||||
</button>
|
||||
</td>
|
||||
|
||||
<td class="text-right">
|
||||
<a href="#" @click="removeProduct(product, index)" class="btn btn-danger btn-icon">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-success" @click="sendProducts">
|
||||
<i class="fa fa-save"></i> Сохранить
|
||||
</button>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal fade text-left" id="large" tabindex="-1" role="dialog" aria-labelledby="myModalLabel17" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="myModalLabel17">Характеристики</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="col-md-12" v-for="(char, index) in characteristics" :key="index">
|
||||
<div class="row">
|
||||
<div class="col-xl-4 col-md-6 col-12 mb-1">
|
||||
<fieldset class="form-group">
|
||||
<input type="text" disabled v-model="char.name.ru" class="form-control">
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-4 col-md-6 col-12 mb-1">
|
||||
<fieldset class="form-group" v-if="char.type != 'checkbox'">
|
||||
<input :type="char.type" min="0" v-model="char_data[index]" class="form-control">
|
||||
</fieldset>
|
||||
|
||||
<fieldset v-else>
|
||||
<div class="vs-checkbox-con vs-checkbox-primary">
|
||||
<input type="checkbox" v-model="char_data[index]" >
|
||||
<span class="vs-checkbox">
|
||||
<span class="vs-checkbox--check">
|
||||
<i class="vs-icon feather icon-check"></i>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" @click="saveChar" data-dismiss="modal">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
productsData: {},
|
||||
characteristicsData: {},
|
||||
categoryData: {}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
products: this.productsData,
|
||||
characteristics: this.characteristicsData.characteristics,
|
||||
|
||||
category_id: this.categoryData,
|
||||
char_data: []
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
removeProduct(product, index) {
|
||||
this.products.splice(index, 1)
|
||||
},
|
||||
|
||||
charView(product) {
|
||||
this.char_data = product.characteristics;
|
||||
},
|
||||
|
||||
saveChar() {
|
||||
this.char_data = [];
|
||||
},
|
||||
|
||||
async sendProducts() {
|
||||
const fields = {
|
||||
data: this.products,
|
||||
category_id: this.category_id
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/dashboard/products/preview/store', fields);
|
||||
|
||||
if (data.status) {
|
||||
window.location = '/dashboard/products'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
1465
resources/js/components/ProductStore.vue
Executable file
1465
resources/js/components/ProductStore.vue
Executable file
File diff suppressed because it is too large
Load Diff
131
resources/js/components/Products/BuyOneClick.vue
Executable file
131
resources/js/components/Products/BuyOneClick.vue
Executable file
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="modal fade buy-by-one-click" ref="buy_one_click" id="buy-by-one-click">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<button class="close" data-dismiss="modal">
|
||||
<i class="fal fa-times"></i>
|
||||
</button>
|
||||
|
||||
<h4>{{ $t('vue.buy_one.title') }}</h4>
|
||||
|
||||
<div class="alert alert-danger" v-if="error">
|
||||
<ul>
|
||||
<li v-for="(error, index) in errors" :key="index">
|
||||
<span v-for="msg in error" :key="msg">
|
||||
{{ msg }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="text" placeholder="" v-model="first_name" id="your_name2" required />
|
||||
<label for="your_name2">{{ $t('vue.buy_one.first_name') }}</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" :placeholder="$t('vue.buy_one.phone_place')" v-model="phone" v-mask="'+### ## ###-##-##'" id="phoneee" required />
|
||||
<label for="phoneee">{{ $t('vue.buy_one.phone') }}</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="email" placeholder="" v-model="email" id="your_name" />
|
||||
<label for="your_name">{{ $t('vue.buy_one.email') }}</label>
|
||||
</div>
|
||||
<div class="mt-4 my-form__group">
|
||||
<textarea name="" id="your_message2" v-model="comment" cols="30" rows="5"></textarea>
|
||||
<label for="your_message2">{{ $t('vue.buy_one.comment') }}</label>
|
||||
</div>
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange">
|
||||
{{ $t('vue.buy_one.send') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade success" ref="alertNotification">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body text-center">
|
||||
<img src="/vendor/site/img/tick.png" alt="Tick icon">
|
||||
<div class="my-3">
|
||||
<h4 class="text-center">
|
||||
{{ $t('vue.buy_one.thx') }}
|
||||
</h4>
|
||||
<h5 class="text-center px-lg-5">
|
||||
{{ $t('vue.buy_one.thx_text') }}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button type="button" data-dismiss="modal" class="my-btn my-btn__orange">{{ $t('vue.noti.ok') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
phoneProfile: {},
|
||||
productId: {},
|
||||
firstName: {}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
phone: this.phoneProfile,
|
||||
first_name: this.firstName,
|
||||
email: null,
|
||||
comment: null,
|
||||
product_id: this.productId,
|
||||
|
||||
error: false,
|
||||
errors: []
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
SendForm() {
|
||||
const field = {
|
||||
phone: this.phone,
|
||||
first_name: this.first_name,
|
||||
email: this.email,
|
||||
comment: this.comment,
|
||||
product_id: this.product_id
|
||||
};
|
||||
|
||||
axios.post('/product/buy/click', field).then((response) => {
|
||||
if (response.data.status) {
|
||||
$(this.$refs.buy_one_click).modal('hide');
|
||||
$(this.$refs.alertNotification).modal('show');
|
||||
|
||||
this.phone = this.phoneProfile;
|
||||
this.first_name = null;
|
||||
this.email = null;
|
||||
this.comment = null
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>w
|
||||
235
resources/js/components/Products/Credit.vue
Executable file
235
resources/js/components/Products/Credit.vue
Executable file
@@ -0,0 +1,235 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="modal fade installment" id="installment" style="display: none;" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<!-- -->
|
||||
<button class="close" data-dismiss="modal"><i class="fal fa-times"></i></button>
|
||||
|
||||
<div>
|
||||
<h4 class="text-center">{{ $t('app.credit.title') }}</h4>
|
||||
|
||||
<ul class="nav nav-pills justify-content-center">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="pill" href="#by_alifmoliya">Alif Moliya</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#by_apelsin">Apelsin</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane container p-0 active" id="by_alifmoliya">
|
||||
<form class="my-form my-form__auth">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="my-form__group">
|
||||
<input class="payment-price" readonly
|
||||
:value="firstPay | number('0,0', { thousandsSeparator: ' ' })" type="number" id="initial-payment"
|
||||
required="">
|
||||
<label for="initial-payment">{{ $t('app.credit.alif.first_pay') }}</label>
|
||||
</div>
|
||||
<div class="small mt-1"><i class="fal fa-info-circle"></i> {{ $t('app.credit.alif.min_pay') }} {{ product.first_pay }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mt-md-0 mt-4 my-form__group">
|
||||
<label>{{ $t('app.credit.alif.months') }}</label>
|
||||
<div
|
||||
class="d-flex justify-content-center align-items-center select-months">
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input months"
|
||||
id="month6" v-model="months" @change="handleMonth"
|
||||
:value="6">
|
||||
<label class="custom-control-label" for="month6">6
|
||||
{{ $t('app.credit.month') }}</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input months"
|
||||
id="month9" v-model="months" @change="handleMonth"
|
||||
:value="9">
|
||||
<label class="custom-control-label" for="month9">9
|
||||
{{ $t('app.credit.month') }}.</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input months"
|
||||
id="month12" v-model="months" @change="handleMonth"
|
||||
:value="12">
|
||||
<label class="custom-control-label" for="month12">12
|
||||
{{ $t('app.credit.month') }}</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input months"
|
||||
id="month3" v-model="months" @change="handleMonth"
|
||||
:value="15">
|
||||
<label class="custom-control-label" for="month3">15
|
||||
{{ $t('app.credit.month') }}.</label>
|
||||
</div>
|
||||
<!-- <div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input" id="month15" name="months"
|
||||
value="customEx">
|
||||
<label class="custom-control-label" for="month15">15 мес.</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" class="custom-control-input" id="month18" name="months"
|
||||
value="customEx">
|
||||
<label class="custom-control-label" for="month18">18 мес.</label>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="text" disabled="" :value="perMonth | number('0,0', { thousandsSeparator: ' ' })"
|
||||
id="for_month" class="payment-price">
|
||||
<label for="for_month">{{ $t('app.credit.alif.per_month') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="text" disabled=""
|
||||
:value="price | number('0,0', { thousandsSeparator: ' ' })"
|
||||
class="payment-price" id="all_price">
|
||||
<label for="all_price">{{ $t('app.credit.alif.price') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6" v-if="phoneVerify">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel"
|
||||
v-model="phone"
|
||||
v-mask="'+998 (##) ###-##-##'"
|
||||
class="payment-price" id="phone">
|
||||
<label for="phone">{{ $t('app.credit.alif.phone') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6" v-if="phoneVerify">
|
||||
<div class="mt-4 my-form__group" v-if="showVerify">
|
||||
<input type="text"
|
||||
v-mask="'####'"
|
||||
v-model="verify"
|
||||
class="payment-price" id="verify">
|
||||
<label for="verify">{{ $t('app.credit.alif.verify_code') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mx-auto mt-3">
|
||||
<div
|
||||
class="mt-4 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button v-if="!phoneVerify" @click="showPhoneVerify" type="button" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('app.credit.btn') }}
|
||||
</button>
|
||||
<button v-if="phoneVerify && !showVerify" @click="sendPhone" type="button" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('app.credit.btn') }}
|
||||
</button>
|
||||
<button v-if="showVerify" @click="submit" type="button" class="my-btn my-btn__orange w-100">
|
||||
{{ $t('app.credit.btn') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane container p-0 fade" id="by_apelsin">
|
||||
<div class="mt-3">
|
||||
<p>{{ $t('app.credit.apelsin_text') }}</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mx-auto mt-3">
|
||||
<a :href="`/product/oncredit/${product.id}`">
|
||||
<button class="my-btn my-btn__orange w-100">{{ $t('app.credit.btn') }}</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Credit",
|
||||
props: {
|
||||
productData: {}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
product: this.productData,
|
||||
firstPay: 0,
|
||||
perMonth: this.productData.per_month,
|
||||
price: Math.round(this.productData.price + (this.productData.price / 100) * 25),
|
||||
months: 6,
|
||||
phoneVerify: false,
|
||||
showVerify: false,
|
||||
phone: null,
|
||||
verify: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleFirstPay(event) {
|
||||
if ((parseInt(event.target.value) < parseInt(this.product.first_pay)) || (parseInt(event.target.value) > parseInt(this.price)) || !event.target.value) {
|
||||
this.firstPay = this.product.first_pay
|
||||
} else {
|
||||
this.perMonth = Math.round((this.price - this.firstPay) / this.months)
|
||||
}
|
||||
},
|
||||
|
||||
handleMonth(event) {
|
||||
switch (this.months) {
|
||||
case 6:
|
||||
this.price = Math.round(this.product.price + (this.product.price / 100) * 25)
|
||||
break
|
||||
case 9:
|
||||
this.price = Math.round(this.product.price + (this.product.price / 100) * 32)
|
||||
break
|
||||
case 12:
|
||||
this.price = Math.round(this.product.price + (this.product.price / 100) * 38)
|
||||
break
|
||||
case 15:
|
||||
this.price = Math.round(this.product.price + (this.product.price / 100) * 50)
|
||||
break
|
||||
}
|
||||
this.months = parseInt(event.target.value)
|
||||
this.perMonth = Math.round((this.price - this.firstPay) / parseInt(event.target.value))
|
||||
|
||||
},
|
||||
|
||||
showPhoneVerify(event) {
|
||||
this.phoneVerify = true
|
||||
},
|
||||
|
||||
sendPhone(event) {
|
||||
axios.post('/product/phone-verify/', {phone: this.phone}).then(response => {
|
||||
this.showVerify = true
|
||||
})
|
||||
},
|
||||
|
||||
submit() {
|
||||
const form = new FormData()
|
||||
|
||||
form.append('phone', this.phone)
|
||||
form.append('code', this.verify)
|
||||
form.append('duration', this.months)
|
||||
axios.post(`/product/oncredit/${this.product.id}`, form).then(response => {
|
||||
$('#installment').modal('hide')
|
||||
$('#success').modal('show')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#initial-payment {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
</style>
|
||||
91
resources/js/components/Products/Notification.vue
Executable file
91
resources/js/components/Products/Notification.vue
Executable file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="modal fade alert-when-has-product" ref="notification_available" id="alert-when-has-product">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<button class="close" data-dismiss="modal">
|
||||
<i class="fal fa-times"></i>
|
||||
</button>
|
||||
|
||||
<h4>{{ $t('vue.noti.title') }}</h4>
|
||||
<p>{{ $t('vue.noti.text') }}</p>
|
||||
|
||||
<form @submit.prevent="SendForm" class="my-form my-form__auth">
|
||||
<div class="mt-4 my-form__group">
|
||||
<input type="tel" v-mask="'+### ## ###-##-##'" v-model="phone" :placeholder="$t('vue.buy_one.phone_place')" id="has_productsss" required />
|
||||
<label for="has_productsss">{{ $t('vue.buy_one.phone') }}</label>
|
||||
</div>
|
||||
<div class="mt-3 d-flex justify-content-md-end justify-content-center align-items-center">
|
||||
<button type="sumbit" class="my-btn my-btn__orange">{{ $t('vue.buy_one.send') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade success" ref="alertNotification">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body text-center">
|
||||
<img src="/vendor/site/img/tick.png" alt="Tick icon">
|
||||
<div class="my-3">
|
||||
<h5 class="text-center px-lg-5">
|
||||
{{ $t('vue.noti.alert') }}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button type="button" data-dismiss="modal" class="my-btn my-btn__orange">{{ $t('vue.noti.ok') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: {
|
||||
productId: {},
|
||||
phoneProfile: {}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
phone: this.phoneProfile,
|
||||
product_id: this.productId
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async SendForm() {
|
||||
const { data } = await axios.post('/product/notification/available', {
|
||||
phone: this.phone,
|
||||
product_id: this.product_id
|
||||
});
|
||||
|
||||
if (data.status) {
|
||||
if (!this.phoneProfile) {
|
||||
this.phone = null;
|
||||
} else {
|
||||
this.phone = '+' + this.phoneProfile;
|
||||
}
|
||||
|
||||
$(this.$refs.notification_available).modal('hide');
|
||||
$(this.$refs.alertNotification).modal('show');
|
||||
}
|
||||
},
|
||||
|
||||
doSomethingOnHidden(){
|
||||
alert('hidden')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
131
resources/js/components/Products/Product.vue
Executable file
131
resources/js/components/Products/Product.vue
Executable file
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div class="product">
|
||||
<div class="product-top">
|
||||
<div class="type" v-if="product.diffDate && product.isAvailable">NEW</div>
|
||||
<div class="discound" v-if="product.discountPrice > 0 && product.price_discount && product.isAvailable">
|
||||
{{ $t('vue.sale') }}
|
||||
</div>
|
||||
<div class="xit" v-if="product.leader_of_sales && product.isAvailable">{{ $t('vue.xit') }}</div>
|
||||
<div class="no-product" v-if="!product.isAvailable">{{ $t('vue.not_available') }}</div>
|
||||
</div>
|
||||
<a :href="'/product/show/' + product.id + '-' + product.slug" class="product-img">
|
||||
<img :src="'/' + product.poster_thumb" :class="!product.isAvailable ? 'no-product-img' : ''" :alt="getName(product.name)" />
|
||||
</a>
|
||||
<div class="product-category">
|
||||
<a v-for="(category, index) in product.categories" :href="category.link">
|
||||
{{ getName(category.name) }}
|
||||
</a>
|
||||
</div>
|
||||
<h3 class="product-title">
|
||||
<a :href="'/product/show/' + product.id + '-' + product.slug">
|
||||
{{ getName(product.name) }}
|
||||
</a>
|
||||
</h3>
|
||||
<div class="product-price">
|
||||
<div class="old-price" v-if="product.price_discount">
|
||||
{{ product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}
|
||||
</div>
|
||||
<div class="new-price">
|
||||
{{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-buttons">
|
||||
<div class="product-to_cart">
|
||||
|
||||
<button v-if="product.isAvailable && !product.isCart" :class="product.isCart ? 'product-to_basket is-active' : 'product-to_basket'" @click="AddToCart(product)">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span>{{ $t('app.product.in_cart') }}</span>
|
||||
<div class="added-to-basket" v-html="$t('vue.favorite.added_to_basket')">
|
||||
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button v-if="product.isAvailable && product.isCart" data-target="#basket_modal" data-toggle="modal" :class="product.isCart ? 'product-to_basket is-active' : 'product-to_basket'" @click="AddToCart(product)">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span>{{ $t('app.product.in_cart') }}</span>
|
||||
|
||||
</button>
|
||||
|
||||
<!-- <button class="product-to_compare">-->
|
||||
<!-- <i class="far fa-balance-scale"></i>-->
|
||||
<!-- </button>-->
|
||||
</div>
|
||||
|
||||
<button class="product-to_favorite" data-target="#login" data-toggle="modal" v-if="!loginInfo">
|
||||
<i class="fas fa-heart"></i>
|
||||
</button>
|
||||
|
||||
<button :class="product.isFavorite ? 'product-to_favorite is-active' : 'product-to_favorite'" @click="Favorite(product)" v-if="loginInfo">
|
||||
<i class="fas fa-heart"></i>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['product', 'loginInfo'],
|
||||
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
async Favorite(product) {
|
||||
var field = document.getElementById("favorite-count");
|
||||
var count = field.value;
|
||||
|
||||
if (product.isFavorite === false) {
|
||||
const { data } = await axios.get('/favorites/store/' + product.id);
|
||||
this.product.isFavorite = true;
|
||||
field.value = parseInt(count) + 1;
|
||||
} else {
|
||||
const { data } = await axios.get('/favorites/delete/' + product.id);
|
||||
this.product.isFavorite = false;
|
||||
field.value = parseInt(count) - 1;
|
||||
}
|
||||
},
|
||||
|
||||
async AddToCart(product) {
|
||||
if (this.product.isCart){
|
||||
this.$eventBus.$emit('cart-preview');
|
||||
return;
|
||||
}
|
||||
const fields = {
|
||||
product_id: product.children.id,
|
||||
count: 1
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/cart/store', fields);
|
||||
|
||||
if (data.status) {
|
||||
product.isCart = true;
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
511
resources/js/components/Products/ProductShow.vue
Executable file
511
resources/js/components/Products/ProductShow.vue
Executable file
@@ -0,0 +1,511 @@
|
||||
<template>
|
||||
<section class="section-product-item">
|
||||
<div class="container">
|
||||
<div class="row" itemtype="http://schema.org/Product" itemscope>
|
||||
<meta itemprop="mpn" :content="product.id" />
|
||||
<meta itemprop="name" :content="getName(product.name)" />
|
||||
<link itemprop="image" :href="product.children.screen.path_thumb" />
|
||||
<meta itemprop="description" :content="getName(product.short_body)" />
|
||||
|
||||
<div itemprop="offers" itemtype="http://schema.org/Offer" itemscope>
|
||||
<link itemprop="url" :href="'https://alistore.uz/product/show/' + product.id + '-' + product.slug " />
|
||||
<meta itemprop="availability" content="https://schema.org/InStock" />
|
||||
<meta itemprop="priceCurrency" content="UZS" />
|
||||
<meta itemprop="itemCondition" content="https://schema.org/UsedCondition" />
|
||||
<meta itemprop="price" :content="product.price_discount ? product.price_discount : product.price" />
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="product-cart">
|
||||
<div class="product-top">
|
||||
<div class="type" v-if="product.diffDate && product.isAvailable">NEW</div>
|
||||
<div class="discound" v-if="product.discountPrice > 0 && product.price_discount && product.isAvailable">
|
||||
{{ $t('vue.sale') }}
|
||||
</div>
|
||||
<div class="xit" v-if="product.leader_of_sales && product.isAvailable">{{ $t('vue.xit') }}</div>
|
||||
<div class="discound"
|
||||
v-if="product.discountPrice > 0 && product.price_discount && product.isAvailable">-{{
|
||||
product.discountPrice }}%
|
||||
</div>
|
||||
<div class="xit" v-if="product.leader_of_sales && product.isAvailable">{{ $t('vue.xit') }}
|
||||
</div>
|
||||
<div class="no-product" v-if="!product.isAvailable">{{ $t('vue.not_available') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="product-buttons">
|
||||
<button class="product-to_favorite" data-target="#login" data-toggle="modal"
|
||||
v-if="!loginInfo">
|
||||
<i class="fas fa-heart"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
:class="product.isFavorite ? 'product-to_favorite is-active' : 'product-to_favorite'"
|
||||
@click="Favorite(product)" v-if="loginInfo">
|
||||
<i class="fas fa-heart"></i>
|
||||
</button>
|
||||
|
||||
<!-- <button class="product-to_compare mt-2">-->
|
||||
<!-- <i class="far fa-balance-scale"></i>-->
|
||||
<!-- </button>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider slider-big" id="aniimated-thumbnial">
|
||||
<div class="slider__content" v-for="(screen, index) in product.childrens[0].screens">
|
||||
<div class="slider__img">
|
||||
<div class="item" :data-src="'/' + screen.path">
|
||||
<img :src="'/' + screen.path_thumb" :alt="getName(product.name)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider slider-small py-3 px-2" id="aniimated-thumbnials">
|
||||
<div class="slider__img" v-for="(screen, index) in product.childrens[0].screens">
|
||||
<div class="item1" :data-src="'/' + screen.path">
|
||||
<img class="" :src="'/' + screen.path_thumb" :alt="getName(product.name)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-8 view_box">
|
||||
<div class="product pt-lg-3 pt-0">
|
||||
<div class="share d-flex align-items-md-center mt-lg-4 mt-2 flex-column flex-md-row mb-3">
|
||||
<p class="mb-md-0 mr-md-3 mt-1">{{ $t('vue.news.news_share') }}:</p>
|
||||
<div class="socials">
|
||||
<ShareNetwork :url="url" network="facebook" :title="getName(product.name)">
|
||||
<i class="fab fa-facebook-f"></i>
|
||||
</ShareNetwork>
|
||||
|
||||
<ShareNetwork :url="url" network="telegram" :title="getName(product.name)">
|
||||
<i class="fab fa-telegram-plane"></i>
|
||||
</ShareNetwork>
|
||||
|
||||
<ShareNetwork :url="url" network="vk" :title="getName(product.name)">
|
||||
<i class="fab fa-vk"></i>
|
||||
</ShareNetwork>
|
||||
|
||||
<ShareNetwork :url="url" network="odnoklassniki" :title="getName(product.name)">
|
||||
<i class="fab fa-odnoklassniki"></i>
|
||||
</ShareNetwork>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 class="product-title">
|
||||
{{ getName(product.name) }}
|
||||
</h1>
|
||||
|
||||
<div class="product-price mb-0">
|
||||
<div class="new-price">
|
||||
{{ product.price_discount ? product.price_discount : product.price | number('0,0', {
|
||||
thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}
|
||||
</div>
|
||||
|
||||
<div class="old-price mt-1" v-if="product.price_discount">
|
||||
{{ product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="product-price align-items-md-center h-100" v-if="settingData.on_credit && product.category.credit && product.price > 500000 && product.price > 500000">
|
||||
<h3 class="product-title mr-2 mt-3 mt-md-0 mb-0">{{ $t('vue.product.in_credit') }}</h3>
|
||||
<div class="new-price">{{ product.onCredit | number('0,0', { thousandsSeparator: ' ' }) }}
|
||||
{{ $t('vue.product.sum_m') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="product-subtitle" v-html="getName(product.short_body)">
|
||||
|
||||
</p>
|
||||
|
||||
<div class="product-color" v-if="colors">
|
||||
<p>{{ $t('vue.cart.product_color_title') }}:</p>
|
||||
<div class="colors">
|
||||
<ul>
|
||||
<li v-for="(color, index) in product.childrens" :key="index">
|
||||
<label v-if="color.color">
|
||||
<input type="radio" name="color" v-model="color_id" value="black"
|
||||
:checked="index === 0">
|
||||
<span class="swatch"
|
||||
:style="{ 'background-color': '#' + color.color.color, 'border-color': '#' + color.color.color }"></span>
|
||||
</label>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-md-center flex-wrap flex-md-row" v-if="product.isAvailable">
|
||||
<div class="product-count">
|
||||
<span class="decrement" @click="CountMinus"><i class="fal fa-minus"></i></span>
|
||||
<input type="text" value="1" v-model="count" min="0" readonly>
|
||||
<span class="increment" @click="CountAdd"><i class="fal fa-plus"></i></span>
|
||||
</div>
|
||||
|
||||
<div class="product-buttons">
|
||||
|
||||
<button v-if="!product.isCart"
|
||||
:class="product.isCart ? 'product-to_basket is-actived is-active' : 'product-to_basket is-actived'"
|
||||
@click="AddToCart">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span class="d-inline-block">{{ $t('vue.cart.product_to_basket_title') }}</span>
|
||||
|
||||
<div class="added-to-basket" v-html="$t('vue.favorite.added_to_basket')">
|
||||
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button v-if="product.isCart"
|
||||
:class="product.isCart ? 'product-to_basket is-actived is-active' : 'product-to_basket is-actived'"
|
||||
@click="AddToCart" data-target="#basket_modal" data-toggle="modal">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span class="d-inline-block">{{ $t('vue.cart.product_to_basket_title') }}</span>
|
||||
</button>
|
||||
|
||||
<div v-if="product.category.credit && product.price > 500000">
|
||||
<a href="javasciprt:" v-if="!loginInfo && settingData.on_credit && product.price > 500000"
|
||||
data-target="#login" data-toggle="modal" @click="CreditCookie"
|
||||
class="btn-links btn-links__one">{{ $t('vue.cart.buy_in_credit') }}</a>
|
||||
<a href="javasciprt:" data-target="#installment" data-toggle="modal"
|
||||
v-if="loginInfo && settingData.on_credit && product.price > 500000" class="btn-links btn-links__one">{{
|
||||
$t('vue.cart.buy_in_credit') }}</a>
|
||||
</div>
|
||||
|
||||
<a href="javascript:0" class="btn-links btn-links__one bg__green"
|
||||
data-target="#buy-by-one-click" data-toggle="modal">{{ $t('vue.cart.buy_in_click')
|
||||
}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="now-no-product" v-if="!product.isAvailable">
|
||||
<p>{{ $t('vue.not_available') }}</p>
|
||||
<button data-target="#alert-when-has-product" data-toggle="modal">{{ $t('vue.notification')
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="payments d-flex align-items-center my-4 flex-wrap">
|
||||
<p class="mr-3 mb-0">{{ $t('vue.cart.payment_title') }}: </p>
|
||||
<div class="d-flex align-items-baseline flex-wrap">
|
||||
<div class="payments-item mr-md-4 m-3 ml-md-0 my-md-0">
|
||||
<img class="img-fluid" src="/vendor/site/img/apelsin.png" alt="Apelsin">
|
||||
</div>
|
||||
|
||||
<div class="payments-item mr-md-4 m-3 ml-md-0 my-md-0">
|
||||
<img class="img-fluid" src="/vendor/site/img/click.png" alt="Click">
|
||||
</div>
|
||||
|
||||
<div class="payments-item mr-md-4 m-3 ml-md-0 my-md-0">
|
||||
<img class="img-fluid" src="/vendor/site/img/payme.png" alt="Payme">
|
||||
</div>
|
||||
<div class="payments-item mr-md-4 m-3 ml-md-0 my-md-0">
|
||||
<img class="img-fluid" src="/vendor/site/img/naqt.png" alt="Naqt">
|
||||
<span style="transform: translateY(2px);" class="ml-1 d-inline-block">{{ $t('vue.checkout.delivery_in_cash') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="product-info mb-2" v-if="settingData.delivery">
|
||||
<p><b>{{ $t('vue.checkout.delivery_title') }}:</b>
|
||||
{{ getName(settingData.other.delivery) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="product-info mb-2" v-if="settingData.pickup">
|
||||
<p><b>{{ $t('vue.checkout.delivery_pickup') }}:</b> {{ getName(settingData.other.pickup) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="all_tabs py-4">
|
||||
<ul class="tabs">
|
||||
<li :class="product.characteristics.length > 0 ? 'active' : ''"
|
||||
v-if="product.characteristics.length > 0" rel="tab1">{{ $t('vue.cart.characteristic') }}
|
||||
</li>
|
||||
<li :class="product.characteristics.length === 0 ? 'active' : ''" rel="tab2">{{
|
||||
$t('vue.cart.description') }}
|
||||
</li>
|
||||
<li rel="tab3">{{ $t('vue.cart.reviews') }} <span class="badge badge-secondary">{{ product.comments.length }}</span>
|
||||
</li>
|
||||
<!-- <li rel="tab3">{{ $t('vue.cart.reviews') }} <sup><span class="badge badge-secondary" style="font-size: 100%;">5</span></sup></li>-->
|
||||
|
||||
</ul>
|
||||
<div class="tab_container">
|
||||
<h3 class="d_active tab_drawer_heading" rel="tab1" v-if="product.characteristics.length > 0 ">{{
|
||||
$t('vue.cart.characteristic') }}</h3>
|
||||
<div id="tab1" class="tab_content" v-if="product.characteristics.length > 0 ">
|
||||
<h4 class="title title--lg p-b-15 view__title">{{ $t('vue.cart.all_characteristic') }}</h4>
|
||||
<table class="view__table table table-bordered table-striped">
|
||||
<tbody>
|
||||
<tr v-for="(char, index) in product.characteristics" :key="index"
|
||||
v-if="char.pivot.value != 'null'">
|
||||
<td class="view__td-1">
|
||||
<div class="view__td-dots">
|
||||
<span class="view__td-info">
|
||||
{{ getName(char.name) }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="view__td-2" v-if="char.type === 'checkbox'">
|
||||
<span v-if="char.pivot.value === 'true'">
|
||||
{{ $t('app.exist') }}
|
||||
</span>
|
||||
<span v-if="char.pivot.value === 'false'">
|
||||
{{ $t('app.no') }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="view__td-2" v-else>
|
||||
{{ char.pivot.value }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- #tab1 -->
|
||||
<h3 class="tab_drawer_heading" rel="tab2">{{ $t('vue.cart.description') }}</h3>
|
||||
<div id="tab2" class="tab_content" v-html="getName(product.body)">
|
||||
|
||||
</div>
|
||||
<!-- #tab2 -->
|
||||
<h3 class="tab_drawer_heading" rel="tab3">{{ $t('vue.cart.reviews') }} <span
|
||||
class="badge badge-secondary">{{ product.comments.length }}</span></h3>
|
||||
<div id="tab3" class="tab_content">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="message-wrap">
|
||||
<div id="review" v-if="product.comments.length === 0">
|
||||
<p>{{ $t('vue.cart.no_reviews') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="msg-wrap" v-if="product.comments.length > 0">
|
||||
<comment-list v-for="(comment, index) in product.comments"
|
||||
:comment-data="comment" :key="index"></comment-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div v-if="!loginInfo">
|
||||
<h5>{{ $t('vue.cart.only_comment_after_auth') }}</h5>
|
||||
|
||||
<button type="button" class="my-btn my-btn__orange mt-3" data-target="#login"
|
||||
data-toggle="modal">
|
||||
{{ $t('vue.login.auth_title') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success" v-if="alertComment">
|
||||
<i class="fas fa-info-circle"></i> {{ $t('vue.cart.success_comment') }}
|
||||
</div>
|
||||
|
||||
<form class="form-horizontal" @submit.prevent="StoreComment" id="form-review" v-if="loginInfo">
|
||||
|
||||
<h2>{{ $t('vue.cart.write_review') }}</h2>
|
||||
<div class="form-group required">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label" for="input-name">{{ $t('vue.cart.your_name')
|
||||
}}:</label>
|
||||
<input type="text" name="name" v-model="comment.first_name" value="" id="input-name"
|
||||
class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label" for="input-review">{{ $t('vue.cart.your_review')
|
||||
}}:</label>
|
||||
<textarea name="text" v-model="comment.body" rows="5" id="input-review"
|
||||
class="form-control"></textarea>
|
||||
<!-- <div class="help-block">-->
|
||||
<!-- <span style="color: #FF0000;">{{ $t('vue.cart.only_text') }}</span>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label">{{ $t('vue.cart.product_rating') }}</label>
|
||||
{{ $t('vue.cart.bad') }}
|
||||
<input type="radio" name="rating" v-model="comment.star" value="1">
|
||||
|
||||
<input type="radio" name="rating" v-model="comment.star" value="2">
|
||||
|
||||
<input type="radio" name="rating" v-model="comment.star" value="3">
|
||||
|
||||
<input type="radio" name="rating" v-model="comment.star" value="4">
|
||||
|
||||
<input type="radio" name="rating" v-model="comment.star" value="5">
|
||||
{{ $t('vue.cart.good') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons clearfix">
|
||||
<div class="pull-right">
|
||||
<button type="submit" id="button-review" data-loading-text="Загрузка..."
|
||||
class="btn btn-primary">{{ $t('vue.cart.sending') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- #tab3 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<notification :product-id="this.product.id" v-if="!product.isAvailable"
|
||||
:phone-profile="this.phoneProfile"></notification>
|
||||
<buy-one-click :product-id="this.product.id" v-if="product.isAvailable" :phone-profile="this.phoneProfile"
|
||||
:first-name="this.firstName"></buy-one-click>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommentList from '../Comment/CommentList';
|
||||
import Notification from './Notification';
|
||||
import BuyOneClick from './BuyOneClick';
|
||||
|
||||
|
||||
import VueSocialSharing from 'vue-social-sharing'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
productData: {},
|
||||
loginInfo: {},
|
||||
firstName: {},
|
||||
settingData: {},
|
||||
phoneProfile: {}
|
||||
},
|
||||
|
||||
components: {
|
||||
'comment-list': CommentList,
|
||||
'ShareSocial': VueSocialSharing,
|
||||
'notification': Notification,
|
||||
'buy-one-click': BuyOneClick
|
||||
},
|
||||
|
||||
created() {
|
||||
this.url = window.location.href;
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
product: this.productData,
|
||||
count: 1,
|
||||
color_id: null,
|
||||
comment: {
|
||||
star: 0,
|
||||
body: '',
|
||||
first_name: this.firstName
|
||||
},
|
||||
|
||||
alertComment: false,
|
||||
|
||||
alertBasket: false,
|
||||
|
||||
colors: false,
|
||||
url: ''
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (name) {
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
default:
|
||||
value = name.ru;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
async Favorite(product) {
|
||||
var field = document.getElementById("favorite-count");
|
||||
var count = field.value;
|
||||
|
||||
if (product.isFavorite === false) {
|
||||
const { data } = await axios.get('/favorites/store/' + product.id);
|
||||
this.product.isFavorite = true;
|
||||
field.value = parseInt(count) + 1;
|
||||
} else {
|
||||
const { data } = await axios.get('/favorites/delete/' + product.id);
|
||||
this.product.isFavorite = false;
|
||||
field.value = parseInt(count) - 1;
|
||||
}
|
||||
},
|
||||
|
||||
async AddToCart() {
|
||||
|
||||
if (this.product.isCart) {
|
||||
this.$eventBus.$emit('cart-preview');
|
||||
return;
|
||||
}
|
||||
|
||||
const fields = {
|
||||
product_id: this.product.childrens[0].id,
|
||||
count: this.count
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/cart/store', fields);
|
||||
|
||||
if (data.status) {
|
||||
this.product.isCart = true;
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
}
|
||||
},
|
||||
|
||||
CountMinus() {
|
||||
if (this.product.isAvailable) {
|
||||
if (this.count <= 1) {
|
||||
return 1;
|
||||
} else {
|
||||
this.count -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
CountAdd() {
|
||||
if (this.product.isAvailable && this.product.count > this.count) {
|
||||
this.count += 1;
|
||||
}
|
||||
},
|
||||
|
||||
CreditCookie() {
|
||||
this.$cookie.delete('cart-preview');
|
||||
this.$cookie.set('product-credit', this.product.id);
|
||||
},
|
||||
|
||||
async StoreComment() {
|
||||
const { data } = await axios.post('/product/comment/' + this.product.id, this.comment);
|
||||
|
||||
if (data.status) {
|
||||
this.comment = {
|
||||
star: 0,
|
||||
body: '',
|
||||
first_name: this.firstName
|
||||
};
|
||||
|
||||
this.alertComment = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
157
resources/js/components/Products/ProductSlider.vue
Executable file
157
resources/js/components/Products/ProductSlider.vue
Executable file
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<swiper
|
||||
ref="mySwiper"
|
||||
class="swiper-container swiper-product swiper-product-lider_sales"
|
||||
:options="swiperOptions"
|
||||
>
|
||||
<swiper-slide v-for="(product, index) in products" :key="index">
|
||||
<Product :product="product" :login-info="loginInfo"/>
|
||||
</swiper-slide>
|
||||
|
||||
<!-- Add Arrows -->
|
||||
<div class="swiper-button-next swiper-button-next-product" slot="button-next"></div>
|
||||
<div class="swiper-button-prev swiper-button-prev-product" slot="button-prev"></div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-product" slot="pagination"></div>
|
||||
</swiper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Swiper, SwiperSlide, directive } from "vue-awesome-swiper";
|
||||
//import "swiper/swiper-bundle.css";
|
||||
import Product from './Product.vue';
|
||||
import 'swiper/css/swiper.css'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
productsData: {},
|
||||
loginInfo: {}
|
||||
},
|
||||
components: {
|
||||
Swiper,
|
||||
SwiperSlide,
|
||||
Product
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
swiperOptions: {
|
||||
spaceBetween: 20,
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next-product",
|
||||
prevEl: ".swiper-button-prev-product",
|
||||
},
|
||||
pagination: {
|
||||
el: ".swiper-pagination-product",
|
||||
dynamicBullets: true,
|
||||
},
|
||||
breakpoints: {
|
||||
1200: {
|
||||
slidesPerView: 5,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 4,
|
||||
},
|
||||
768: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
576: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
0: {
|
||||
slidesPerView: 1.3,
|
||||
},
|
||||
},
|
||||
autoplay: {
|
||||
delay: 4000,
|
||||
},
|
||||
},
|
||||
products: this.productsData,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
swiper() {
|
||||
return this.$refs.mySwiper.$swiper;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$breakpoints: (
|
||||
"phone-smallest": 251px,
|
||||
"phone-small": 321px,
|
||||
"phone": 400px,
|
||||
"phone-wide": 480px,
|
||||
"phablet": 560px,
|
||||
"tablet-small": 640px,
|
||||
"tablet": 768px,
|
||||
"tablet-wide": 1024px,
|
||||
"desktop": 1248px,
|
||||
"desktop-wide": 1440px,
|
||||
"desktop-large": 2500px,
|
||||
);
|
||||
|
||||
@mixin mq($width, $type: min) {
|
||||
@if map_has_key($breakpoints, $width) {
|
||||
$width: map_get($breakpoints, $width);
|
||||
|
||||
@if $type==max {
|
||||
$width: $width - 1px;
|
||||
}
|
||||
|
||||
@media only screen and (#{$type}-width: $width) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Transition
|
||||
%tr03 {
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
%tr02 {
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
$my-orange: rgb(255, 98, 26);
|
||||
$my-dark-gray: #5b5b5b;
|
||||
$my-blue-dark: #0a0d21;
|
||||
|
||||
// Vertical or Horizontal position
|
||||
%v-c {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
-ms-transform: translateY(-50%);
|
||||
-webkit-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
%h-c {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
-ms-transform: translateX(-50%);
|
||||
-webkit-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
%c-c {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.swiper-product {
|
||||
padding: 75px 0 50px;
|
||||
margin-top: -50px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
|
||||
@include mq("tablet", max) {
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
164
resources/js/components/Search/SearchList.vue
Executable file
164
resources/js/components/Search/SearchList.vue
Executable file
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="products.length === 0">
|
||||
{{ $t('app.search_result', {text: searchText}) }}
|
||||
</div>
|
||||
|
||||
<div class="row" v-if="products.length > 0">
|
||||
<div v-for="(product, index) in products" class="col-lg-12 col-md-6">
|
||||
<div class="product my-3">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-2">
|
||||
<a :href="'/product/show/' + product.id + '-' + product.slug">
|
||||
<div class="product-top">
|
||||
<div class="type" v-if="product.diffDate && product.isAvailable">NEW</div>
|
||||
<div class="discound" v-if="product.discountPrice > 0 && product.price_discount && product.isAvailable">
|
||||
{{ $t('vue.sale') }}
|
||||
</div>
|
||||
<div class="xit" v-if="product.leader_of_sales && product.isAvailable">ХИТ</div>
|
||||
<div class="no-product" v-if="!product.isAvailable">
|
||||
{{ $t('vue.not_available') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="product-img">
|
||||
<img :src="'/' + product.poster_thumb" :alt="getName(product.name)" :class="!product.isAvailable ? 'no-product-img' : ''" >
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<h3 class="product-title">
|
||||
<a :href="'/product/show/' + product.id + '-' + product.slug">{{ getName(product.name) }}</a>
|
||||
</h3>
|
||||
<!-- <div class="product-address">{{ $t('app.product.article_number') }}: {{ product.article_number }}</div>-->
|
||||
<div class="product-price_and_checkout mt-2" v-if="product.discountPrice > 0">
|
||||
<button class="my-btn my-btn__orange my-btn__orange--small">{{ $t('app.discount') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-2"></div>
|
||||
<div class="col-lg-3">
|
||||
<div class="product-price mt-3 mt-lg-0">
|
||||
<div class="old-price mb-1 text-lg-right" v-if="product.price_discount">
|
||||
{{ product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}
|
||||
</div>
|
||||
<div class="new-price text-lg-right">{{ product.price_discount ? product.price_discount : product.price | number('0,0', { thousandsSeparator: ' ' }) }} {{ $t('app.sum') }}</div>
|
||||
|
||||
</div>
|
||||
<div class="product-buttons">
|
||||
<div class="product-to_cart justify-content-lg-end">
|
||||
<button v-if="!product.isCart && product.isAvailable" :class="product.isCart ? 'product-to_basket is-active is-actived' : 'product-to_basket is-actived'" @click="AddToCart(product)">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span>{{ $t('app.to_cart') }}</span>
|
||||
|
||||
<div class="added-to-basket" v-html="$t('vue.favorite.added_to_basket')">
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button v-if="product.isCart && product.isAvailable" :class="product.isCart ? 'product-to_basket is-active is-actived' : 'product-to_basket is-actived'" data-target="#basket_modal" data-toggle="modal" @click="AddToCart(product)">
|
||||
<i class="far fa-shopping-basket"></i>
|
||||
<span>{{ $t('app.to_cart') }}</span>
|
||||
</button>
|
||||
|
||||
<div class="d-flex">
|
||||
<button class="product-to_compare mr-3 ml-2">
|
||||
<i class="far fa-balance-scale"></i>
|
||||
</button>
|
||||
|
||||
<button class="product-to_favorite" data-target="#login" data-toggle="modal" v-if="!loginInfo">
|
||||
<i class="fas fa-heart"></i>
|
||||
</button>
|
||||
|
||||
<button :class="product.isFavorite ? 'product-to_favorite is-active' : 'product-to_favorite'" @click="Favorite(product)" v-if="loginInfo">
|
||||
<i class="fas fa-heart"></i>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
searchData: {},
|
||||
loginInfo: {},
|
||||
searchText: {}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
products: this.searchData.data
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
},
|
||||
|
||||
async AddToCart(product) {
|
||||
if (product.isCart) {
|
||||
this.$eventBus.$emit('cart-preview');
|
||||
return;
|
||||
}
|
||||
|
||||
const fields = {
|
||||
product_id: product.children.id,
|
||||
count: 1
|
||||
};
|
||||
|
||||
const { data } = await axios.post('/cart/store', fields);
|
||||
|
||||
if (data.status) {
|
||||
product.isCart = true;
|
||||
var basket = document.getElementById("basket-count");
|
||||
basket.value = data.count;
|
||||
}
|
||||
},
|
||||
|
||||
async Favorite(product) {
|
||||
var field = document.getElementById("favorite-count");
|
||||
var count = field.value;
|
||||
|
||||
if (product.isFavorite === false) {
|
||||
const { data } = await axios.get('/favorites/store/' + product.id);
|
||||
product.isFavorite = true;
|
||||
field.value = parseInt(count) + 1;
|
||||
} else {
|
||||
const { data } = await axios.get('/favorites/delete/' + product.id);
|
||||
product.isFavorite = false;
|
||||
field.value = parseInt(count) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
152
resources/js/components/Slider/SliderView.vue
Executable file
152
resources/js/components/Slider/SliderView.vue
Executable file
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-1">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" @click="changeLang" id="ru" data-toggle="tab" href="#RU" aria-selected="true">RU</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" @click="changeLang" id="uz" data-toggle="tab" href="#UZ" aria-selected="false">UZ</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" @click="changeLang" data-toggle="tab" href="#all" aria-selected="false">Все</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav nav-tabs" v-if="filter.lang" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" @click="changeType" id="mobile" data-toggle="tab" href="#RU" aria-selected="true">Мобильный</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" @click="changeType" id="desktop" data-toggle="tab" href="#UZ" aria-selected="false">Компьютер</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav nav-tabs" v-if="filter.type" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" @click="changePlacement" id="top" data-toggle="tab" href="#RU" aria-selected="true">Верхний</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" @click="changePlacement" id="middle" data-toggle="tab" href="#UZ" aria-selected="false">Нижний</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table mb-0" :key="0">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th scope="col" width="50">ID</th>
|
||||
<th scope="col" width="50">{{ $t('admin.slider.image') }}</th>
|
||||
<th scope="col">{{ $t('admin.slider.name') }}</th>
|
||||
<th scope="col">{{ $t('admin.slider.position') }}</th>
|
||||
<th scope="col" class="text-right">{{ $t('admin.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-if="sliders.length === 0">
|
||||
<tr>
|
||||
<td class="text-center" colspan="4">
|
||||
{{ $t('admin.no_data') }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<draggable v-else v-model="sliders" tag="tbody">
|
||||
<tr v-for="slider in sliders" :key="slider.id" v-if="(!filter.lang || filter.lang === slider.language) && (!filter.type || filter.type === slider.type) && (!filter.placement || filter.placement === slider.placement)">
|
||||
<th scope="row">
|
||||
{{ slider.id }}
|
||||
</th>
|
||||
<td>
|
||||
<img :src="`/${slider.image}`" width="100%" alt="">
|
||||
</td>
|
||||
<td>
|
||||
<i v-if="!slider.published" class="fa fa-info-circle text-danger" data-toggle="tooltip" data-original-title="$t('admin.no_publish')"></i>
|
||||
{{ slider.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ slider.position }}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<a v-if="role.permissions.sliders.update" :href="`/dashboard/sliders/update/${slider.id}`" class="btn btn-sm btn-success btn-icon" data-toggle="tooltip" :data-original-title="$t('admin.edit')">
|
||||
<i class="feather icon-edit"></i>
|
||||
</a>
|
||||
|
||||
<a v-if="role.permissions.sliders.delete" :href="`/dashboard/sliders/delete/${slider.id}`" class="btn btn-sm btn-danger btn-icon" data-toggle="tooltip" :data-original-title="$t('admin.delete')">
|
||||
<i class="feather icon-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</draggable>
|
||||
</table>
|
||||
<div class="card-body">
|
||||
<button class="btn btn-primary" @click="save">
|
||||
<i class="fa fa-save"></i> Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
|
||||
export default {
|
||||
name: "SliderView",
|
||||
components: {
|
||||
draggable
|
||||
},
|
||||
props: {
|
||||
slidersData: {},
|
||||
role: {},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sliders: this.slidersData,
|
||||
filter: {
|
||||
lang: null,
|
||||
type: null,
|
||||
placement: null,
|
||||
},
|
||||
}
|
||||
},
|
||||
// mounted() {
|
||||
// console.log(this.sliders)
|
||||
// },
|
||||
methods: {
|
||||
changeLang(event) {
|
||||
let lang = event.target.getAttribute('id')
|
||||
this.filter.lang = lang
|
||||
if (!lang) {
|
||||
this.filter.type = null
|
||||
this.filter.placement = null
|
||||
}
|
||||
},
|
||||
changeType(event) {
|
||||
this.filter.type = event.target.getAttribute('id')
|
||||
},
|
||||
changePlacement(event) {
|
||||
this.filter.placement = event.target.getAttribute('id')
|
||||
},
|
||||
|
||||
changePosition() {
|
||||
for (let i = 0; i < this.sliders.length; i++) {
|
||||
let position = i + 1
|
||||
this.sliders[i].position = i + 1;
|
||||
}
|
||||
},
|
||||
|
||||
save() {
|
||||
this.changePosition()
|
||||
const form = new FormData()
|
||||
|
||||
for (let i = 0; i < this.sliders.length; i++) {
|
||||
let slider = this.sliders[i]
|
||||
form.append(`sliders[${i}][id]`, slider.id)
|
||||
form.append(`sliders[${i}][position]`, slider.position)
|
||||
}
|
||||
|
||||
axios.post('/dashboard/sliders/position', form)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
13
resources/js/components/Specials/Mobile.vue
Executable file
13
resources/js/components/Specials/Mobile.vue
Executable file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Mobile"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
188
resources/js/components/Specials/SpecialBlock.vue
Executable file
188
resources/js/components/Specials/SpecialBlock.vue
Executable file
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="specials" v-if="!mobile">
|
||||
<a v-for="(offer, index) in offers" :key="index" :href="offer.link" class="special" :style="{ 'background-image': 'url(/' + offer.image + ')' }">
|
||||
<div class="special-content">
|
||||
<h3 class="special-title">{{ getName(offer.name) }}</h3>
|
||||
<p class="special-price">{{ getName(offer.description) }}</p>
|
||||
<div class="my-btn my-btn__orange">
|
||||
<span>{{ $t('vue.special.more') }}</span>
|
||||
<i class="fal fa-chevron-right ml-2"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<swiper
|
||||
ref="mySwiperSpicial"
|
||||
class="swiper-container swiper-product swiper-specials"
|
||||
:options="swiperOptions"
|
||||
v-if="mobile"
|
||||
>
|
||||
<swiper-slide v-for="(offer, index) in offers" :key="index">
|
||||
<div class="specials">
|
||||
<a :href="offer.link" class="special" :style="{ 'background-image': 'url(/' + offer.image + ')' }">
|
||||
<div class="special-content">
|
||||
<h3 class="special-title">{{ getName(offer.name) }}</h3>
|
||||
<p class="special-price">{{ getName(offer.description) }}</p>
|
||||
|
||||
<div class="my-btn my-btn__orange">
|
||||
<span>{{ $t('vue.special.more') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
|
||||
|
||||
<!-- Add Arrows -->
|
||||
<div class="swiper-button-next swiper-button-next-product" slot="button-next"></div>
|
||||
<div class="swiper-button-prev swiper-button-prev-product" slot="button-prev"></div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-product" slot="pagination"></div>
|
||||
</swiper>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
|
||||
import 'swiper/css/swiper.css'
|
||||
import { isMobileOnly } from "mobile-device-detect";
|
||||
|
||||
|
||||
export default {
|
||||
props: {
|
||||
offersData: {}
|
||||
},
|
||||
|
||||
components: {
|
||||
Swiper,
|
||||
SwiperSlide,
|
||||
isMobileOnly
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
mobile: isMobileOnly ? true : false,
|
||||
|
||||
swiperOptions: {
|
||||
spaceBetween: 20,
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next-product",
|
||||
prevEl: ".swiper-button-prev-product",
|
||||
},
|
||||
pagination: {
|
||||
el: ".swiper-pagination-product",
|
||||
dynamicBullets: true,
|
||||
},
|
||||
breakpoints: {
|
||||
1200: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
768: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
576: {
|
||||
slidesPerView: 1,
|
||||
},
|
||||
0: {
|
||||
slidesPerView: 1,
|
||||
},
|
||||
},
|
||||
autoplay: {
|
||||
delay: 4000,
|
||||
},
|
||||
},
|
||||
offers: this.offersData,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
swiper() {
|
||||
return this.$refs.mySwiperSpicial.$swiper;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
getName(name) {
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
let value = '';
|
||||
|
||||
if (lang) {
|
||||
switch(lang){
|
||||
case "ru":
|
||||
value = name.ru;
|
||||
break;
|
||||
case "uz":
|
||||
value = name.uz;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = name.ru;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
$breakpoints: (
|
||||
"phone-smallest": 251px,
|
||||
"phone-small": 321px,
|
||||
"phone": 400px,
|
||||
"phone-wide": 480px,
|
||||
"phablet": 560px,
|
||||
"tablet-small": 640px,
|
||||
"tablet": 768px,
|
||||
"tablet-wide": 1024px,
|
||||
"desktop": 1248px,
|
||||
"desktop-wide": 1440px,
|
||||
"desktop-large": 2500px
|
||||
);
|
||||
|
||||
@mixin mq($width, $type: min) {
|
||||
@if map_has_key($breakpoints, $width) {
|
||||
$width: map_get($breakpoints, $width);
|
||||
|
||||
@if $type==max {
|
||||
$width: $width - 1px;
|
||||
}
|
||||
|
||||
@media only screen and (#{$type}-width: $width) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-specials {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
margin-bottom: 0;
|
||||
margin-top: 50px;
|
||||
|
||||
@include mq("tablet", max) {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 30px;
|
||||
margin-top: 0;
|
||||
}
|
||||
.specials {
|
||||
.special {
|
||||
width: 100%;
|
||||
|
||||
@include mq("tablet", max) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
43
resources/js/components/StocksView.vue
Executable file
43
resources/js/components/StocksView.vue
Executable file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="section-products" v-if="newsData.length > 0">
|
||||
<div class="container">
|
||||
<h2 class="section-title">{{ $t('vue.stocks.sales') }}</h2>
|
||||
<news-slider :posts-data="newsData"></news-slider>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section-categories">
|
||||
<div class="container">
|
||||
<h2 class="section-title">{{ $t('vue.stocks.discount') }}</h2>
|
||||
|
||||
<div class="aksiya">
|
||||
<Product v-for="(product, index) in products" :key="index" :product="product" :login-info="loginInfo"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Product from './Products/Product.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
productsData: {},
|
||||
loginInfo: {},
|
||||
newsData: {}
|
||||
},
|
||||
|
||||
components: {
|
||||
Product
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
products: this.productsData.data
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
88
resources/js/vendor.js
Executable file
88
resources/js/vendor.js
Executable file
@@ -0,0 +1,88 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
import VueInternationalization from 'vue-i18n';
|
||||
import Locale from './vue-i18n-locales.generated';
|
||||
|
||||
import Vue2Filters from 'vue2-filters'
|
||||
import VueMask from 'v-mask'
|
||||
|
||||
import VueSocialSharing from 'vue-social-sharing'
|
||||
import VueCookie from 'vue-cookie';
|
||||
|
||||
|
||||
// New way (ES Modules)
|
||||
import axios from 'axios';
|
||||
window.axios = axios;
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
|
||||
//Site
|
||||
import ProductSlider from './components/Products/ProductSlider';
|
||||
import ProductShow from './components/Products/ProductShow';
|
||||
import Login from './components/Auth/Login';
|
||||
import FavoritesBlock from './components/Favorites/FavoriteBlock';
|
||||
import SearchBlock from './components/Search/SearchList';
|
||||
import NewsSlider from './components/News/NewsSlider'
|
||||
import NewsSection from './components/News/NewsSection'
|
||||
|
||||
import CategoriesBlock from "./components/CategoriesBlock";
|
||||
import CartView from './components/Cart/CartList';
|
||||
import CatalogShow from "./components/Catalog/CatalogShow";
|
||||
import CheckoutView from "./components/Checkout/CheckoutView";
|
||||
import CartPreview from "./components/Cart/CartPreview";
|
||||
import PartnerSlider from "./components/Partners/PartnerSlider";
|
||||
import HeaderSlider from './components/Banners/HeaderSlider';
|
||||
import FeaturesSection from './components/FeaturesSection';
|
||||
import BonusSection from "./components/BonusSection";
|
||||
import StocksView from "./components/StocksView";
|
||||
import SpecialBlock from "./components/Specials/SpecialBlock";
|
||||
import BrandView from "./components/BrandView";
|
||||
import Credit from "./components/Products/Credit";
|
||||
|
||||
Vue.component('news-slider', NewsSlider);
|
||||
Vue.component('news-section', NewsSection);
|
||||
|
||||
Vue.component('products-slider', ProductSlider);
|
||||
Vue.component('product-show', ProductShow);
|
||||
Vue.component('search-block', SearchBlock);
|
||||
Vue.component('categories-block', CategoriesBlock);
|
||||
|
||||
Vue.component('login', Login);
|
||||
Vue.component('credit-modal', Credit);
|
||||
Vue.component('favorite-block', FavoritesBlock);
|
||||
Vue.component('cart-view', CartView);
|
||||
Vue.component('checkout-view', CheckoutView);
|
||||
Vue.component('catalog-show', CatalogShow);
|
||||
Vue.component('cart-preview', CartPreview);
|
||||
Vue.component('partners-slider', PartnerSlider);
|
||||
Vue.component('header-slider', HeaderSlider);
|
||||
Vue.component('features-section', FeaturesSection);
|
||||
Vue.component('bonus-section', BonusSection);
|
||||
|
||||
Vue.component('stocks-view', StocksView);
|
||||
Vue.component('brand-view', BrandView);
|
||||
|
||||
Vue.component('special-block', SpecialBlock);
|
||||
|
||||
Vue.use(VueMask);
|
||||
Vue.use(VueSocialSharing);
|
||||
|
||||
Vue.use(VueCookie);
|
||||
|
||||
Vue.use(VueInternationalization);
|
||||
Vue.use(Vue2Filters);
|
||||
|
||||
Vue.prototype.$eventBus = new Vue();
|
||||
|
||||
const lang = document.documentElement.lang.substr(0, 2);
|
||||
|
||||
const i18n = new VueInternationalization({
|
||||
locale: lang,
|
||||
messages: Locale
|
||||
});
|
||||
|
||||
const app = new Vue({
|
||||
el: '#app',
|
||||
i18n,
|
||||
});
|
||||
1365
resources/js/vue-i18n-locales.generated.js
Executable file
1365
resources/js/vue-i18n-locales.generated.js
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user