some changes in register 1401-03-02
This commit is contained in:
@@ -113,3 +113,15 @@ Vue.filter('jtjdate', (val) => {
|
||||
}
|
||||
return val;
|
||||
});
|
||||
|
||||
Vue.filter('toFixed', (val) => {
|
||||
if (val) {
|
||||
try {
|
||||
return parseFloat(val).toFixed(2)
|
||||
}
|
||||
catch (e) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
});
|
||||
|
||||
+20
-20
@@ -133,32 +133,32 @@ require('./assets/css/iconfont.css')
|
||||
// import 'vue-select/dist/vue-select.css';
|
||||
|
||||
//permission functions
|
||||
Vue.prototype.$getAccess = (rid)=>{
|
||||
const roles = store.state.access.permissions
|
||||
if(roles){
|
||||
return roles.includes(rid)
|
||||
}
|
||||
Vue.prototype.$getAccess = (rid) => {
|
||||
const roles = store.state.access.permissions
|
||||
if (roles) {
|
||||
return roles.includes(rid)
|
||||
}
|
||||
}
|
||||
import VuePersianDatetimePicker from 'vue-persian-datetime-picker';
|
||||
Vue.use(VuePersianDatetimePicker, {
|
||||
name: 'date-picker',
|
||||
props: {
|
||||
displayFormat: 'jYYYY/jMM/jDD',
|
||||
format: 'YYYY/MM/DD',
|
||||
editable: false,
|
||||
inputClass: '',
|
||||
placeholder: 'انتخاب کنید',
|
||||
color: '#1DA57A',
|
||||
autoSubmit: true,
|
||||
}
|
||||
name: 'date-picker',
|
||||
props: {
|
||||
displayFormat: 'jYYYY/jMM/jDD',
|
||||
format: 'YYYY/MM/DD',
|
||||
editable: false,
|
||||
inputClass: '',
|
||||
placeholder: 'انتخاب کنید',
|
||||
color: '#1DA57A',
|
||||
autoSubmit: true,
|
||||
}
|
||||
});
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
i18n,
|
||||
acl,
|
||||
render: h => h(App)
|
||||
router,
|
||||
store,
|
||||
i18n,
|
||||
acl,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import store from '@/store/store.js'
|
||||
|
||||
export const printWindow = (innerHTML = document.getElementById('printContent') ? document.getElementById('printContent').innerHTML : '') => {
|
||||
|
||||
// Get all stylesheets HTML
|
||||
let stylesHtml = ''
|
||||
for (const node of [...document.querySelectorAll('link[rel="stylesheet"], style')]) {
|
||||
stylesHtml += node.outerHTML
|
||||
}
|
||||
|
||||
// Open the print window
|
||||
const WinPrint = window.open('', '', 'left=0,top=0,width=800,height=900,toolbar=0,scrollbars=0,status=0')
|
||||
WinPrint.document.write('<!DOCTYPE html><html><head>' +
|
||||
stylesHtml +
|
||||
'<title>چاپ اطلاعات</title>' +
|
||||
'</head><body>' +
|
||||
innerHTML +
|
||||
'</body></html>')
|
||||
|
||||
WinPrint.document.close()
|
||||
WinPrint.focus()
|
||||
setTimeout(() => {
|
||||
// WinPrint.print()
|
||||
// WinPrint.close()
|
||||
}, 600)
|
||||
}
|
||||
|
||||
const keyEvent = ($event) => {
|
||||
if ($event.ctrlKey && $event.code == 'KeyP' && store.state.isViewData) {
|
||||
$event.preventDefault()
|
||||
printWindow()
|
||||
}
|
||||
}
|
||||
|
||||
export const setKeyEvent = () => {
|
||||
document.addEventListener('keydown', keyEvent)
|
||||
}
|
||||
export const removeKeyEvent = () => {
|
||||
|
||||
document.removeEventListener('keydown', keyEvent)
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ export default {
|
||||
Vue.prototype.$ntSetError = function (msg) {
|
||||
this.$vs.notify({
|
||||
title: 'خطا در ثبت اطلاعات',
|
||||
//text: msg || 'اطلاعات ثبت نگردید.',
|
||||
text: msg || 'اطلاعات ثبت نگردید.',
|
||||
color: 'danger',
|
||||
})
|
||||
}
|
||||
|
||||
+10
-1
@@ -91,6 +91,15 @@ const router = new Router({
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/personel/edit/:id',
|
||||
name: 'personel',
|
||||
component: () => import('./views/personel/view_edit_personel.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
parent: 'main'
|
||||
}
|
||||
},
|
||||
/* {
|
||||
path: '/register/contract',
|
||||
name: 'register-contract',
|
||||
component: () => import('./views/register/RegisterPersonnel.vue'),
|
||||
@@ -98,7 +107,7 @@ const router = new Router({
|
||||
rule: 'editor',
|
||||
parent: 'main'
|
||||
}
|
||||
},
|
||||
},*/
|
||||
{
|
||||
path: '/contract',
|
||||
name: 'contract',
|
||||
|
||||
@@ -134,7 +134,8 @@ const mutations = {
|
||||
}
|
||||
// Store data in localStorage
|
||||
localStorage.setItem('userInfo', JSON.stringify(userInfo))
|
||||
}
|
||||
},
|
||||
SetViewData (state, val) { state.isViewData = val },
|
||||
}
|
||||
|
||||
export default mutations
|
||||
|
||||
+2
-1
@@ -94,7 +94,8 @@ const state = {
|
||||
loading: false,
|
||||
error: undefined,
|
||||
|
||||
|
||||
// custom print view
|
||||
isViewData : false,
|
||||
}
|
||||
|
||||
export default state
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<template>
|
||||
|
||||
<div id="loading-bg">
|
||||
<div class="loading-logo">
|
||||
<img src="@/assets/images/logo/logo.svg" width="150px" alt="Logo">
|
||||
|
||||
</div>
|
||||
<div class="loading">
|
||||
<div class="effect-1 effects"></div>
|
||||
<div class="effect-2 effects"></div>
|
||||
<div class="effect-3 effects"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
handleLoginEvent (data) {
|
||||
this.$store.dispatch('updateUserInfo', {
|
||||
displayName: data.profile.name,
|
||||
email: data.profile.email,
|
||||
photoURL: data.profile.picture,
|
||||
providerId: data.profile.sub.substr(0, data.profile.sub.indexOf('|')),
|
||||
uid: data.profile.sub
|
||||
})
|
||||
this.$router.push(data.state.target || '/')
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.$auth.handleAuthentication()
|
||||
if (this.$auth.isAuthenticated()) this.$router.push('/').catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../assets/css/loader.css";
|
||||
</style>
|
||||
@@ -1,315 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: DashboardEcommerce.vue
|
||||
Description: Dashboard - Ecommerce
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full sm:w-1/2 md:w-1/2 lg:w-1/4 xl:w-1/4 mb-base">
|
||||
<statistics-card-line
|
||||
v-if="subscribersGained.analyticsData"
|
||||
icon="UsersIcon"
|
||||
:statistic="subscribersGained.analyticsData.subscribers | k_formatter"
|
||||
statisticTitle="رشد ثبت نام کاربران"
|
||||
:chartData="subscribersGained.series"
|
||||
type="area"/>
|
||||
</div>
|
||||
|
||||
<div class="vx-col w-full sm:w-1/2 md:w-1/2 lg:w-1/4 xl:w-1/4 mb-base">
|
||||
<statistics-card-line
|
||||
v-if="revenueGenerated.analyticsData"
|
||||
icon="DollarSignIcon"
|
||||
:statistic="revenueGenerated.analyticsData.revenue | k_formatter"
|
||||
statisticTitle="ترند مالی ماه"
|
||||
:chartData="revenueGenerated.series"
|
||||
color="success"
|
||||
type="area"/>
|
||||
</div>
|
||||
|
||||
<div class="vx-col w-full sm:w-1/2 md:w-1/2 lg:w-1/4 xl:w-1/4 mb-base">
|
||||
<statistics-card-line
|
||||
v-if="quarterlySales.analyticsData"
|
||||
icon="HexagonIcon"
|
||||
:statistic="quarterlySales.analyticsData.sales"
|
||||
statisticTitle="تبادات گرمی"
|
||||
:chartData="quarterlySales.series"
|
||||
color="danger"
|
||||
type="area"/>
|
||||
</div>
|
||||
<div class="vx-col w-full sm:w-1/2 md:w-1/2 lg:w-1/4 xl:w-1/4 mb-base">
|
||||
<statistics-card-line
|
||||
v-if="ordersRecevied.analyticsData"
|
||||
icon="ShoppingBagIcon"
|
||||
:statistic="ordersRecevied.analyticsData.orders | k_formatter"
|
||||
statisticTitle="تعداد سفارشات"
|
||||
:chartData="ordersRecevied.series"
|
||||
color="warning"
|
||||
type="area"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-row">
|
||||
|
||||
<!-- LINE CHART -->
|
||||
<div class="vx-col w-full md:w-2/3 mb-base">
|
||||
<vx-card title="سفارشات ">
|
||||
<div slot="no-body" class="p-6 pb-0">
|
||||
<div class="flex" v-if="revenueComparisonLine.analyticsData">
|
||||
<div class="mr-6">
|
||||
<p class="mb-1 font-semibold">ماه جاری</p>
|
||||
<p class="text-3xl text-success">{{ revenueComparisonLine.analyticsData.thisMonth.toLocaleString()
|
||||
}}<sup class="text-base mr-1">تومان</sup></p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mb-1 font-semibold">ماه گذشته</p>
|
||||
<p class="text-3xl">{{ revenueComparisonLine.analyticsData.lastMonth.toLocaleString() }}<sup
|
||||
class="text-base mr-1">تومان</sup></p>
|
||||
</div>
|
||||
</div>
|
||||
<vue-apex-charts
|
||||
type="line"
|
||||
height="266"
|
||||
:options="analyticsData.revenueComparisonLine.chartOptions"
|
||||
:series="revenueComparisonLine.series"/>
|
||||
</div>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
<!-- RADIAL CHART -->
|
||||
<div class="vx-col w-full md:w-1/3 mb-base">
|
||||
<vx-card title="سفارشات باز">
|
||||
<template slot="actions">
|
||||
<ATooltip placement="right">
|
||||
<span slot="title">نسبت سفارشات باز به سفارشات بسته</span>
|
||||
<feather-icon icon="HelpCircleIcon" svgClasses="w-6 h-6 text-grey"></feather-icon>
|
||||
</ATooltip>
|
||||
</template>
|
||||
|
||||
<!-- CHART -->
|
||||
<template slot="no-body">
|
||||
<div class="mt-10">
|
||||
<vue-apex-charts type="radialBar" height="240" :options="analyticsData.goalOverviewRadialBar.chartOptions"
|
||||
:series="goalOverview.series"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- DATA -->
|
||||
<div class="flex justify-between text-center mt-6" slot="no-body-bottom">
|
||||
<div class="w-1/2 border border-solid d-theme-border-grey-light border-r-0 border-b-0 border-l-0">
|
||||
<p class="mt-4"> کامل شده</p>
|
||||
<p class="mb-4 text-3xl font-semibold">786,617</p>
|
||||
</div>
|
||||
<div class="w-1/2 border border-solid d-theme-border-grey-light border-r-0 border-b-0">
|
||||
<p class="mt-4">در حال پردازش</p>
|
||||
<p class="mb-4 text-3xl font-semibold">13,561</p>
|
||||
</div>
|
||||
</div>
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full md:w-2/3">
|
||||
<vx-card title="نسبت فروش تومان به گرم">
|
||||
<div class="flex">
|
||||
<span class="flex items-center"><div
|
||||
class="h-3 w-3 rounded-full mr-1 bg-primary"></div><span>تومان</span></span>
|
||||
<span class="flex items-center ml-4"><div class="h-3 w-3 rounded-full mr-1 bg-danger"></div><span>گرم</span></span>
|
||||
</div>
|
||||
<vue-apex-charts type="bar" height="277" :options="analyticsData.clientRetentionBar.chartOptions"
|
||||
:series="clientRetentionBar.series"/>
|
||||
</vx-card>
|
||||
</div>
|
||||
<div class="vx-col w-full lg:w-1/3 lg:mt-0 mt-base">
|
||||
<vx-card title="کیفی های فعال و غیرفعال">
|
||||
<div slot="no-body">
|
||||
<vue-apex-charts class="mt-6 mb-8" type="donut" height="325"
|
||||
:options="analyticsData.sessionsByDeviceDonut.chartOptions" :series="sessionsData.series"/>
|
||||
</div>
|
||||
|
||||
<ul class="mt-6">
|
||||
<li v-for="deviceData in sessionsData.analyticsData" :key="deviceData.device" class="flex mb-3">
|
||||
<feather-icon :icon="deviceData.icon"
|
||||
:svgClasses="[`h-5 w-5 stroke-current text-${deviceData.color}`]"></feather-icon>
|
||||
<span class="ml-2 inline-block font-semibold">{{ deviceData.device }}</span>
|
||||
<span class="mx-2">-</span>
|
||||
<span class="mr-4">{{ deviceData.sessionsPercentage }}%</span>
|
||||
<div class="ml-auto flex -mr-1">
|
||||
<span class="mr-1">{{ deviceData.comparedResultPercentage }}%</span>
|
||||
<feather-icon :icon=" deviceData.comparedResultPercentage < 0 ? 'ArrowDownIcon' : 'ArrowUpIcon'"
|
||||
:svgClasses="[deviceData.comparedResultPercentage < 0 ? 'text-danger' : 'text-success' ,'stroke-current h-4 w-4 mb-1 mr-1']"></feather-icon>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
import VueApexCharts from 'vue-apexcharts'
|
||||
import StatisticsCardLine from '@/components/statistics-cards/StatisticsCardLine.vue'
|
||||
import analyticsData from './ui-elements/card/analyticsData.js'
|
||||
import ChangeTimeDurationDropdown from '@/components/ChangeTimeDurationDropdown.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VueApexCharts,
|
||||
StatisticsCardLine,
|
||||
VuePerfectScrollbar,
|
||||
ChangeTimeDurationDropdown
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
subscribersGained: {},
|
||||
revenueGenerated: {},
|
||||
quarterlySales: {},
|
||||
ordersRecevied: {},
|
||||
|
||||
revenueComparisonLine: {},
|
||||
goalOverview: {},
|
||||
|
||||
browserStatistics: [],
|
||||
clientRetentionBar: {},
|
||||
|
||||
sessionsData: {},
|
||||
chatLog: [],
|
||||
chatMsgInput: '',
|
||||
customersData: {},
|
||||
|
||||
analyticsData,
|
||||
settings: { // perfectscrollbar settings
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed: .60
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
scrollbarTag() {
|
||||
return this.$store.getters.scrollbarTag
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const scroll_el = this.$refs.chatLogPS.$el || this.$refs.chatLogPS
|
||||
scroll_el.scrollTop = this.$refs.chatLog.scrollHeight
|
||||
},
|
||||
created() {
|
||||
// Subscribers gained - Statistics
|
||||
this.$http.get('/api/card/card-statistics/subscribers')
|
||||
.then((response) => {
|
||||
this.subscribersGained = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Revenue Generated
|
||||
this.$http.get('/api/card/card-statistics/revenue')
|
||||
.then((response) => {
|
||||
this.revenueGenerated = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Sales
|
||||
this.$http.get('/api/card/card-statistics/sales')
|
||||
.then((response) => {
|
||||
this.quarterlySales = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Orders - Statistics
|
||||
this.$http.get('/api/card/card-statistics/orders')
|
||||
.then((response) => {
|
||||
this.ordersRecevied = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Revenue Comparison
|
||||
this.$http.get('/api/card/card-analytics/revenue-comparison')
|
||||
.then((response) => {
|
||||
this.revenueComparisonLine = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Goal Overview
|
||||
this.$http.get('/api/card/card-analytics/goal-overview')
|
||||
.then((response) => {
|
||||
this.goalOverview = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Browser Analytics
|
||||
this.$http.get('/api/card/card-analytics/browser-analytics')
|
||||
.then((response) => {
|
||||
this.browserStatistics = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Client Retention
|
||||
this.$http.get('/api/card/card-analytics/client-retention')
|
||||
.then((response) => {
|
||||
this.clientRetentionBar = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Sessions By Device
|
||||
this.$http.get('/api/card/card-analytics/session-by-device')
|
||||
.then((response) => {
|
||||
this.sessionsData = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Chat Log
|
||||
this.$http.get('/api/chat/demo-1/log')
|
||||
.then((response) => {
|
||||
this.chatLog = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Customers
|
||||
this.$http.get('/api/card/card-analytics/customers')
|
||||
.then((response) => {
|
||||
this.customersData = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.chat-card-log {
|
||||
height: 400px;
|
||||
|
||||
.chat-sent-msg {
|
||||
background-color: #f2f4f7 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,23 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-form-item :label="label">
|
||||
<a-input
|
||||
v-decorator="[this.key,{ rules: [{ required: true, message: 'asdads' }] },]"/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Inp",
|
||||
props: [
|
||||
'label',
|
||||
'key',
|
||||
'rules'
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,198 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: DashboardAnalytics.vue
|
||||
Description: Dashboard Analytics
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="dashboard-analytics">
|
||||
<XTable :model="tableModel"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueApexCharts from 'vue-apexcharts'
|
||||
import StatisticsCardLine from '@/components/statistics-cards/StatisticsCardLine.vue'
|
||||
import analyticsData from './ui-elements/card/analyticsData.js'
|
||||
import ChangeTimeDurationDropdown from '@/components/ChangeTimeDurationDropdown.vue'
|
||||
import VxTimeline from '@/components/timeline/VxTimeline'
|
||||
import XTable from "../components/x-table/XTable";
|
||||
import {default as TableModel} from './apps/customer/tableCustomer';
|
||||
// import * as TableModel from './apps/customer/tableCustomer';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tableModel: TableModel,
|
||||
checkpointReward: {},
|
||||
subscribersGained: {},
|
||||
ordersRecevied: {},
|
||||
salesBarSession: {},
|
||||
supportTracker: {},
|
||||
productsOrder: {},
|
||||
salesRadar: {},
|
||||
|
||||
timelineData: [
|
||||
{
|
||||
color: 'primary',
|
||||
icon: 'PlusIcon',
|
||||
title: 'Client Meeting',
|
||||
desc: 'Bonbon macaroon jelly beans gummi bears jelly lollipop apple',
|
||||
time: '25 mins Ago'
|
||||
},
|
||||
{
|
||||
color: 'warning',
|
||||
icon: 'MailIcon',
|
||||
title: 'Email Newsletter',
|
||||
desc: 'Cupcake gummi bears soufflé caramels candy',
|
||||
time: '15 Days Ago'
|
||||
},
|
||||
{
|
||||
color: 'danger',
|
||||
icon: 'UsersIcon',
|
||||
title: 'Plan Webinar',
|
||||
desc: 'Candy ice cream cake. Halvah gummi bears',
|
||||
time: '20 days ago'
|
||||
},
|
||||
{
|
||||
color: 'success',
|
||||
icon: 'LayoutIcon',
|
||||
title: 'Launch Website',
|
||||
desc: 'Candy ice cream cake. Halvah gummi bears Cupcake gummi bears soufflé caramels candy.',
|
||||
time: '25 days ago'
|
||||
},
|
||||
{
|
||||
color: 'primary',
|
||||
icon: 'TvIcon',
|
||||
title: 'Marketing',
|
||||
desc: 'Candy ice cream cake. Halvah gummi bears Cupcake gummi bears.',
|
||||
time: '28 days ago'
|
||||
}
|
||||
],
|
||||
|
||||
analyticsData,
|
||||
dispatchedOrders: []
|
||||
}
|
||||
},
|
||||
components: {
|
||||
XTable,
|
||||
VueApexCharts,
|
||||
StatisticsCardLine,
|
||||
ChangeTimeDurationDropdown,
|
||||
VxTimeline
|
||||
},
|
||||
created() {
|
||||
this.$http.get('/api/user/checkpoint-reward')
|
||||
.then((response) => {
|
||||
this.checkpointReward = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Subscribers gained - Statistics
|
||||
this.$http.get('/api/card/card-statistics/subscribers')
|
||||
.then((response) => {
|
||||
this.subscribersGained = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Orders - Statistics
|
||||
this.$http.get('/api/card/card-statistics/orders')
|
||||
.then((response) => {
|
||||
this.ordersRecevied = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Sales bar - Analytics
|
||||
this.$http.get('/api/card/card-analytics/sales/bar')
|
||||
.then((response) => {
|
||||
this.salesBarSession = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Support Tracker
|
||||
this.$http.get('/api/card/card-analytics/support-tracker')
|
||||
.then((response) => {
|
||||
this.supportTracker = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Products Order
|
||||
this.$http.get('/api/card/card-analytics/products-orders')
|
||||
.then((response) => {
|
||||
this.productsOrder = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Sales Radar
|
||||
this.$http.get('/api/card/card-analytics/sales/radar')
|
||||
.then((response) => {
|
||||
this.salesRadar = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Dispatched Orders
|
||||
this.$http.get('/api/table/dispatched-orders')
|
||||
.then((response) => {
|
||||
this.dispatchedOrders = response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/*! rtl:begin:ignore */
|
||||
#dashboard-analytics {
|
||||
.greet-user {
|
||||
position: relative;
|
||||
|
||||
.decore-left {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.decore-right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: 576px) {
|
||||
.decore-left, .decore-right {
|
||||
width: 140px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.text-white .ant-statistic-content {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.text-white .ant-statistic-title {
|
||||
color: rgba(255, 255, 255, 0.64);
|
||||
}
|
||||
|
||||
/*! rtl:end:ignore */
|
||||
</style>
|
||||
@@ -1,148 +0,0 @@
|
||||
<template>
|
||||
<a-form :form="form" @submit="handleSubmit">
|
||||
<vx-card title="دسترسی ها">
|
||||
<ASpin type="loading" :spinning="loading">
|
||||
<div class="grid grid-col-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 md:gap-2 xl:grid-cols-2 lg:gap-4 xl:gap-4">
|
||||
<a-form-item label="سطح کاربر">
|
||||
<a-select
|
||||
v-decorator="['user_type', { initialValue:null,rules: [{ required: true, message: 'لطفاسطح دسترسی را انتخاب کنید' }] }]" @change="selectChange">
|
||||
<a-select-option v-for="(item,key) in userTypes" :value="key">
|
||||
{{ item }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="نقش ها">
|
||||
<a-tree
|
||||
v-model="rid"
|
||||
checkable
|
||||
default-expand-all
|
||||
style="width: 100%"
|
||||
:tree-data="treeData"
|
||||
:replace-fields="replaceFields"
|
||||
:auto-expand-parent="autoExpandParent"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-button type="primary" html-type="submit">
|
||||
ذخیره
|
||||
</a-button>
|
||||
</ASpin>
|
||||
</vx-card>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "Access",
|
||||
data() {
|
||||
return {
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
expandedKeys:[],
|
||||
value: ['0-0-0'],
|
||||
treeData:undefined,
|
||||
userTypes: undefined,
|
||||
autoExpandParent: false,
|
||||
rid: [],
|
||||
replaceFields: {
|
||||
children: 'child',
|
||||
title: 'title'
|
||||
},
|
||||
keyId: null,
|
||||
getDataUserType:null
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async getPermission() {
|
||||
try{
|
||||
const {data} = await axios.get('admin/permission/rid')
|
||||
this.treeData = Object.values(data)
|
||||
}catch (e) {
|
||||
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try {
|
||||
values.rid = this.rid
|
||||
await this.$store.dispatch('access/save', values);
|
||||
this.$ntSet()
|
||||
// this.form.resetFields()
|
||||
} catch (e) {
|
||||
this.$ntSetError()
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
async getUserType() {
|
||||
const {data} = await axios.get('admin/user/type')
|
||||
this.userTypes = data
|
||||
console.log(this.userTypes,'user_type')
|
||||
},
|
||||
loadSyncOptionChange(){
|
||||
let storageId = localStorage.getItem("contestId");
|
||||
storageId = this.keyId;
|
||||
localStorage.setItem("contestId", storageId);
|
||||
let test = localStorage.getItem("contestId");
|
||||
test = JSON.parse(localStorage.getItem("contestId"));
|
||||
localStorage.setItem("contestId", test);
|
||||
if(test != null){
|
||||
this.$store.dispatch('access/getOneId',test).then(()=>{
|
||||
this.rid = this.data.rid
|
||||
this.form.setFieldsValue(this.data)
|
||||
})
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
},
|
||||
selectChange(id){
|
||||
this.keyId = id
|
||||
this.loadSyncOptionChange()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$store.state.access.loading;
|
||||
},
|
||||
data(){
|
||||
console.log(this.$store.state.access.access_id,'hgghgh')
|
||||
return this.$store.state.access.access_id
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getUserType()
|
||||
this.getPermission()
|
||||
this.keyId = 1
|
||||
this.loadSyncOptionChange()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
[dir=rtl] .ant-tree-checkbox-inner::after{
|
||||
right: 55%;
|
||||
top: 35%;
|
||||
border-left: 0 !important;
|
||||
-webkit-transform: rotate(-45deg) scale(0) translate(50%, -50%);
|
||||
transform: rotate(-45deg) scale(0) translate(50%, -50%);
|
||||
}
|
||||
[dir=rtl] .ant-tree-checkbox-checked .ant-tree-checkbox-inner::after{
|
||||
border-left: 0 !important;
|
||||
border-right: 2px solid #fff;
|
||||
}
|
||||
[dir=rtl] .ant-tree-checkbox-checked .ant-tree-checkbox-inner::after {
|
||||
border-left: 0 !important;
|
||||
border-right: 2px solid #fff;
|
||||
-webkit-transform: rotate(-45deg) scale(1) translate(50%, -50%);
|
||||
transform: rotate(25deg) scale(1) translate(50%, -50%);
|
||||
}
|
||||
</style>
|
||||
@@ -1,273 +0,0 @@
|
||||
<template>
|
||||
<a-form :form="form" :layout="formLayout" @submit="handleSubmit">
|
||||
<ASpin type="loading" :spinning="loading">
|
||||
<vx-card title="افزودن بسته آگهی">
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="عنوان">
|
||||
<a-input
|
||||
v-decorator="[`title`,{initialValue:null,rules: [{ required: true, message: 'واردکردن عنوان الزامی است.' }]}]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="توضیحات">
|
||||
<a-textarea
|
||||
v-decorator="[`description`,{initialValue:null,rules: [{ required: false, message: '' }] }]"
|
||||
autocomplete="off"
|
||||
:rows="4"
|
||||
:cols="50"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<div v-for="(item,index) in items" :key="index" :value="index">
|
||||
<div class="grid lg:grid-cols-5 sm:grid-cols-1 md:grid-cols-5 md:col-gap-2 lg:col-gap-6 row-gap-6">
|
||||
<a-col :span="8">
|
||||
<a-form-item>
|
||||
<a-checkbox v-model="item.isCheckCase" v-decorator="[`ip[${index}].active`,{initialValue:null,valuePropName:'checked',rules: [{ required: false}] }]">
|
||||
{{item.title}}
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<a-form-item v-show="item.isShow">
|
||||
<a-checkbox v-model="item.isChecked" v-decorator="[`ip[${index}].is_infinite`,{initialValue:false,rules: [{ required: false}] }]">
|
||||
نامحدود
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-form-item v-show="false">
|
||||
<a-input v-decorator="[`ip[${index}].ip_id`,{initialValue:item.ip_id}]"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="عنوان" :label-col="{ span: 7 }" >
|
||||
<a-input
|
||||
v-decorator="[`ip[${index}].title`,{rules: [{ required: false,message:'وارد کردن مقدار الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
width="200px"
|
||||
:disabled="!item.isCheckCase"
|
||||
ref="title"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="توضیحات" :label-col="{ span: 7 }">
|
||||
<a-input
|
||||
v-decorator="[`ip[${index}].description`,{ initialValue:null,rules: [{ required: false, message: '' }] }]"
|
||||
autocomplete="off"
|
||||
width="200px"
|
||||
:disabled="!item.isCheckCase"
|
||||
ref="description"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item :label="item.label">
|
||||
<a-input-number :min="1" :max="10000"
|
||||
:disabled="item.isShowCount || item.isChecked || !item.isCheckCase"
|
||||
ref="day"
|
||||
v-decorator="[`ip[${index}].total`,{ initialValue:null,rules: [{ required: false}] }]"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="مدت زمان">
|
||||
<a-input-number :min="1" :max="10000"
|
||||
ref="time"
|
||||
:disabled="item.isShowTime || item.isChecked || !item.isCheckCase"
|
||||
v-decorator="[`ip[${index}].time`,{ initialValue:null,rules: [{ required: false}] }]"/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="انتخاب رنگ بسته">
|
||||
<a-input type="color" v-decorator="['color',{ initialValue:null ,rules: [{ required: false }] }]"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<div class="item-date">
|
||||
<label style="white-space: nowrap;margin-left: 1em;margin-top: 0.3em;">مدت زمان فعال بودن:</label>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#ff9800"
|
||||
v-model="start_at"
|
||||
placeholder="تاریخ شروع"
|
||||
/>
|
||||
<p id="between-datepicker">
|
||||
تا
|
||||
</p>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#ff9800"
|
||||
v-model="end_at"
|
||||
placeholder="تاریخ پایان"
|
||||
/>
|
||||
</div>
|
||||
</a-row>
|
||||
<a-button type="primary" html-type="submit">ذخیره</a-button>
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import VuePersianDatetimePicker from 'vue-persian-datetime-picker'
|
||||
import * as moment from 'jalali-moment';
|
||||
|
||||
export default {
|
||||
name: "AddPackage",
|
||||
components:{
|
||||
datePicker: VuePersianDatetimePicker,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
labelCol: {span: 4},
|
||||
AdPackage: undefined,
|
||||
size: 4,
|
||||
formLayout: 'horizontal',
|
||||
isChecked:false,
|
||||
start_at:null,
|
||||
end_at:null,
|
||||
items: [
|
||||
{ip_id: 1,label:"تعداد", title: 'نردبان',isShow:false,isShowCount:false,isShowTime:true,isCheckCase:false},
|
||||
{ip_id: 2,label:"تعداد", title: 'فوری',isShow:true,isShowCount:false,isShowTime:true,isChecked:false,isCheckCase:false},
|
||||
{ip_id: 3,label:"تعداد", title: 'ارسال پیامک',isShow:false,isShowCount:true,isShowTime:true,isCheckCase:false},
|
||||
{ip_id: 4,label:"تعداد", title: 'استوری',isShow:false,isShowCount:false,isShowTime:true,isCheckCase:false},
|
||||
{ip_id: 5,label:"تعداد", title: ' تعداد تصاویر',isShow:false,isShowCount:false,isShowTime:true,isCheckCase:false},
|
||||
{ip_id: 6,label:"تعداد", title: 'ارسال پست',isShow:true,isShowCount:false,isShowTime:true,isChecked:false,isCheckCase:false},
|
||||
{ip_id: 7,label:"تعداد", title: 'مدت زمان تمدیدآگهی',isShow:false,isShowCount:false,isShowTime:true,isCheckCase:false},
|
||||
{ip_id: 8,label:"تعدادکلیک", title: 'ویترین آگهی',isShow:false,isShowCount:false,isShowTime:false,isCheckCase:false},
|
||||
{ip_id: 9,label:"تعدادکلیک",title: 'نمایش آگهی در وبلاگ',isShow:true,isShowCount:false,isShowTime:false,isChecked:false,isCheckCase:false},
|
||||
{ip_id: 10,label:"تعداد کلیک", title: 'آگهی ویژه',isShow:true,isShowCount:false,isShowTime:false,isChecked:false,isCheckCase:false},
|
||||
{ip_id: 11,label:"تعداد", title: 'درج لینک سایت',isShow:false,isShowCount:true,isShowTime:true,isCheckCase:false},
|
||||
{ip_id: 12,label:"تعداد", title: 'نمایش در آگهی مشابه',isShow:true,isShowCount:false,isShowTime:false,isChecked:false,isCheckCase:false},
|
||||
{ip_id: 13,label:"تعداد", title: 'ارسال ایمیل',isShow:false,isShowCount:true,isShowTime:true,isCheckCase:false},
|
||||
{ip_id: 14,label:"تعداد", title: 'مشاهده آمار بازدید',isShow:false,isShowCount:true,isShowTime:true,isCheckCase:false}
|
||||
],
|
||||
checkRef:['title','description','day','time']
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
const ip = values.ip.filter((elm) => elm.active);
|
||||
values.start_at = moment(this.start_at,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
values.end_at = moment(this.end_at,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
const exp = {
|
||||
...values,
|
||||
ip
|
||||
};
|
||||
if(this.$route.params.id){
|
||||
try {
|
||||
await this.$store.dispatch('adpackage/put',{
|
||||
id: this.$route.params.id,
|
||||
data: exp
|
||||
})
|
||||
this.$router.push('/ipc/list')
|
||||
this.form.resetFields()
|
||||
this.$ntSet();
|
||||
} catch ({message}) {
|
||||
this.$ntSetError();
|
||||
} finally {
|
||||
|
||||
}
|
||||
}else{
|
||||
try {
|
||||
await this.$store.dispatch('adpackage/save', exp)
|
||||
this.$router.push('/ipc/list')
|
||||
this.form.resetFields()
|
||||
this.$ntSet();
|
||||
} catch (e) {
|
||||
console.log(e.response)
|
||||
// console.log(message,'error')
|
||||
// this.$ntSetError(message);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
changeValCase(val){
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$store.state.adpackage.loading;
|
||||
},
|
||||
editAdById(){
|
||||
return this.$route.params && this.$route.params.id != undefined
|
||||
},
|
||||
data(){
|
||||
return this.$store.state.adpackage.AdOneId
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if(this.editAdById){
|
||||
this.$store.dispatch('adpackage/get',this.$route.params.id).then(()=>{
|
||||
const active = this.data.ip.filter(item=>item.active).find(el=>el.active)
|
||||
if(active.active){
|
||||
this.checkRef.forEach((item)=>{
|
||||
return this.$refs[item].disabled = false
|
||||
})
|
||||
}
|
||||
this.data.saj = `${this.data.saj}`
|
||||
this.data.eaj = `${this.data.eaj}`
|
||||
this.form.setFieldsValue(this.data)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
|
||||
@media (min-width: 940px ) {
|
||||
.item-display {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
column-gap: 0.5rem;
|
||||
}
|
||||
|
||||
.ant-row.ant-form-item[data-v-57741c72] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ant-col-8{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ant-select.ant-select-enabled {
|
||||
display: block !important
|
||||
}
|
||||
|
||||
.item-date {
|
||||
display: flex;
|
||||
justify-content: flex-end
|
||||
}
|
||||
|
||||
input[type="color"] {
|
||||
width: 100px !important;
|
||||
}
|
||||
|
||||
#between-datepicker {
|
||||
margin-top: 0.5rem;
|
||||
padding: 0 .5em;
|
||||
}
|
||||
|
||||
[dir] .ant-select-selection--single {
|
||||
cursor: pointer;
|
||||
width: 300px !important;
|
||||
}
|
||||
|
||||
.ant-select.ant-select-enabled[data-v-57741c72] {
|
||||
display: block !important;
|
||||
width: 300px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="لیست بسته های آگهی" class="mb-base">
|
||||
<XTable :model="model" ref="ipc">
|
||||
<span slot="active" slot-scope="text,active">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="text.record.active"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</span>
|
||||
<span slot="opt" slot-scope="text,record" :style="{display:'flex'}">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>ویرایش</span>
|
||||
</template>
|
||||
<feather-icon icon="EditIcon" @click="edit(text.record.id)" svgClasses="w-5 h-5 text-success" style="cursor: pointer"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>مشاهده</span>
|
||||
</template>
|
||||
<feather-icon icon="EyeIcon" @click="view(text.record.id)" svgClasses="w-5 h-5" style="cursor: pointer"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>حذف</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آیا می خواهید حذف کنید؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="okDelete(text.record.id,text.record)"
|
||||
>
|
||||
<feather-icon icon="TrashIcon" svgClasses="w-5 h-5 text-danger" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</XTable>
|
||||
<ASpin type="loading" :spinning="loading">
|
||||
<a-modal :width="1000" v-model="visible" title="مشاهده اطلاعات بسته آگهی" ok-text="تایید" cancel-text="ردکردن" :ok-button-props="{ props: { disabled: true } }" :cancel-button-props="{ props: { disabled: true } }">
|
||||
<div v-if="modalLoading">
|
||||
<ASkeleton />
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-descriptions id="ipshow">
|
||||
<a-descriptions-item label="عنوان">
|
||||
{{DataModal.title}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="توضیحات">
|
||||
{{DataModal.description}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="تاریخ شروع">
|
||||
{{ DataModal.start_at | jdate}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="امکان">
|
||||
<div v-for="item in DataModal.ip" v-if="DataModal.ip" style="margin-top: 1em">
|
||||
<ATag>
|
||||
<p>عنوان: {{item.title}}</p>
|
||||
<p>تعداد:{{item.total}}</p>
|
||||
<p>{{item.time}}زمان:</p>
|
||||
</ATag>
|
||||
</div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="تعداد">
|
||||
{{DataModal.total }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="تاریخ پایان">
|
||||
{{DataModal.end_at | jdate }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
</a-modal>
|
||||
</ASpin>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import XTable from '../../components/x-table/XTable'
|
||||
import * as TableCol from './tablePackage'
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "ListPackage",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
model: null,
|
||||
visible: false,
|
||||
modalLoading: false,
|
||||
DataModal:{},
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
view(id) {
|
||||
this.modalLoading = true;
|
||||
this.visible = true;
|
||||
this.getDtaModal(id);
|
||||
},
|
||||
async getDtaModal(id) {
|
||||
try {
|
||||
const {data} = await axios.get(`admin/ipc/${id}`)
|
||||
this.DataModal = data;
|
||||
} catch (e) {
|
||||
this.visible = false;
|
||||
} finally {
|
||||
this.modalLoading = false;
|
||||
}
|
||||
},
|
||||
async okDelete(id){
|
||||
try{
|
||||
await axios.delete(`/admin/ipc/${id}`)
|
||||
this.$refs.ipc.fetch()
|
||||
this.$ntSet('بسته آگهی باموفقیت حذف شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
edit(id){
|
||||
return this.$router.push(`/ipc/edit/${id}`)
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
loading() {
|
||||
return this.$store.state.shop.loading;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.model = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#ipshow span.ant-descriptions-item-content{
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(3,1fr);
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +0,0 @@
|
||||
import XTbl,{Xtc} from '../../components/new-x-table/index';
|
||||
const tbl = new XTbl('/admin/ipc/table', 'لسیت بسته ها');
|
||||
|
||||
tbl.add(new Xtc('title', 'نام بسته').filterText())
|
||||
tbl.add(new Xtc('active', 'وضعبت').filterSwitch().renderSlot('active'))
|
||||
tbl.add(new Xtc('description', 'توضیح').filterNumber())
|
||||
tbl.add(new Xtc('saj', 'تاریخ شروع').filterDate())
|
||||
tbl.add(new Xtc('eaj', 'تاریخ پایان').filterDate())
|
||||
tbl.add(new Xtc('opt', 'عملیات').noSort().renderSlot('opt'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-button class="editable-add-btn" @click="openAddAttrModal">
|
||||
افزودن ردیف
|
||||
</a-button>
|
||||
<a-table bordered :data-source="attributes" :columns="columns" style="margin-top: 1em">
|
||||
<template slot="op" slot-scope="text, record">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>ویرایش</span>
|
||||
</template>
|
||||
<feather-icon icon="EditIcon" @click="edit(record.id,record)" svgClasses="w-6 h-6 text-success" style="cursor: pointer"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر" @confirm="() => onDelete(record.id)">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<feather-icon icon="TrashIcon" svgClasses="h-6 w-6 text-danger" class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-table>
|
||||
<AdvAttributeModal ref="modalAttr" :visible.sync="visibleAdvAttrModal" :model="tempAttrModel" :id="id" @submit="handleAdd"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AdvAttributeModal from "./AdvAttributeModal";
|
||||
|
||||
class Attr {
|
||||
id = 0;
|
||||
title;
|
||||
type;
|
||||
value;
|
||||
editable = false;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "AdvAttributeComponent",
|
||||
components: {AdvAttributeModal},
|
||||
props: ['attributes','id','attr'],
|
||||
data(){
|
||||
return{
|
||||
visibleAdvAttrModal:false,
|
||||
tempAttrModel:undefined,
|
||||
columns: [
|
||||
{
|
||||
title: 'نام',
|
||||
dataIndex: 'title',
|
||||
customRender: (text, row, index)=>{
|
||||
console.log(text, row, index,'indexx')
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'نوع',
|
||||
dataIndex: 'attribute.type_str',
|
||||
},
|
||||
{
|
||||
title: 'مقدار',
|
||||
dataIndex: 'value',
|
||||
},
|
||||
{
|
||||
title: 'عملیات',
|
||||
dataIndex: 'op',
|
||||
scopedSlots: {customRender: 'op'},
|
||||
}
|
||||
],
|
||||
count: 0,
|
||||
editingKey:''
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
onDelete(id) {
|
||||
const dataSource = [...this.attributes];
|
||||
this.attributes = dataSource.filter(item => item.id !== id);
|
||||
},
|
||||
openAddAttrModal() {
|
||||
this.tempAttrModel = new Attr();
|
||||
this.visibleAdvAttrModal = true;
|
||||
this.$refs.modalAttr.getCollection()
|
||||
},
|
||||
handleAdd(newKey,newVal) {
|
||||
const {count} = this
|
||||
this.count = count + 1
|
||||
console.log(this.tempAttrModel,'newData')
|
||||
let newObj = Object.assign({},this.tempAttrModel)
|
||||
console.log(newObj,'newObj')
|
||||
this.attr[newKey] = newVal
|
||||
this.attributes = [...this.attributes, newObj ];
|
||||
console.log(this.attributes,'this.attributes')
|
||||
console.log(this.attr,'attr')
|
||||
// newObj.id = count
|
||||
this.$emit('handleAdd',this.attr);
|
||||
this.visibleAdvAttrModal = false;
|
||||
},
|
||||
handleChange(value, id, column) {
|
||||
console.log(column,'colllll')
|
||||
const newData = [...this.attributes];
|
||||
const target = newData.filter(item => id === item.id)[0];
|
||||
if (target) {
|
||||
target[column] = value;
|
||||
this.attributes = newData;
|
||||
}
|
||||
},
|
||||
edit(record,recording){
|
||||
console.log(recording,'record')
|
||||
this.tempAttrModel = record;
|
||||
const newData = [...this.attributes];
|
||||
const target = newData.filter(item => record === item.id)[0];
|
||||
this.editingKey = record;
|
||||
if (target) {
|
||||
target.editable = true;
|
||||
this.attributes = newData;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<!--var arr = [{key:"11", value:"1100"},{key:"22", value:"2200"}];-->
|
||||
<!--var object = arr.reduce(-->
|
||||
<!--(obj, item) => Object.assign(obj, { [item.key]: item.value }), {});-->
|
||||
<!--this.attributes = this.data.attributes.reduce((obj,item)=> Object.assign(obj, { [item.attribute_id]: item.value }),{});-->
|
||||
|
||||
<!--console.log(object)-->
|
||||
@@ -1,86 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<AModal v-model="visible" title="افزودن صفت" ok-text="تایید" cancel-text="رد">
|
||||
<AForm :form="form" @submit="submit">
|
||||
<AFormItem label="عنوان">
|
||||
<a-select v-model="model.title">
|
||||
<a-select-option v-for="item in collection" :value="item.attribute_id" v-if="item.attribute">
|
||||
{{ item.attribute.title }} , {{ item.attribute.type_str }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</AFormItem>
|
||||
|
||||
<AFormItem label="مقدار">
|
||||
<a-input
|
||||
v-model="model.value"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</AFormItem>
|
||||
<AFormItem>
|
||||
<a-button html-type="submit" type="primary">
|
||||
ثبت صفت
|
||||
</a-button>
|
||||
</AFormItem>
|
||||
<AFormItem v-if="model.editable">
|
||||
<a-input v-model="model.editable" v-show="false"/>
|
||||
</AFormItem>
|
||||
</AForm>
|
||||
</AModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "AdvAttributeModal",
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean
|
||||
},
|
||||
model: {
|
||||
default: {}
|
||||
},
|
||||
id:{
|
||||
type:Number
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
attrType:[
|
||||
{id:1, title:'input'},
|
||||
{id:2, title:'dropdown'},
|
||||
{id:3, title:'radio_button'},
|
||||
{id:4, title:'checkbox'},
|
||||
{id:5, title:'input_number'},
|
||||
{id:6, title:'category'},
|
||||
{id:7, title:'cheep'},
|
||||
{id:8, title:'email'},
|
||||
{id:9, title:'mobile'},
|
||||
{id:10, title:'phone'},
|
||||
{id:11, title:'price'},
|
||||
{id:12, title:'date'},
|
||||
{id:13, title:'slider'},
|
||||
{id:14, title:'other'}
|
||||
],
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
collection:null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit(e) {
|
||||
e.preventDefault()
|
||||
this.$emit('submit',this.model.title,this.model.value);
|
||||
},
|
||||
async getCollection(){
|
||||
const {data} = await axios.get(`site/collection/${this.id}`)
|
||||
this.collection = data.attributes
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,437 +0,0 @@
|
||||
<template>
|
||||
<a-form :form="form" @submit="handleSubmit">
|
||||
<a-spin type="loading" :spinning="loading">
|
||||
<vx-card title="ویرایش آگهی">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 md:gap-2 xl:grid-cols-2 lg:gap-4 xl:gap-4">
|
||||
<a-form-item label="عنوان آگهی">
|
||||
<a-input
|
||||
v-decorator="['title', { rules: [{ required: true, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="توضیحات آگهی">
|
||||
<a-textarea
|
||||
v-decorator="['body', { rules: [{ required: false, message: '' }] }]" autocomplete="off"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="همراه آگهی دهنده">
|
||||
<a-input
|
||||
v-decorator="['phone', { rules: [{ required: false, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
:disabled="true"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="همراه بازاریاب">
|
||||
<a-input
|
||||
v-decorator="['marketer.mobile', { rules: [{ required: false, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
:disabled="true"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="دسته">
|
||||
<a-tree-select
|
||||
v-decorator="['collection_id', { rules: [{ required: false, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
style="width: 100%"
|
||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
:tree-data="collection"
|
||||
placeholder=""
|
||||
tree-default-expand-all
|
||||
:replaceFields="replaceFields"
|
||||
@change="accessIdAdv"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="فروشگاه ثبت کننده">
|
||||
<a-input
|
||||
style="width: 100%"
|
||||
v-decorator="['store.title']" :disabled="true"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="تعداد بازدید">
|
||||
<a-input
|
||||
v-decorator="['view_count', { rules: [{ required: false, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
:disabled="true"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="شهر">
|
||||
<a-select
|
||||
show-search
|
||||
v-decorator="['city_id',{ rules: [{ required: true, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
option-filter-prop="children"
|
||||
:filter-option="filterOption"
|
||||
>
|
||||
<a-select-option v-for="(item, key, index) in cities" :value="key" :key="index">
|
||||
{{item.join(' , ')}}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="شماره نمایش داده شده در آگهی">
|
||||
<a-input
|
||||
v-decorator="['phone', { rules: [{ required: false, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
:disabled="true"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="تاریخ انقضا">
|
||||
<a-input
|
||||
v-decorator="['expired_at', { rules: [{ required: false, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
:disabled="true"
|
||||
/>
|
||||
<!-- <label></label>-->
|
||||
<!-- <date-picker-->
|
||||
<!-- :auto-submit="true"-->
|
||||
<!-- color="#ff9800"-->
|
||||
<!-- v-model="expired_at"-->
|
||||
<!-- style="margin-top: 0.5em"-->
|
||||
<!-- :initial-value="null"-->
|
||||
<!-- />-->
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-checkbox :disabled="true" v-decorator="['is_swap',{initialValue:false,valuePropName: 'checked'}]">
|
||||
تمایل به معاوضه
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-checkbox :disabled="true" v-decorator="['for_store',{initialValue:false,valuePropName: 'checked'}]">
|
||||
ثبت شده برای فروشگاه
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-checkbox :disabled="true" v-decorator="['for_other',{initialValue:false,valuePropName: 'checked'}]">
|
||||
ثبت آگهی برای شخص دیگر
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-checkbox :disabled="true" v-decorator="['active_chat',{valuePropName: 'checked'}]">
|
||||
فعال کردن چت
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<a-form-item label="برچسب ها">
|
||||
<TagCreator></TagCreator>
|
||||
</a-form-item>
|
||||
<!-- <a-checkbox @change="activeImage">تایید تصاویر</a-checkbox>-->
|
||||
<a-form-item label="تصاویر آگهی">
|
||||
<Xupload url="admin/file" v-model="images" @change="changeUploadImage"/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<AdvAttributeComponent :attributes="attributes" :attr="getAttr" :id="data.collection_id" @handleAdd="saveAttrTable"/>
|
||||
<a-button html-type="submit" type="primary" ghost style="margin-left: 3rem;margin-top: 1rem">
|
||||
ذخیره تغییرات
|
||||
</a-button>
|
||||
</vx-card>
|
||||
</a-spin>
|
||||
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from '@/axios'
|
||||
import AdvAttributeModal from "./AdvAttributeModal";
|
||||
import AdvAttributeComponent from "./AdvAttributeComponent";
|
||||
import AdvImagesComponent from "./AdvImagesComponent";
|
||||
import TagCreator from '../../components/tag-creator/TagCreator'
|
||||
import * as moment from 'jalali-moment';
|
||||
import Xupload from '../../components/x-upload/XUpload'
|
||||
export default {
|
||||
name: "adv-add",
|
||||
components: {
|
||||
AdvImagesComponent,
|
||||
AdvAttributeComponent,
|
||||
AdvAttributeModal,
|
||||
TagCreator,
|
||||
Xupload
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeConfirm:false,
|
||||
activeTitleBtn:false,
|
||||
activeImageBtn:false,
|
||||
attributes: [],
|
||||
collection: [],
|
||||
rejectReason: [],
|
||||
provinces: [],
|
||||
provinceCities: [],
|
||||
images: [],
|
||||
cities: [],
|
||||
stores: [],
|
||||
tags: [],
|
||||
visibleConfirmForm: false,
|
||||
cancelAdv: false,
|
||||
value: this.text,
|
||||
editable: false,
|
||||
tempAttrModel: undefined,
|
||||
count: 2,
|
||||
visibleAdvAttrModal: false,
|
||||
attr: {
|
||||
title: '',
|
||||
type: '',
|
||||
value: '',
|
||||
for_swap: ''
|
||||
},
|
||||
adv_for_other: true,
|
||||
adv_has_store: true,
|
||||
previewVisible: false,
|
||||
previewImage: '',
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
expired_at:'',
|
||||
replaceFields:{ children:'children', title:'title', key:'key', value: 'id' },
|
||||
receiveAttr:null,
|
||||
getAttr:null,
|
||||
collection_adv:null
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
saveAttrTable(value){
|
||||
console.log(value,'valuehjjjjj')
|
||||
this.receiveAttr = value
|
||||
},
|
||||
accessIdAdv(id){
|
||||
this.collection_adv = id
|
||||
},
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
try{
|
||||
const rec_attr = this.receiveAttr
|
||||
values.attributes = rec_attr
|
||||
console.log(rec_attr,'dfffffffffff')
|
||||
values.images = this.images
|
||||
this.$store.dispatch('advModel/save', {
|
||||
id: this.$route.params.id,
|
||||
data:values
|
||||
});
|
||||
this.$ntSet('عملیات با موفقیت انجام شد.')
|
||||
this.$router.push('/adv/list')
|
||||
}catch ({message}) {
|
||||
this.$ntSetError(message)
|
||||
}finally {
|
||||
|
||||
}
|
||||
// this.form.resetFields()
|
||||
}
|
||||
});
|
||||
this.visibleConfirmForm = false;
|
||||
},
|
||||
|
||||
activeTitle(e){
|
||||
this.activeTitleBtn = e.target.checked;
|
||||
if(this.activeTitleBtn === true && this.activeImageBtn === true){
|
||||
this.activeConfirm = true
|
||||
}
|
||||
else {
|
||||
this.activeConfirm = false
|
||||
}
|
||||
console.log('activeConfirm',this.activeConfirm);
|
||||
},
|
||||
|
||||
changeUploadImage(file){
|
||||
file.subject = 1
|
||||
file.alt = null
|
||||
file.description = null
|
||||
file.collection_id = this.collection_adv
|
||||
console.log(file,'fileeee')
|
||||
},
|
||||
|
||||
activeImage(e){
|
||||
this.activeImageBtn = e.target.checked;
|
||||
if(this.activeTitleBtn === true && this.activeImageBtn === true){
|
||||
this.activeConfirm = true
|
||||
}
|
||||
else {
|
||||
this.activeConfirm = false
|
||||
}
|
||||
console.log('activeConfirm',this.activeConfirm);
|
||||
},
|
||||
|
||||
cancellForm() {
|
||||
this.cancelAdv = true;
|
||||
},
|
||||
|
||||
async getCollection() {
|
||||
const {data} = await axios.get('admin/adv/collection')
|
||||
console.log(data,'collection')
|
||||
this.collection = data
|
||||
},
|
||||
|
||||
async getRejectReason() {
|
||||
await axios.get('admin/adv/reject')
|
||||
.then((res) => {
|
||||
console.log(res.data, 'rejectReason')
|
||||
return this.rejectReason = res.data
|
||||
})
|
||||
},
|
||||
|
||||
async getStores() {
|
||||
const {data} = await axios.get('admin/adv/store')
|
||||
this.stores = data
|
||||
},
|
||||
|
||||
async getCity() {
|
||||
const {data} = await axios.get('site/city');
|
||||
console.log(data,'city')
|
||||
this.cities = data;
|
||||
// this.provinces = new-x-table Set(Object.values(data).map((item) => item[0]));
|
||||
},
|
||||
|
||||
// async getCity() {
|
||||
// const {data} = await axios.get('site/city');
|
||||
// this.provinceCities = data;
|
||||
// this.provinces = new-x-table Set(Object.values(data).map((item) => item[0]));
|
||||
// },
|
||||
//
|
||||
// changeProvinces(value) {
|
||||
// let cities = [];
|
||||
// for (var i in this.provinceCities) {
|
||||
// if (this.provinceCities[i][0] == value) {
|
||||
// cities.push({id: i, title: this.provinceCities[i][1]});
|
||||
// }
|
||||
// }
|
||||
// this.form.setFieldsValue({city: undefined});
|
||||
// this.cities = cities;
|
||||
// },
|
||||
|
||||
successUpload() {
|
||||
console.log('ok')
|
||||
this.$vs.notify({color: 'success', title: 'Upload Success', text: 'Lorem ipsum dolor sit amet, consectetur'})
|
||||
},
|
||||
|
||||
addDomain() {
|
||||
this.dynamicValidateForm.domains.push({
|
||||
value: '',
|
||||
key: Date.now(),
|
||||
});
|
||||
},
|
||||
removeDomain(item) {
|
||||
let index = this.dynamicValidateForm.domains.indexOf(item);
|
||||
if (index !== -1) {
|
||||
this.dynamicValidateForm.domains.splice(index, 1);
|
||||
}
|
||||
},
|
||||
filterOption(input, option) {
|
||||
return (
|
||||
option.componentOptions.children[0].text.indexOf(input) >= 0
|
||||
)
|
||||
},
|
||||
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$store.state.advModel.loading;
|
||||
},
|
||||
editAdvById() {
|
||||
return this.$route.params && this.$route.params.id !== undefined
|
||||
},
|
||||
data() {
|
||||
console.log('this.$store.state.adv.collectionSingle', this.$store.state.advModel.collectionSingle);
|
||||
return this.$store.state.advModel.collectionSingle
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getCollection();
|
||||
this.getStores();
|
||||
this.getRejectReason();
|
||||
this.getCity();
|
||||
if (this.editAdvById) {
|
||||
this.$store.dispatch('advModel/advId', this.$route.params.id).then(() => {
|
||||
// this.data.tags = `${this.data.tags}`
|
||||
this.data.collection_id = `${this.data.collection_id}`
|
||||
this.data.city_id = `${this.data.city_id}`
|
||||
this.images = this.data.images;
|
||||
this.attributes = this.data.attributes
|
||||
this.getAttr = this.attributes.reduce((obj,item)=> Object.assign(obj,{[item.attribute_id]: item.value}),{});
|
||||
console.log(this.getAttr,'getAttr')
|
||||
this.form.setFieldsValue(this.data);
|
||||
this.tags = this.data.tags
|
||||
if (this.data.marketer_id !== null) {
|
||||
this.adv_for_other = true
|
||||
}
|
||||
if (this.data.store_id !== null) {
|
||||
this.adv_has_store = true
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@media (min-width: 940px) {
|
||||
.checkbox {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
[dir] .ant-form-item {
|
||||
margin-bottom: 0
|
||||
}
|
||||
}
|
||||
|
||||
.content-area__content {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-notification {
|
||||
z-index: 100000000 !important;
|
||||
}
|
||||
|
||||
.v-nav-menu .vs-sidebar {
|
||||
z-index: 1 !important;
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-checkbox-wrapper + .ant-checkbox-wrapper {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
.ant-checkbox-wrapper {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.ant-input-number {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.grow-space {
|
||||
padding: 0 10px
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-checkbox-wrapper + .ant-checkbox-wrapper[data-v-6c853ba7] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.birth-day{
|
||||
margin-top: .3em;
|
||||
}
|
||||
|
||||
.birth-day label{
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-checkbox-inner::after{
|
||||
right: 55%;
|
||||
top: 35%;
|
||||
border-left: 0 !important;
|
||||
-webkit-transform: rotate(-45deg) scale(0) translate(50%, -50%);
|
||||
transform: rotate(-45deg) scale(0) translate(50%, -50%);
|
||||
}
|
||||
[dir=rtl] .ant-tree-checkbox-checked .ant-tree-checkbox-inner::after{
|
||||
border-left: 0 !important;
|
||||
border-right: 2px solid #fff;
|
||||
}
|
||||
[dir=rtl] .ant-tree-checkbox-checked .ant-tree-checkbox-inner::after {
|
||||
border-left: 0 !important;
|
||||
border-right: 2px solid #fff;
|
||||
-webkit-transform: rotate(25deg) scale(1) translate(50%, -50%);
|
||||
transform: rotate(25deg) scale(1) translate(50%, -50%);
|
||||
}
|
||||
[dir=rtl] .ant-checkbox-checked .ant-checkbox-inner::after {
|
||||
border-right: 2px solid #fff;
|
||||
-webkit-transform: rotate(25deg) scale(1) translate(50%, -50%);
|
||||
transform: rotate(25deg) scale(1) translate(50%, -50%);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
<vx-card title="لیست درخواست های آگهی های منقضی شده" class="vx-card">
|
||||
<XTable
|
||||
:model="model">
|
||||
</XTable>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from './AdvExpiredListModel';
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
import axios from "@/axios";
|
||||
import XTable from "../../components/x-table/XTable";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
XTable,
|
||||
CustomerView,
|
||||
vSelect,
|
||||
FeatherIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
variantLoading: false,
|
||||
productLoading: false,
|
||||
variantPopup: false,
|
||||
model: null,
|
||||
components: {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.model = TableCol.default;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.ant-popover {
|
||||
z-index: 25000000;
|
||||
}
|
||||
</style>
|
||||
@@ -1,14 +0,0 @@
|
||||
import XTbl, {Xtc} from '../../components/x-table/index';
|
||||
|
||||
const tbl = new XTbl('/admin/request', 'لیست درخواست های آگهی های منقضی شده');
|
||||
|
||||
tbl.add(new Xtc('id', 'کد درخواست').filterNumber());
|
||||
tbl.add(new Xtc('customer.mobile', 'موبایل درخواست دهنده').filterText());
|
||||
tbl.add(new Xtc('adv_id', 'کد آگهی').filterNumber());
|
||||
tbl.add(new Xtc('adv.collection.title', 'دسته آگهی').filterText());
|
||||
tbl.add(new Xtc('adv.city', 'شهر آگهی').filterText());
|
||||
tbl.add(new Xtc('caj', 'تاریخ ثبت درخواست').filterDate());
|
||||
tbl.add(new Xtc('adv.owner.mobile', 'مالک اگهی').filterText());
|
||||
tbl.add(new Xtc('adv.marketer.mobile', 'بازاریاب آگهی').filterText());
|
||||
|
||||
export default tbl;
|
||||
@@ -1,104 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="img in model">
|
||||
<img :src="img.src">
|
||||
</div>
|
||||
<a-upload
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
list-type="picture-card"
|
||||
@preview="handlePreview"
|
||||
@change="handleChange"
|
||||
>
|
||||
<div v-if="fileList.length < 8">
|
||||
<a-icon type="plus"/>
|
||||
<div class="ant-upload-text">
|
||||
Upload
|
||||
</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
|
||||
<img alt="example" style="width: 100%" :src="previewImage"/>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
// function getBase64(file) {
|
||||
// return new-x-table Promise((resolve, reject) => {
|
||||
// const reader = new-x-table FileReader();
|
||||
// reader.readAsDataURL(file);
|
||||
// reader.onload = () => resolve(reader.result);
|
||||
// reader.onerror = error => reject(error);
|
||||
// });
|
||||
// }
|
||||
|
||||
export default {
|
||||
name: "AdvImagesComponent",
|
||||
props: {
|
||||
model: {
|
||||
default: []
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
previewVisible: false,
|
||||
previewImage: '',
|
||||
fileList: [
|
||||
{
|
||||
uid: '-1',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-2',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-3',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-4',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-5',
|
||||
name: 'image.png',
|
||||
status: 'error',
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCancel() {
|
||||
this.previewVisible = false;
|
||||
},
|
||||
async handlePreview(file) {
|
||||
if (!file.url && !file.preview) {
|
||||
file.preview = await getBase64(file.originFileObj);
|
||||
}
|
||||
this.previewImage = file.url || file.preview;
|
||||
this.previewVisible = true;
|
||||
},
|
||||
handleChange({fileList}) {
|
||||
this.fileList = fileList;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
console.log('images',this.model);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,495 +0,0 @@
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
<vx-card title="لیست آگهی های ثبت شده" class="vx-card">
|
||||
<XTable :model="model" ref="adv">
|
||||
<span slot="ad_adv" slot-scope="text,record">
|
||||
<span v-for="item in text.record.adv_ipc">
|
||||
{{ item.ipc.title }}
|
||||
</span>
|
||||
</span>
|
||||
<span slot="attr" slot-scope="text,record">
|
||||
<span v-for="item in text.record.attributes">
|
||||
<ATag>{{ item.title }}</ATag>
|
||||
</span>
|
||||
</span>
|
||||
<span slot="swap" slot-scope="text,record">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="text.record.is_swap"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</span>
|
||||
<span slot="active_adv" slot-scope="text,record">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="text.record.active"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</span>
|
||||
<span slot="lock" slot-scope="text,record">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="text.record.lock"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</span>
|
||||
<span slot="opt" slot-scope="text,record" class="flex space-x-2">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>نظارت</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آیا می خواهید آگهی تایید کنید؟"
|
||||
ok-text="تایید"
|
||||
cancel-text="رد"
|
||||
@confirm="okAdv(text.record.id)"
|
||||
@cancel="cancelAdv(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="EyeIcon" svgClasses="w-5 h-5 text-warning" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>فعالسازی آگهی</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آگهی مورد نظر فعال شود؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="okActiveAdv(text.record.id)"
|
||||
@cancel="cancelActiveAdv(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-primary" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>قفل آگهی</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="قفل آگهی مورد نظر باز شود؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="okLockAdv(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="LockIcon" svgClasses="w-5 h-5 text-success" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>حذف</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آیا می خواهید حذف کنید؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="okDelete(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="TrashIcon" svgClasses="w-5 h-5 text-danger" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>مشاهده آگهی</span>
|
||||
</template>
|
||||
<feather-icon icon="MonitorIcon" @click="viewAdv(text.record.id)" svgClasses="w-5 h-5" style="cursor: pointer"/>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</XTable>
|
||||
<a-modal v-model="visibleReasonReject" ok-text="ارسال" title="دلیل رد" :ok-button-props="{ props: { disabled: true } }" :cancel-button-props="{ props: { disabled: true } }">
|
||||
<a-form :form="formSuperVisionCancel" @submit="submitRejectAdv">
|
||||
<a-form-item label="دلیل رد">
|
||||
<a-radio-group v-decorator="['reject_reason',{ initialValue:null,rules: [{ required: false, message:'' }] }]">
|
||||
<a-radio v-for="item in radioGroupReason" :value="item">
|
||||
{{ item }}
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
<a-input
|
||||
v-decorator="['reject_reason', { rules: [{ required: true, message: 'لطفامقدار وارد کنید.' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button html-type="submit">
|
||||
ثبت
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
<a-modal :visible="visibleGetOneById" :width="1000" ok-text="ارسال" @cancel="cancelModalOneId">
|
||||
<div v-if="isGetData">
|
||||
<ASkeleton/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="getAdvOneId">
|
||||
<a-descriptions title="اطلاعات آگهی">
|
||||
<a-descriptions-item label="عنوان آگهی">
|
||||
{{ getAdvOneId.title }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="فعالسازی چت">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="getAdvOneId.active_chat"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="فعالسازی پیامک">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="getAdvOneId.active_sms"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="فعالسازی تلفن">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="getAdvOneId.active_phone"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="توضیحات آگهی">
|
||||
{{ getAdvOneId.body }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شماره موبایل ثبت کننده آگهی">
|
||||
{{ getAdvOneId.mobile }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="نام دسته آگهی">
|
||||
{{ getAdvOneId.collection.title }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="تاریخ ثبت آگهی">
|
||||
{{ getAdvOneId.caj }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
|
||||
<div class="flex">
|
||||
<div class="flex-initial" v-for="item in getAdvOneId.images" v-if="getAdvOneId.images">
|
||||
<img :src="item.src" alt="" width="200" height="200" class="object-cover"/>
|
||||
</div>
|
||||
<div class="flex-none" v-for="item in getAdvOneId.video" v-if="getAdvOneId.video">
|
||||
<video width="200" height="200" controls>
|
||||
<source :src="item.src" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div v-if="getAdvOneId.attributes.attribute.sounds">-->
|
||||
<!-- <div class="flex-initial" v-for="item in getAdvOneId.attributes.attribute.sounds">-->
|
||||
<!-- <audio :src="item.src" controls></audio>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
|
||||
<a-table :locale="{emptyText:'رکوردی وجود ندارد.'}" class="mt-5" :columns="columns" :data-source="getAdvOneId.attributes" bordered>
|
||||
<span slot="value" slot-scope="text,record">
|
||||
<span v-if="typeof text === 'string' ">
|
||||
<span v-if="text.includes('.jpg') || text.includes('.png') || text.includes('.jpeg')">
|
||||
<img :src="text" width="100" height="100" class="object-cover"/>
|
||||
</span>
|
||||
<span v-else-if="text.includes('.mp3') || text.includes('.ogg')">
|
||||
<audio controls>
|
||||
<source :src="text" type="audio/ogg">
|
||||
<source :src="text" type="audio/mpeg">
|
||||
</audio>
|
||||
</span>
|
||||
<span v-else-if="text.includes('.pdf')">
|
||||
<a :href="text" download>
|
||||
دانلودpdf
|
||||
</a>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ text }}
|
||||
</span>
|
||||
</span>
|
||||
<span v-else>
|
||||
<template v-for="item in text">
|
||||
<span v-if="item.includes('.jpg') || item.includes('.png') || item.includes('.jpeg') || item.includes('.webp')">
|
||||
<img :src="item" width="100" height="100" class="object-cover"/>
|
||||
</span>
|
||||
<span v-else>
|
||||
<a-tag>
|
||||
{{ item }}
|
||||
</a-tag>
|
||||
</span>
|
||||
</template>
|
||||
</span>
|
||||
</span>
|
||||
</a-table>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</a-modal>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from './AdvListModel';
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
import axios from "@/axios";
|
||||
import XTable from "../../components/x-table/XTable";
|
||||
import SendMsg from "../../components/SendMsg";
|
||||
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'نام صفت',
|
||||
dataIndex: 'title',
|
||||
},
|
||||
{
|
||||
title: 'مقادیر صفت ',
|
||||
dataIndex: 'value',
|
||||
scopedSlots: { customRender: 'value' },
|
||||
},
|
||||
{
|
||||
title: 'گروه صفت',
|
||||
dataIndex: 'attribute.group.title',
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SendMsg,
|
||||
XTable,
|
||||
CustomerView,
|
||||
vSelect,
|
||||
FeatherIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: null,
|
||||
interval:undefined,
|
||||
modelChangeCollection:null,
|
||||
tempRowId: undefined,
|
||||
radioGroupReason: undefined,
|
||||
collection:[],
|
||||
replaceFields:{ children:'children', title:'title', key:'id', value: 'id' },
|
||||
visibleReasonReject:false,
|
||||
formSuperVisionCancel: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
getAdvOneId:null,
|
||||
isGetData:true,
|
||||
visibleGetOneById:false,
|
||||
columns
|
||||
}
|
||||
},
|
||||
|
||||
methods:{
|
||||
|
||||
async okDelete(id){
|
||||
try{
|
||||
await axios.delete(`admin/adv/${id}`)
|
||||
this.$refs.adv.fetch()
|
||||
this.$ntSet('حذف با موفقیت انجام شد.')
|
||||
} catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
edit(id){
|
||||
this.$router.push(`/adv/edit/${id}`)
|
||||
},
|
||||
|
||||
send(id) {
|
||||
this.visibleSendMsg = true;
|
||||
this.tempRowId = id
|
||||
},
|
||||
|
||||
changeCategory(id){
|
||||
this.tempRowId = id
|
||||
this.visibleChangeCategory = true;
|
||||
this.getCollection();
|
||||
},
|
||||
|
||||
viewAdv(id){
|
||||
this.visibleGetOneById = true
|
||||
this.isGetData = true
|
||||
this.getOneIdAdv(id)
|
||||
},
|
||||
|
||||
async getOneIdAdv(id){
|
||||
try{
|
||||
const {data} = await axios.get(`admin/adv/${id}`)
|
||||
this.getAdvOneId = data
|
||||
}catch (e) {
|
||||
this.visibleGetOneById = false
|
||||
this.$ntSetError('خطا در دریافت اطلاعات')
|
||||
}finally {
|
||||
this.isGetData = false
|
||||
}
|
||||
},
|
||||
|
||||
cancelModal(){
|
||||
this.visibleChangeCategory = false;
|
||||
},
|
||||
|
||||
cancelModalOneId(){
|
||||
this.visibleGetOneById = false;
|
||||
},
|
||||
|
||||
monitoring(id){
|
||||
this.tempRowId = id
|
||||
this.visibleSuperVision = true
|
||||
},
|
||||
|
||||
confirmationAdv(){
|
||||
this.visibleSuperVisionOk = true
|
||||
},
|
||||
|
||||
rejectAdv(){
|
||||
this.visibleReasonReject = true
|
||||
this.getRadioButtonReason()
|
||||
},
|
||||
|
||||
getCollection(){
|
||||
axios.get('admin/adv/collection')
|
||||
.then((res)=>{
|
||||
return this.collection = res.data
|
||||
})
|
||||
},
|
||||
|
||||
async getRadioButtonReason(){
|
||||
try{
|
||||
const {data} = await axios.get('admin/adv/reason/reject')
|
||||
this.radioGroupReason = data
|
||||
}catch (e) {
|
||||
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
submitReasonDelete(e){
|
||||
e.preventDefault()
|
||||
const id = this.tempRowId
|
||||
this.form.validateFields(async(err, values) => {
|
||||
if (!err) {
|
||||
try{
|
||||
await axios.put(`admin/adv/delete/${id}`,{reason_delete:values.reason_delete})
|
||||
this.$refs.adv.fetch()
|
||||
this.form.resetFields()
|
||||
this.visibleReasonDelete = false
|
||||
this.$ntSet()
|
||||
}catch (e) {
|
||||
this.visibleReasonDelete = false
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
submitChangeCategory(e){
|
||||
e.preventDefault()
|
||||
const id = this.tempRowId
|
||||
this.formChangeCategory.validateFields(async (err, values) => {
|
||||
if(!err){
|
||||
try{
|
||||
await axios.put(`admin/adv/${id}`, {data:values,op:"collection"})
|
||||
this.$refs.adv.fetch()
|
||||
this.$ntSet('تغییردسته باموفقیت ثبت شد.')
|
||||
this.formChangeCategory.resetFields()
|
||||
this.visibleChangeCategory = false
|
||||
}catch (e) {
|
||||
this.visibleChangeCategory = false
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
async okAdv(id){
|
||||
try{
|
||||
await axios.put(`admin/adv/${id}`,{data:{sts:3},op:"sts"})
|
||||
this.$refs.adv.fetch()
|
||||
this.$ntSet('تاییدآگهی باموفقیت انجام شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
async okActiveAdv(id){
|
||||
try{
|
||||
await axios.put(`admin/adv/${id}`,{data:{active:true},op:"active"})
|
||||
this.$refs.adv.fetch()
|
||||
this.$ntSet('آگهی تایید شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
async cancelActiveAdv(id){
|
||||
try{
|
||||
await axios.put(`admin/adv/${id}`,{data:{active:false},op:"active"})
|
||||
this.$refs.adv.fetch()
|
||||
this.$ntSet('آگهی رد شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
async okLockAdv(id){
|
||||
try{
|
||||
await axios.put(`admin/adv/${id}`,{op:"lock"})
|
||||
this.$refs.adv.fetch()
|
||||
this.$ntSet('آگهی مورد نظر باز شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
cancelAdv(id){
|
||||
this.tempRowId = id
|
||||
this.visibleReasonReject = true
|
||||
},
|
||||
|
||||
submitRejectAdv(e){
|
||||
e.preventDefault()
|
||||
const id = this.tempRowId
|
||||
this.formSuperVisionCancel.validateFields(async (err, values) => {
|
||||
if(!err){
|
||||
try{
|
||||
await axios.put(`admin/adv/${id}`,{data:{reject_reason:values.reject_reason,sts:4},op:"sts"})
|
||||
this.$refs.adv.fetch()
|
||||
this.$ntSet('ردآگهی باموفقیت انجام شد.')
|
||||
this.formSuperVisionCancel.resetFields()
|
||||
this.visibleReasonReject = false
|
||||
}catch (e) {
|
||||
this.visibleReasonReject = false
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
disabledTitleParent(value){
|
||||
const item = this.collection.map(item=>item.title)
|
||||
console.log(value,'map')
|
||||
}
|
||||
},
|
||||
|
||||
created(){
|
||||
this.model = TableCol.default
|
||||
// this.interval = setInterval(()=>{
|
||||
// this.$refs.adv.fetch()
|
||||
// },10000)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.ant-popover {
|
||||
z-index: 25000000;
|
||||
}
|
||||
[dir=rtl] .ant-modal-footer{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -1,21 +0,0 @@
|
||||
import XTbl, {Xtc} from '../../components/x-table/index';
|
||||
|
||||
|
||||
const tbl = new XTbl('admin/adv/table', 'لیست آگهی های ثبت شده');
|
||||
tbl.add(new Xtc('title', 'عنوان آگهی').filterText());
|
||||
tbl.add(new Xtc('id', 'کد آگهی').filterText());
|
||||
tbl.add(new Xtc('collection.title', 'دسته آگهی').filterText());
|
||||
tbl.add(new Xtc('city', 'شهر').filterText());
|
||||
tbl.add(new Xtc('caj', 'تاریخ ثبت').filterDate());
|
||||
tbl.add(new Xtc('exaj', 'تاریخ انقضا').hidden().filterDate());
|
||||
tbl.add(new Xtc('marketer_phone', 'بازاریاب آگهی').hidden().filterText());
|
||||
tbl.add(new Xtc('owner.mobile', 'مالک').filterText().hidden());
|
||||
tbl.add(new Xtc('acceptor.name', 'ناظر').hidden().filterText());
|
||||
tbl.add(new Xtc('sts_str', 'وضعیت').filterSwitch());
|
||||
tbl.add(new Xtc('active', 'فعالسازی آگهی').filterSwitch().renderSlot('active_adv'));
|
||||
tbl.add(new Xtc('lock', 'قفل').filterSwitch().renderSlot('lock'));
|
||||
tbl.add(new Xtc('vaj', 'تاریخ نظارت').hidden().filterDate());
|
||||
tbl.add(new Xtc('price', 'قیمت آگهی').hidden().filterNumber());
|
||||
tbl.add(new Xtc('id', 'عملیات').noSort().renderSlot('opt'));
|
||||
|
||||
export default tbl;
|
||||
@@ -1,17 +0,0 @@
|
||||
import XTbl, {Xtc} from '../../components/x-table/index';
|
||||
|
||||
const tbl = new XTbl('/list/table', 'لیست آگهی های حذف شده');
|
||||
tbl.add(new Xtc('title', 'بازه زمانی').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'کد آگهی').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'ثبت کننده آگهی').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'مالک آگهی').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'گزارش دهنده آگهی').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'علت گزارش').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'توضیحات').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'دسته').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'شهر').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'ناظر').filterSwitch());
|
||||
tbl.add(new Xtc('title', 'عملیات').noSort());
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card title="لیست آگهی های حذف شده" class="vx-card">
|
||||
<XTable :model="model"></XTable>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from './AdvMaliciousListModel';
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
import axios from "@/axios";
|
||||
import XTable from "../../components/x-table/XTable";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
XTable,
|
||||
CustomerView,
|
||||
vSelect,
|
||||
FeatherIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.model = TableCol.default;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.ant-popover {
|
||||
z-index: 25000000;
|
||||
}
|
||||
</style>
|
||||
@@ -1,599 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<vx-card title="لیست آگهی های حذف شده">
|
||||
<div v-if="isSkeleton">
|
||||
<ASkeleton/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-table :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered :data-source="listAdvDelete" :columns="columns" style="margin-top: 1em">
|
||||
<template slot="thumb" slot-scope="text,record">
|
||||
<img :src="record.thumb" width="50" alt="" class="object-cover">
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</vx-card>
|
||||
<ASpin type="loading" :spinning="loadingOwnerMarketer">
|
||||
<vx-card title="تعداد آگهی های ثبت شده در شهرهای مختلف" style=" margin-top: 2rem">
|
||||
<a-form :form="formAdv" @submit="submitCountADv">
|
||||
<div class="grid sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-5 lg:gap-y-3">
|
||||
<div>
|
||||
<a-form-item>
|
||||
<a-input
|
||||
placeholder="تاریخ شروع"
|
||||
v-model="start_adv_city_at"
|
||||
id="start_at_city"
|
||||
style="width: 200px"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#4f72ab"
|
||||
v-model="start_adv_city_at"
|
||||
element="start_at_city"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<a-form-item>
|
||||
<a-input
|
||||
placeholder="تاریخ پایان"
|
||||
v-model="end_adv_city_at"
|
||||
id="end_at_city"
|
||||
style="width:200px"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#4f72ab"
|
||||
v-model="end_adv_city_at"
|
||||
element="end_at_city"
|
||||
/>
|
||||
</div>
|
||||
<a-form-item>
|
||||
<a-select
|
||||
placeholder="دسته ها"
|
||||
style="width: 200px"
|
||||
notFoundContent="رکوردی یافت نشد"
|
||||
v-decorator="['collection_id',{ rules: [{ required: true,message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
>
|
||||
<a-select-option v-for="(item,index) in collection" :value="item.id">
|
||||
{{ item.title }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-select
|
||||
placeholder="شهرها"
|
||||
style="width: 200px"
|
||||
notFoundContent="رکوردی یافت نشد"
|
||||
v-decorator="['city_id',{ rules: [{ required: true, message: 'لطفاشهرمورد نظر را انتخاب کنید' }] }]">
|
||||
<a-select-option v-for="(item,key) in getCity" :value="key">
|
||||
{{item[0]}}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-button type="primary" html-type="submit" class="w-2/5 ">
|
||||
بررسی
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
|
||||
<a-table :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered :data-source="countAdv" :columns="columnsCityDifferent" style="margin-top: 1em">
|
||||
<template slot="thumb" slot-scope="text,record">
|
||||
<img :src="record.thumb" width="50" alt="" class="object-cover">
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
<ASpin type="loading" :spinning="loadingSpecifiedDate">
|
||||
<vx-card title="تعداد آگهی های تایید شده دربازه ی زمانی مختلف" style="margin-top: 2rem">
|
||||
<a-form :form="form" layout="inline" @submit="handleSubmit">
|
||||
<div class="grid sm:gap-y-4 sm:grid-cols-1 md:flex md:space-x-4 lg:space-x-4">
|
||||
<div>
|
||||
<a-form-item>
|
||||
<a-input
|
||||
placeholder="تاریخ شروع"
|
||||
v-model="start_adv_submit_at"
|
||||
id="start_at_date_adv"
|
||||
style="width: 200px"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#4f72ab"
|
||||
v-model="start_adv_submit_at"
|
||||
element="start_at_date_adv"
|
||||
placeholder="تاریخ شروع"
|
||||
class="mt-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a-form-item>
|
||||
<a-input
|
||||
placeholder="تاریخ پایان"
|
||||
v-model="end_adv_submit_at"
|
||||
id="end_at_date_adv"
|
||||
style="width: 200px"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#4f72ab"
|
||||
v-model="end_adv_submit_at"
|
||||
element="end_at_date_adv"
|
||||
placeholder="تاریخ پایان"
|
||||
class="mt-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<a-button type="primary" html-type="submit" class="mt-1">
|
||||
بررسی
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div v-if="isShow">
|
||||
<apexchart height="400" type="line" :options="chartOptions" :series="series"></apexchart>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
<!-- line chart -->
|
||||
<ASpin type="loading" :spinning="loadingCompareAdv">
|
||||
<vx-card title="مقایسه مجموع آگهی هادر شهرهای مختلف" style="margin-top: 2rem">
|
||||
<a-form :form="formLine" @submit="lineSave" class="flex space-y-1 sm:space-y-2 grid sm:gap-y-4 sm:grid-cols-1 md:flex md:space-x-4">
|
||||
<div>
|
||||
<a-form-item>
|
||||
<a-input
|
||||
placeholder="تاریخ شروع"
|
||||
v-model="start_adv_sum_at"
|
||||
id="start_adv_sum_at"
|
||||
style="width: 200px"
|
||||
autocomplete="off"
|
||||
class="mt-3"
|
||||
/>
|
||||
</a-form-item>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#4f72ab"
|
||||
element="start_adv_sum_at"
|
||||
v-model="start_adv_sum_at"
|
||||
placeholder="تاریخ شروع"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<a-form-item>
|
||||
<a-input
|
||||
placeholder="تاریخ پایان"
|
||||
v-model="end_adv_sum_at"
|
||||
id="end_adv_submit_at"
|
||||
style="width: 200px"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#4f72ab"
|
||||
element="end_adv_submit_at"
|
||||
v-model="end_adv_sum_at"
|
||||
placeholder="تاریخ پایان"
|
||||
/>
|
||||
</div>
|
||||
<a-form-item>
|
||||
<a-select
|
||||
placeholder="دسته ها"
|
||||
style="width: 200px"
|
||||
notFoundContent="رکوردی یافت نشد"
|
||||
v-decorator="['collection_id',{ rules: [{ required: true,message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
>
|
||||
<a-select-option v-for="(item,index) in collection" :value="item.id">
|
||||
{{ item.title }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-button type="primary" html-type="submit">
|
||||
بررسی
|
||||
</a-button>
|
||||
</a-form>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div v-show="isShowLine">
|
||||
<apexchart height="400" type="bar" :options="lineChartOptions" :series="lineSeries"></apexchart>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
<vx-card title="تعداد آگهی حذف شده بر حسب دلایل حذف" style="margin-top: 2rem">
|
||||
<apexchart type="line" height="400" :options="AdvChartOption" :series="seriesChartAdv" class="mobile_overflow"></apexchart>
|
||||
</vx-card>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueApexCharts from 'vue-apexcharts'
|
||||
import axios from '@/axios'
|
||||
import VuePersianDatetimePicker from 'vue-persian-datetime-picker'
|
||||
import * as moment from 'jalali-moment';
|
||||
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'عنوان آگهی',
|
||||
dataIndex: 'title',
|
||||
},
|
||||
{
|
||||
title: 'شماره موبایل حذف کننده',
|
||||
dataIndex: 'mobile'
|
||||
},
|
||||
{
|
||||
title: 'دلیل حذف',
|
||||
dataIndex: 'reason_delete'
|
||||
},
|
||||
{
|
||||
title: 'عکس آگهی',
|
||||
dataIndex: 'thumb',
|
||||
scopedSlots: {customRender: 'thumb'}
|
||||
},
|
||||
{
|
||||
title: 'تاریخ حذف',
|
||||
dataIndex: 'uaj'
|
||||
},
|
||||
{
|
||||
title: 'شهر',
|
||||
dataIndex: 'city'
|
||||
},
|
||||
{
|
||||
title: 'دسته',
|
||||
dataIndex: 'collection.title'
|
||||
},
|
||||
]
|
||||
|
||||
const columnsCityDifferent = [
|
||||
{
|
||||
title: 'عنوان آگهی',
|
||||
dataIndex: 'title',
|
||||
},
|
||||
{
|
||||
title: 'شماره موبایل حذف کننده',
|
||||
dataIndex: 'mobile'
|
||||
},
|
||||
{
|
||||
title: 'دلیل حذف',
|
||||
dataIndex: 'caj'
|
||||
},
|
||||
{
|
||||
title: 'توضیحات آگهی',
|
||||
dataIndex: 'body'
|
||||
},
|
||||
{
|
||||
title: 'عکس آگهی',
|
||||
dataIndex: 'thumb',
|
||||
scopedSlots: {customRender: 'thumb'}
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: "ChartAdvertising",
|
||||
components:{
|
||||
apexchart:VueApexCharts,
|
||||
datePicker: VuePersianDatetimePicker
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
form:this.$form.createForm(this, {name: 'coordinated'}),
|
||||
formLine:this.$form.createForm(this, {name: 'coordinated'}),
|
||||
formDonut:this.$form.createForm(this, {name: 'coordinated'}),
|
||||
formAdv:this.$form.createForm(this, {name: 'coordinated'}),
|
||||
formgrwothAdv:this.$form.createForm(this, {name: 'coordinated'}),
|
||||
formCountAdv:this.$form.createForm(this, {name: 'coordinated'}),
|
||||
formCountOwnerMarketer:this.$form.createForm(this, {name: 'coordinated'}),
|
||||
isShowLine:false,
|
||||
isShowDonut:false,
|
||||
isShow:false,
|
||||
isShowGrowthAdv:false,
|
||||
collection:undefined,
|
||||
advChartCollection:undefined,
|
||||
chartOptions: {
|
||||
xaxis: {
|
||||
categories: []
|
||||
},
|
||||
},
|
||||
series: [{
|
||||
name: 'series-1',
|
||||
data: []
|
||||
}],
|
||||
lineChartOptions: {
|
||||
xaxis: {
|
||||
categories: []
|
||||
}
|
||||
},
|
||||
lineSeries: [{
|
||||
name: 'line',
|
||||
data: []
|
||||
}],
|
||||
donutChartOptions: {
|
||||
xaxis: {
|
||||
categories: []
|
||||
}
|
||||
},
|
||||
donutChartOptionsReasonDelete:{},
|
||||
donutSeriesReasonDelete: [],
|
||||
AdvChartOption: {
|
||||
xaxis: {
|
||||
categories: []
|
||||
}
|
||||
},
|
||||
donutSeries: [],
|
||||
seriesChartAdv: [{
|
||||
data:null
|
||||
}],
|
||||
listAdvDelete:undefined,
|
||||
getCity:undefined,
|
||||
countCountOwnerMarketer: 0,
|
||||
countAdv:0,
|
||||
conutAdvLastDays: 0,
|
||||
chartOptionsGrowthAdv:{},
|
||||
seriesGrowthAdv:[],
|
||||
start_at:null,
|
||||
start_adv_city_at:null,
|
||||
end_adv_city_at:null,
|
||||
start_adv_marketer_at:null,
|
||||
end_adv_marketer_at:null,
|
||||
start_adv_submit_at:null,
|
||||
end_adv_submit_at:null,
|
||||
start_adv_sum_at:null,
|
||||
end_adv_sum_at:null,
|
||||
start_adv_use_ad_at:null,
|
||||
end_adv_use_ad_at:null,
|
||||
start_adv_growth_at:null,
|
||||
end_adv_growth_at:null,
|
||||
columns,
|
||||
columnsCityDifferent,
|
||||
isSkeleton:false
|
||||
}
|
||||
},
|
||||
|
||||
methods:{
|
||||
async getCountAdPackage(){
|
||||
this.isSkeleton = true
|
||||
try{
|
||||
const {data} = await axios.post('admin/adv/list/delete');
|
||||
console.log(data,'dataadv');
|
||||
this.listAdvDelete = data.rows
|
||||
}catch (e) {
|
||||
console.log(e);
|
||||
}finally {
|
||||
this.isSkeleton = false
|
||||
}
|
||||
|
||||
},
|
||||
async getCityAdv(){
|
||||
const {data} = await axios.get('site/city');
|
||||
this.getCity = data
|
||||
},
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try{
|
||||
values.start_at = moment(this.start_adv_submit_at,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
values.end_at = moment(this.end_adv_submit_at,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
const data = await this.$store.dispatch('adv/save', values);
|
||||
const x = data.map((chart)=>moment(chart.date,'YYYY-M-D').format('jYYYY/jM/jD'));
|
||||
const y = data.map((chart)=>chart.total);
|
||||
this.series = [{
|
||||
data: y
|
||||
}]
|
||||
this.chartOptions = {
|
||||
colors: ['#4f72ab'],
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: x
|
||||
},
|
||||
bar: {
|
||||
dataLabels: {
|
||||
position: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 2000,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: "bottom"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.isShow = true
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
submitCountADv(e) {
|
||||
e.preventDefault();
|
||||
this.formAdv.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try{
|
||||
values.start_at = moment(this.start_adv_city_at,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
values.end_at = moment(this.end_adv_city_at,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
const data = await this.$store.dispatch('adv/countAdv', values);
|
||||
this.countAdv = data
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
lineSave(e) {
|
||||
e.preventDefault();
|
||||
this.formLine.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try{
|
||||
values.start_at = moment(this.start_adv_sum_at,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
values.end_at = moment(this.end_adv_sum_at,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
const data = await this.$store.dispatch('adv/line', values);
|
||||
const x = data.map((chart)=>chart.city ? chart.city : 'سایر شهرها' );
|
||||
const y = data.map((chart)=>chart.total);
|
||||
this.lineSeries = [{
|
||||
data: y
|
||||
}]
|
||||
this.lineChartOptions = {
|
||||
colors: ['#4f72ab'],
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: x
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 2000,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: "bottom"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.isShowLine = true
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
async getCollection(){
|
||||
const {data} = await axios.get('/admin/collection/parent')
|
||||
this.collection = data
|
||||
},
|
||||
async getAdvChartCollection(){
|
||||
const {data} = await axios.get('/admin/adv/query/delete')
|
||||
this.seriesChartAdv = [
|
||||
{
|
||||
name:"تعداد آگهی حذف شده",
|
||||
data: data.map((el)=>el.total)
|
||||
}
|
||||
]
|
||||
this.AdvChartOption={
|
||||
colors: ['#4f72ab'],
|
||||
xaxis: {
|
||||
categories: data.map(el=>el.reason_delete)
|
||||
},
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async getAdvChartReasonDelete(){
|
||||
const {data} = await axios.get('/admin/adv/chart/delete')
|
||||
const label = data.map((chart)=>{
|
||||
if(chart.reason_delete == null)
|
||||
chart.reason_delete = "سایر"
|
||||
|
||||
return chart.reason_delete
|
||||
});
|
||||
const y = data.map((chart)=>chart.total);
|
||||
this.donutChartOptionsReasonDelete = {
|
||||
labels: label,
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 2000,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: "bottom"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.donutSeriesReasonDelete = y
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
loadingSpecifiedDate() {
|
||||
return this.$store.state.adv.loadingSpecifiedDate;
|
||||
},
|
||||
loadingCompareAdv() {
|
||||
return this.$store.state.adv.loadingCompareAdv;
|
||||
},
|
||||
loadingUseAdvPackage() {
|
||||
return this.$store.state.adv.loadingUseAdvPackage;
|
||||
},
|
||||
loadingOwnerMarketer() {
|
||||
return this.$store.state.adv.loadingOwnerMarketer;
|
||||
},
|
||||
loadingGrowthAdv() {
|
||||
return this.$store.state.adv.loadingGrowthAdv;
|
||||
},
|
||||
loadingLastDaysAdv() {
|
||||
return this.$store.state.adv.loadingLastDaysAdv;
|
||||
},
|
||||
loadingAdvOwnerMarketer() {
|
||||
return this.$store.state.adv.loadingAdvOwnerMarketer;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getCollection()
|
||||
this.getAdvChartCollection()
|
||||
this.getAdvChartReasonDelete()
|
||||
this.getCountAdPackage()
|
||||
this.getCityAdv()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media(max-width: 1024px){
|
||||
.mobile_overflow{
|
||||
overflow-x: scroll;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,45 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="لیست دلایل حذف آگهی">
|
||||
<XTable :model="getColTable"></XTable>
|
||||
<a-descriptions>
|
||||
<a-descriptions-item>
|
||||
تعداد:{{count.count}}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import XTable from '../../components/x-table/XTable'
|
||||
import * as TableCol from './tableadvertising'
|
||||
import axios from "@/axios";
|
||||
|
||||
export default {
|
||||
name: "listAdvertising",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
getColTable: undefined,
|
||||
count:undefined
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
async getCountReasonAd(){
|
||||
const {data} = await axios.post('/admin/adv/delete')
|
||||
console.log(data,'data')
|
||||
this.count = data
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getCountReasonAd()
|
||||
this.getColTable = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,10 +0,0 @@
|
||||
import XTbl,{Xtc} from '../../components/x-table/index';
|
||||
const tbl = new XTbl('/admin/adv/delete', 'لیست دلایل حذف آگهی');
|
||||
|
||||
tbl.add(new Xtc('id', 'کدآگهی').filterText())
|
||||
tbl.add(new Xtc('reason_delete', 'دلیل حذف').filterText())
|
||||
tbl.add(new Xtc('uaj', 'تاریخ حذف').filterDate())
|
||||
tbl.add(new Xtc('removal_type', 'حذف کننده').filterSelect())
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,354 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<vx-card title="بیشترین گزارشات ثبت شده براساس شهرودسته" class="mobile-Chart">
|
||||
<apexchart width="1000" class="width_mobile_chart" height="400" type="bar" :options="chartOptions" :series="series"></apexchart>
|
||||
</vx-card>
|
||||
<vx-card title="نمودار دلایل گزارش آگهی" style="margin-top: 2rem">
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div >
|
||||
<apexchart ref="chartDonut" type="donut" :options="chartOptionsDonut" :series="seriesDonut"></apexchart>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</vx-card>
|
||||
<ASpin type="loading" :spinning="loading">
|
||||
<vx-card title="نمودارخطی أگهی های گزارش شده دربازه زمانی" style="margin-top: 2rem">
|
||||
<a-form :form="form" layout="inline" :wrapper-col="{ span: 24 }" @submit="lineSubmit">
|
||||
<a-form-item>
|
||||
<a-date-picker placeholder="تاریخ شروع" v-decorator="['start_at', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-date-picker placeholder="تاریخ پایان" v-decorator="['end_at', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"/>
|
||||
</a-form-item>
|
||||
<a-button type="primary" html-type="submit">
|
||||
بررسی
|
||||
</a-button>
|
||||
</a-form>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div v-if="isShow">
|
||||
<apexchart height="400" type="line" :options="chartOptionsLine" :series="seriesLine"></apexchart>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
<vx-card title="دلایل حذف آگهی" style="margin-top: 2rem">
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div>
|
||||
<apexchart type="donut" :options="chartOptionsDonutDeleteAdv" :series="seriesDonutDeleteAdv"></apexchart>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</vx-card>
|
||||
<vx-card title="گزارش دهنده های شاخص" style="margin-top: 2rem">
|
||||
<a-table :columns="columns" :data-source="reporterLow" bordered/>
|
||||
</vx-card>
|
||||
<vx-card title="ثبت کننده آگهی بابیشترین آگهی گزارش شده" style="margin-top: 2rem">
|
||||
<a-table :columns="columnsMaxReporter" :data-source="maxReporter" bordered/>
|
||||
</vx-card>
|
||||
<vx-card title="مالک آگهی بابیشترین آگهی گزارش شده" style="margin-top: 2rem">
|
||||
<a-table :columns="columnsMaxOwner" :data-source="ownerReporter" bordered/>
|
||||
</vx-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueApexCharts from 'vue-apexcharts'
|
||||
import axios from '@/axios'
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'نام',
|
||||
dataIndex: 'customer.name',
|
||||
key: '1',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
{
|
||||
title: 'موبایل',
|
||||
dataIndex: 'customer.mobile',
|
||||
key: '2'
|
||||
},
|
||||
{
|
||||
title: 'تعداد آگهی ثبت شده',
|
||||
dataIndex: 'total',
|
||||
key: '3'
|
||||
}
|
||||
]
|
||||
const columnsMaxReporter = [
|
||||
{
|
||||
title: 'نام',
|
||||
dataIndex: 'name',
|
||||
key: '1',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
{
|
||||
title: 'موبایل',
|
||||
dataIndex: 'mobile',
|
||||
key: '2'
|
||||
},
|
||||
{
|
||||
title: 'تعداد آگهی گزارش شده',
|
||||
dataIndex: 'count_bad_adv',
|
||||
key: '3'
|
||||
}
|
||||
]
|
||||
const columnsMaxOwner = [
|
||||
{
|
||||
title: 'نام',
|
||||
dataIndex: 'owner_adv.name',
|
||||
key: '1',
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
{
|
||||
title: 'موبایل',
|
||||
dataIndex: 'owner_adv.mobile',
|
||||
key: '2'
|
||||
},
|
||||
{
|
||||
title: 'تعداد آگهی ثبت شده',
|
||||
dataIndex: 'total',
|
||||
key: '3'
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: "ChartDestructiveAdv",
|
||||
components:{
|
||||
apexchart:VueApexCharts
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
columns,
|
||||
columnsMaxReporter,
|
||||
columnsMaxOwner,
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
isShow:false,
|
||||
reporterLow:[],
|
||||
maxReporter:undefined,
|
||||
ownerReporter:undefined,
|
||||
series:[{
|
||||
name:'sss',
|
||||
data:[]
|
||||
}],
|
||||
seriesDonut:[],
|
||||
seriesLine:[],
|
||||
seriesDonutDeleteAdv:[],
|
||||
chartOptionsDonut:{
|
||||
xaxis: {
|
||||
categories: []
|
||||
}
|
||||
},
|
||||
chartOptions:{
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: []
|
||||
}
|
||||
},
|
||||
chartOptionsLine:{
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: []
|
||||
}
|
||||
},
|
||||
chartOptionsDonutDeleteAdv:{}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
lineSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try{
|
||||
const data = await this.$store.dispatch('badadv/line', values);
|
||||
const x = data.map((chart)=>chart.date);
|
||||
const y = data.map((chart)=>chart.total);
|
||||
this.seriesLine = [{
|
||||
data: y
|
||||
}]
|
||||
this.chartOptionsLine = {
|
||||
colors: ['#FF9800'],
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: x
|
||||
},
|
||||
bar: {
|
||||
dataLabels: {
|
||||
position: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 2000,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: "bottom"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.isShow = true
|
||||
this.$ntSet()
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
async getBadAdvChartCityCollection(){
|
||||
const {data} = await axios.get('/admin/badadv/chart/compare')
|
||||
const x = data.map(chart=>chart.city)
|
||||
const y = data.map(chart=>chart.total)
|
||||
this.series=[{
|
||||
data: y
|
||||
}]
|
||||
this.chartOptions = {
|
||||
colors:['#FF9800'],
|
||||
xaxis: {
|
||||
categories: x,
|
||||
xAxis: {
|
||||
labels: {
|
||||
overflow: 'right',
|
||||
display: 'block',
|
||||
align: 'left',
|
||||
x: 5,
|
||||
style: {
|
||||
fontSize: '1em',
|
||||
color: '#000',
|
||||
width: '500px'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async getAdvChartCollection(){
|
||||
const {data} = await axios.get('/admin/badadv/chart/reason')
|
||||
const label = data.map(chart=>chart.title)
|
||||
const y = data.map(chart=>chart.total)
|
||||
this.seriesDonut = y
|
||||
this.chartOptionsDonut = {
|
||||
labels: label,
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 2000,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: "bottom"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
async getChartDeleteAdv(){
|
||||
try{
|
||||
const {data} = await axios.get('/admin/badadv/chart/delete')
|
||||
const label = data.map(chart=>{
|
||||
if(chart.reason_delete == null){
|
||||
chart.reason_delete = "سایر"
|
||||
}
|
||||
return chart.reason_delete
|
||||
|
||||
})
|
||||
const y = data.map(chart=>chart.total)
|
||||
this.seriesDonutDeleteAdv = y
|
||||
this.chartOptionsDonutDeleteAdv = {
|
||||
labels: label,
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 2000,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: "bottom"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}catch (e) {
|
||||
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
async getReporterLower(){
|
||||
const {data} = await axios.get('/admin/badadv/chart/count')
|
||||
this.reporterLow = data
|
||||
},
|
||||
async getMaxReporter(){
|
||||
const {data} = await axios.get('/admin/badadv/chart/creator')
|
||||
this.maxReporter = data
|
||||
},
|
||||
async getOwnerReporter(){
|
||||
const {data} = await axios.get('/admin/badadv/chart/owner')
|
||||
console.log(data,'data')
|
||||
this.ownerReporter = data
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$store.state.badadv.loading;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getBadAdvChartCityCollection()
|
||||
this.getAdvChartCollection()
|
||||
this.getChartDeleteAdv()
|
||||
this.getReporterLower()
|
||||
this.getMaxReporter()
|
||||
this.getOwnerReporter()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media(max-width:768px){
|
||||
.mobile-Chart{
|
||||
overflow-x: scroll;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,87 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="لیست آگهی های مخرب">
|
||||
<XTable :model="getColTable" ref="badAdv">
|
||||
<span slot="opt" slot-scope="text,record" class="flex space-x-2">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>فعالسازی آگهی</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آگهی مورد نظر غیر فعال شود؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="okActiveAdv(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="ActivityIcon" svgClasses="w-5 h-5 text-primary" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>حذف</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آیا می خواهید حذف کنید؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="okDelete(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="TrashIcon" svgClasses="w-5 h-5 text-danger" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span slot="adv_active" slot-scope="text,record" v-if="text.record.adv">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="text.record.adv.active"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</span>
|
||||
</XTable>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableDestructive'
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "LIstDestructive-adv",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
getColTable: undefined,
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
async okDelete(id){
|
||||
try{
|
||||
await axios.delete(`admin/badadv/${id}`)
|
||||
this.$refs.badAdv.fetch()
|
||||
this.$ntSet('حذف با موفقیت انجام شد.')
|
||||
} catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
async okActiveAdv(id){
|
||||
try{
|
||||
await axios.put(`admin/badadv/${id}`)
|
||||
this.$refs.badAdv.fetch()
|
||||
this.$ntSet()
|
||||
} catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getColTable = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import XTbl,{Xtc} from '../../../components/x-table/index';
|
||||
const tbl = new XTbl('/admin/badadv/table', 'لیست آگهی های مخرب');
|
||||
|
||||
tbl.add(new Xtc('caj', 'تاریخ ثبت').filterDate())
|
||||
tbl.add(new Xtc('owner_adv.mobile', 'مالک آگهی').filterText())
|
||||
tbl.add(new Xtc('customer.mobile', 'گزارش دهنده آگهی').filterText())
|
||||
tbl.add(new Xtc('title', 'علت گزارش').filterText())
|
||||
tbl.add(new Xtc('body', 'توضیحات').filterText())
|
||||
tbl.add(new Xtc('acceptor.name', 'ناظر').filterText())
|
||||
tbl.add(new Xtc('adv.active', 'وضعیت').filterSwitch().renderSlot('adv_active'))
|
||||
tbl.add(new Xtc('', 'عملیات').noSort().renderSlot('opt'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,324 +0,0 @@
|
||||
<template>
|
||||
<div id="simple-calendar-app">
|
||||
<div class="vx-card no-scroll-content">
|
||||
<calendar-view
|
||||
ref="calendar"
|
||||
:displayPeriodUom="calendarView"
|
||||
:show-date="showDate"
|
||||
:events="simpleCalendarEvents"
|
||||
enableDragDrop
|
||||
:eventTop="windowWidth <= 400 ? '2rem' : '3rem'"
|
||||
eventBorderHeight="0px"
|
||||
eventContentHeight="1.65rem"
|
||||
class="theme-default"
|
||||
@click-date="openAddNewEvent"
|
||||
@click-event="openEditEvent"
|
||||
@drop-on-date="eventDragged">
|
||||
|
||||
<div slot="header" class="mb-4">
|
||||
|
||||
<div class="vx-row no-gutter">
|
||||
|
||||
<!-- Month Name -->
|
||||
<div class="vx-col w-1/3 items-center sm:flex hidden">
|
||||
<!-- Add new-x-table event button -->
|
||||
<vs-button icon-pack="feather" icon="icon-plus" @click="promptAddNewEvent(new Date())">Add</vs-button>
|
||||
</div>
|
||||
|
||||
<!-- Current Month -->
|
||||
<div class="vx-col sm:w-1/3 w-full sm:my-0 my-3 flex sm:justify-end justify-center order-last">
|
||||
<div class="flex items-center">
|
||||
<feather-icon
|
||||
:icon="$vs.rtl ? 'ChevronRightIcon' : 'ChevronLeftIcon'"
|
||||
@click="updateMonth(-1)"
|
||||
svgClasses="w-5 h-5 m-1"
|
||||
class="cursor-pointer bg-primary text-white rounded-full" />
|
||||
|
||||
<span class="mx-3 text-xl font-medium whitespace-no-wrap">{{ showDate | month }}</span>
|
||||
|
||||
<feather-icon
|
||||
:icon="$vs.rtl ? 'ChevronLeftIcon' : 'ChevronRightIcon'"
|
||||
@click="updateMonth(1)"
|
||||
svgClasses="w-5 h-5 m-1"
|
||||
class="cursor-pointer bg-primary text-white rounded-full" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-col sm:w-1/3 w-full flex justify-center">
|
||||
<template v-for="(view, index) in calendarViewTypes">
|
||||
<vs-button
|
||||
v-if="calendarView === view.val"
|
||||
:key="String(view.val) + 'filled'"
|
||||
type="filled"
|
||||
class="p-3 md:px-8 md:py-3"
|
||||
:class="{'border-l-0 rounded-l-none': index, 'rounded-r-none': calendarViewTypes.length !== index+1}"
|
||||
@click="calendarView = view.val"
|
||||
>{{ view.label }}</vs-button>
|
||||
<vs-button
|
||||
v-else
|
||||
:key="String(view.val) + 'border'"
|
||||
type="border"
|
||||
class="p-3 md:px-8 md:py-3"
|
||||
:class="{'border-l-0 rounded-l-none': index, 'rounded-r-none': calendarViewTypes.length !== index+1}"
|
||||
@click="calendarView = view.val"
|
||||
>{{ view.label }}</vs-button>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-row sm:flex hidden mt-4">
|
||||
<div class="vx-col w-full flex">
|
||||
<!-- Labels -->
|
||||
<div class="flex flex-wrap sm:justify-start justify-center">
|
||||
<div v-for="(label, index) in calendarLabels" :key="index" class="flex items-center mr-4 mb-2">
|
||||
<div class="h-3 w-3 inline-block rounded-full mr-2" :class="'bg-' + label.color"></div>
|
||||
<span>{{ label.text }}</span>
|
||||
</div>
|
||||
<div class="flex items-center mr-4 mb-2">
|
||||
<div class="h-3 w-3 inline-block rounded-full mr-2 bg-primary"></div>
|
||||
<span>None</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</calendar-view>
|
||||
</div>
|
||||
|
||||
<!-- ADD EVENT -->
|
||||
<vs-prompt
|
||||
class="calendar-event-dialog"
|
||||
title="Add Event"
|
||||
accept-text= "Add Event"
|
||||
@accept="addEvent"
|
||||
:is-valid="validForm"
|
||||
:active.sync="activePromptAddEvent">
|
||||
|
||||
<div class="calendar__label-container flex">
|
||||
|
||||
<vs-chip v-if="labelLocal != 'none'" class="text-white" :class="'bg-' + labelColor(labelLocal)">{{ labelLocal }}</vs-chip>
|
||||
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="ml-auto my-2 cursor-pointer">
|
||||
|
||||
<feather-icon icon="TagIcon" svgClasses="h-5 w-5" class="cursor-pointer" @click.prevent></feather-icon>
|
||||
|
||||
<vs-dropdown-menu style="z-index: 200001">
|
||||
<vs-dropdown-item v-for="(label, index) in calendarLabels" :key="index" @click="labelLocal = label.value">
|
||||
<div class="h-3 w-3 inline-block rounded-full mr-2" :class="'bg-' + label.color"></div>
|
||||
<span>{{ label.text }}</span>
|
||||
</vs-dropdown-item>
|
||||
|
||||
<vs-dropdown-item @click="labelLocal = 'none'">
|
||||
<div class="h-3 w-3 mr-1 inline-block rounded-full mr-2 bg-primary"></div>
|
||||
<span>None</span>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
|
||||
</div>
|
||||
|
||||
<vs-input name="event-name" v-validate="'required'" class="w-full" label-placeholder="Event Title" v-model="title"></vs-input>
|
||||
<div class="my-4">
|
||||
<small class="date-label">Start Date</small>
|
||||
<datepicker :language="$vs.rtl ? langHe : langEn" name="start-date" v-model="startDate" :disabled="disabledFrom"></datepicker>
|
||||
</div>
|
||||
<div class="my-4">
|
||||
<small class="date-label">End Date</small>
|
||||
<datepicker :language="$vs.rtl ? langHe : langEn" :disabledDates="disabledDatesTo" name="end-date" v-model="endDate"></datepicker>
|
||||
</div>
|
||||
<vs-input name="event-url" v-validate="'url'" class="w-full mt-6" label-placeholder="Event URL" v-model="url" :color="!errors.has('event-url') ? 'success' : 'danger'"></vs-input>
|
||||
|
||||
</vs-prompt>
|
||||
|
||||
<!-- EDIT EVENT -->
|
||||
<vs-prompt
|
||||
class="calendar-event-dialog"
|
||||
title="Edit Event"
|
||||
accept-text= "Submit"
|
||||
cancel-text = "Remove"
|
||||
button-cancel = "border"
|
||||
@cancel="removeEvent"
|
||||
@accept="editEvent"
|
||||
:is-valid="validForm"
|
||||
:active.sync="activePromptEditEvent">
|
||||
|
||||
<div class="calendar__label-container flex">
|
||||
|
||||
<vs-chip v-if="labelLocal != 'none'" class="text-white" :class="'bg-' + labelColor(labelLocal)">{{ labelLocal }}</vs-chip>
|
||||
|
||||
<vs-dropdown vs-custom-content class="ml-auto my-2 cursor-pointer">
|
||||
|
||||
<feather-icon icon="TagIcon" svgClasses="h-5 w-5" @click.prevent></feather-icon>
|
||||
|
||||
<vs-dropdown-menu style="z-index: 200001">
|
||||
<vs-dropdown-item v-for="(label, index) in calendarLabels" :key="index" @click="labelLocal = label.value">
|
||||
<div class="h-3 w-3 inline-block rounded-full mr-2" :class="'bg-' + label.color"></div>
|
||||
<span>{{ label.text }}</span>
|
||||
</vs-dropdown-item>
|
||||
|
||||
<vs-dropdown-item @click="labelLocal = 'none'">
|
||||
<div class="h-3 w-3 mr-1 inline-block rounded-full mr-2 bg-primary"></div>
|
||||
<span>None</span>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
|
||||
</div>
|
||||
|
||||
<vs-input name="event-name" v-validate="'required'" class="w-full" label-placeholder="Event Title" v-model="title"></vs-input>
|
||||
<div class="my-4">
|
||||
<small class="date-label">Start Date</small>
|
||||
<datepicker :language="$vs.rtl ? langHe : langEn" :disabledDates="disabledDatesFrom" name="start-date" v-model="startDate"></datepicker>
|
||||
</div>
|
||||
<div class="my-4">
|
||||
<small class="date-label">End Date</small>
|
||||
<datepicker :language="$vs.rtl ? langHe : langEn" :disabledDates="disabledDatesTo" name="end-date" v-model="endDate"></datepicker>
|
||||
</div>
|
||||
<vs-input name="event-url" v-validate="'url'" class="w-full mt-6" label-placeholder="Event URL" v-model="url" :color="!errors.has('event-url') ? 'success' : 'danger'"></vs-input>
|
||||
|
||||
</vs-prompt>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { CalendarView, CalendarViewHeader } from 'vue-simple-calendar'
|
||||
import moduleCalendar from '@/store/calendar/moduleCalendar.js'
|
||||
require('vue-simple-calendar/static/css/default.css')
|
||||
|
||||
import Datepicker from 'vuejs-datepicker'
|
||||
import { en, he } from 'vuejs-datepicker/src/locale'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CalendarView,
|
||||
CalendarViewHeader,
|
||||
Datepicker
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showDate: new Date(),
|
||||
disabledFrom: false,
|
||||
id: 0,
|
||||
title: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
labelLocal: 'none',
|
||||
|
||||
langHe: he,
|
||||
langEn: en,
|
||||
|
||||
url: '',
|
||||
calendarView: 'month',
|
||||
|
||||
activePromptAddEvent: false,
|
||||
activePromptEditEvent: false,
|
||||
|
||||
calendarViewTypes: [
|
||||
{
|
||||
label: 'Month',
|
||||
val: 'month'
|
||||
},
|
||||
{
|
||||
label: 'Week',
|
||||
val: 'week'
|
||||
},
|
||||
{
|
||||
label: 'Year',
|
||||
val: 'year'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
simpleCalendarEvents () {
|
||||
return this.$store.state.calendar.events
|
||||
},
|
||||
validForm () {
|
||||
return this.title !== '' && this.startDate !== '' && this.endDate !== '' && Date.parse(this.endDate) - Date.parse(this.startDate) >= 0 && !this.errors.has('event-url')
|
||||
},
|
||||
disabledDatesTo () {
|
||||
return { to: new Date(this.startDate) }
|
||||
},
|
||||
disabledDatesFrom () {
|
||||
return { from: new Date(this.endDate) }
|
||||
},
|
||||
calendarLabels () {
|
||||
return this.$store.state.calendar.eventLabels
|
||||
},
|
||||
labelColor () {
|
||||
return (label) => {
|
||||
if (label === 'business') return 'success'
|
||||
else if (label === 'work') return 'warning'
|
||||
else if (label === 'personal') return 'danger'
|
||||
else if (label === 'none') return 'primary'
|
||||
}
|
||||
},
|
||||
windowWidth () {
|
||||
return this.$store.state.windowWidth
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addEvent () {
|
||||
const obj = { title: this.title, startDate: this.startDate, endDate: this.endDate, label: this.labelLocal, url: this.url }
|
||||
obj.classes = `event-${ this.labelColor(this.labelLocal)}`
|
||||
this.$store.dispatch('calendar/addEvent', obj)
|
||||
},
|
||||
updateMonth (val) {
|
||||
this.showDate = this.$refs.calendar.getIncrementedPeriod(val)
|
||||
},
|
||||
clearFields () {
|
||||
this.title = this.endDate = this.url = ''
|
||||
this.id = 0
|
||||
this.labelLocal = 'none'
|
||||
},
|
||||
promptAddNewEvent (date) {
|
||||
this.disabledFrom = false
|
||||
this.addNewEventDialog(date)
|
||||
},
|
||||
addNewEventDialog (date) {
|
||||
this.clearFields()
|
||||
this.startDate = date
|
||||
this.endDate = date
|
||||
this.activePromptAddEvent = true
|
||||
},
|
||||
openAddNewEvent (date) {
|
||||
this.disabledFrom = true
|
||||
this.addNewEventDialog(date)
|
||||
},
|
||||
openEditEvent (event) {
|
||||
const e = this.$store.getters['calendar/getEvent'](event.id)
|
||||
this.id = e.id
|
||||
this.title = e.title
|
||||
this.startDate = e.startDate
|
||||
this.endDate = e.endDate
|
||||
this.url = e.url
|
||||
this.labelLocal = e.label
|
||||
this.activePromptEditEvent = true
|
||||
},
|
||||
editEvent () {
|
||||
const obj = { id: this.id, title: this.title, startDate: this.startDate, endDate: this.endDate, label: this.labelLocal, url: this.url }
|
||||
obj.classes = `event-${ this.labelColor(this.labelLocal)}`
|
||||
this.$store.dispatch('calendar/editEvent', obj)
|
||||
},
|
||||
removeEvent () {
|
||||
this.$store.dispatch('calendar/removeEvent', this.id)
|
||||
},
|
||||
eventDragged (event, date) {
|
||||
this.$store.dispatch('calendar/eventDragged', {event, date})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.$store.registerModule('calendar', moduleCalendar)
|
||||
this.$store.dispatch('calendar/fetchEvents')
|
||||
this.$store.dispatch('calendar/fetchEventLabels')
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$store.unregisterModule('calendar')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/apps/simple-calendar.scss";
|
||||
</style>
|
||||
@@ -1,530 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-form :form="form" @submit="handleSubmit">
|
||||
<a-spin type="loading" :spinning="loading">
|
||||
<vx-card :title="!this.$route.params.id ? 'افزودن دسته':'ویرایش دسته' ">
|
||||
<div class="grid grid-col-1 sm:grid-cols-1 md:grid-cols-4 lg:grid-cols-5 md:gap-2 xl:grid-cols-5 lg:gap-4 xl:gap-4">
|
||||
<a-form-item label="نام دسته">
|
||||
<a-input
|
||||
v-decorator="['title',{rules: [{ required: true, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="ناظران دسته">
|
||||
<a-select
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
:disabled="inputDisabled"
|
||||
placeholder="ناظران دسته"
|
||||
notFoundContent="رکوردی یافت نشد"
|
||||
option-filter-prop="children"
|
||||
:filter-option="filterOption"
|
||||
v-decorator="['supervisors',{ initialValue:[] ,rules: [{ required: false }] }]"
|
||||
>
|
||||
<a-select-option v-for="(item,index) in collection" :value="item.id" :key="index">
|
||||
{{ item.name }} , {{ item.mobile }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="پدر دسته">
|
||||
<a-select
|
||||
option-filter-prop="children"
|
||||
:filter-option="filterOption"
|
||||
show-search
|
||||
allowClear
|
||||
notFoundContent="رکوردی یافت نشد"
|
||||
style="width: 100%"
|
||||
v-decorator="['parent_id',{ initialValue:null ,rules: [{ required: false }] }]"
|
||||
>
|
||||
<a-select-option v-for="(item,index) in manegerCollection" :value="item.id" :key="index">
|
||||
{{ item.title }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="عنوان فرعی">
|
||||
<a-input
|
||||
v-decorator="['sub_title',{ initialValue: editCollectionById ? data.sub_title : null ,rules: [{ required: false, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="عنوان تخصیص به امور خیریه">
|
||||
<a-input
|
||||
v-decorator="['titleـpayment',{ initialValue: editCollectionById ? data.sub_title : null ,rules: [{ required: false, message: 'واردکردن دسته الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<a-form-item label="انتخاب آیکون" class="flex-initial">
|
||||
<Xupload url="admin/file" @change="changeUploadImage" @input="iconChange"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="توضیحات دسته" class="flex-initial w-full">
|
||||
<a-textarea
|
||||
v-decorator="['meta', { initialValue:null,rules: [{ required: false}] }]"
|
||||
autocomplete="off"
|
||||
:disabled="inputDisabled"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<a-button class="editable-add-btn" @click="AddRowGroups">
|
||||
افزودن ردیف
|
||||
</a-button>
|
||||
<a-table :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered :data-source="editCollectionById ? data.groups: groups " :columns="columns" style="margin-top: 1em">
|
||||
<template slot="for_comment" slot-scope="text,record">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="text"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</template>
|
||||
<template slot="op" slot-scope="text, record">
|
||||
<a-tooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر"
|
||||
@confirm="() => onDelete(record)">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<feather-icon icon="TrashIcon" svgClasses="h-6 w-6 text-danger"
|
||||
class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-table>
|
||||
<div class="checkbox_group">
|
||||
<div class="checkbox grid sm:grid-cols-1 sm:gap-0 md:grid-cols-4 lg:grid-cols-4">
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['free_adv',{initialValue:false,valuePropName: 'checked'}]">
|
||||
آگهی رایگان
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has_in_menu',{initialValue:false,valuePropName: 'checked'}]">
|
||||
نمایش در دسته بندی ها
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox
|
||||
v-decorator="['has_same_adv',{initialValue:false,valuePropName: 'checked'}]">
|
||||
نمایش آگهی های مشابه
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has_comment',{initialValue:false,valuePropName: 'checked'}]">
|
||||
امکان نظر دادن
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox
|
||||
v-decorator="['has_comment_attribute',{initialValue:false,valuePropName: 'checked'}]">
|
||||
امکان نظر سنجی محدود
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has_lta',{initialValue:false,valuePropName: 'checked'}]">
|
||||
خبرم کن
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has_flower',{initialValue:false,valuePropName: 'checked'}]">
|
||||
تاج گل
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has_payment',{initialValue:false,valuePropName: 'checked'}]">
|
||||
نیاز به پرداخت دارد
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has_pdf',{initialValue:false,valuePropName: 'checked'}]">
|
||||
نیاز به فایل pdf
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has_title',{initialValue:false,valuePropName: 'checked'}]">
|
||||
نیاز به عنوان دارد
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has_repeat',{initialValue:false,valuePropName: 'checked'}]">
|
||||
نیاز به تکرار دارد
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['has-payment-charity',{initialValue:false,valuePropName: 'checked'}]">
|
||||
تخصیص هزینه به امور خیریه قرار بگیرد
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-decorator="['for_charity',{initialValue:false,valuePropName: 'checked'}]">
|
||||
این دسته صرفا برای خیریه باشد
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<a-button v-if="this.$route.params.id" type="primary" html-type="submit">
|
||||
ویرایش دسته
|
||||
</a-button>
|
||||
<a-button v-else type="primary" html-type="submit">
|
||||
ذخیره
|
||||
</a-button>
|
||||
</vx-card>
|
||||
</a-spin>
|
||||
</a-form>
|
||||
|
||||
|
||||
<a-modal v-model="visible" title="افزودن صفت" ok-text="تایید" cancel-text="رد">
|
||||
<a-form :form="formGroups" @submit.prevent="submit">
|
||||
<a-form-item label="گروه صفت">
|
||||
<a-select style="width: 100%" v-model="tempRow.group_attribute_id" notFoundContent="رکوردی یافت نشد">
|
||||
<a-select-option v-for="item in groupCollection" :value="item.id">
|
||||
{{ item.title }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-model="tempRow.for_comment">
|
||||
نظرات داشته باشد
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="وزن">
|
||||
<a-input v-model="tempRow.w">
|
||||
وزن
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-button html-type="submit" type="primary">
|
||||
ثبت صفت
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapActions} from 'vuex';
|
||||
import axios from '@/axios';
|
||||
import VuePersianDatetimePicker from 'vue-persian-datetime-picker';
|
||||
import Xupload from '../../../components/x-upload/XUpload';
|
||||
|
||||
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'گروه صفت',
|
||||
dataIndex: 'group.title',
|
||||
},
|
||||
{
|
||||
title: 'کامنت',
|
||||
dataIndex: 'for_comment',
|
||||
scopedSlots: {customRender: 'for_comment'},
|
||||
},
|
||||
{
|
||||
title: 'وزن',
|
||||
dataIndex: 'w',
|
||||
},
|
||||
{
|
||||
title: 'عملیات',
|
||||
dataIndex: 'op',
|
||||
scopedSlots: {customRender: 'op'},
|
||||
}
|
||||
];
|
||||
|
||||
export default {
|
||||
name: "add-group",
|
||||
components: {
|
||||
datePicker: VuePersianDatetimePicker,
|
||||
Xupload
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
date: '',
|
||||
file: null,
|
||||
number2: 50,
|
||||
collection: [],
|
||||
manegerCollection: null,
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
formGroups: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
inputDisabled: false,
|
||||
visible: false,
|
||||
tempRowId: null,
|
||||
tempRow: {},
|
||||
count: 1,
|
||||
titleSelected: null,
|
||||
valueSelected: null,
|
||||
fileList: [],
|
||||
groupCollection: [],
|
||||
img_src: null,
|
||||
icon_src: null,
|
||||
groups: [],
|
||||
columns,
|
||||
subtitle: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
...mapActions('collection', [
|
||||
'submitCollection'
|
||||
]),
|
||||
onDelete(record) {
|
||||
if(this.editCollectionById){
|
||||
this.$store.commit('collection/DELETE_ROW', this.data.groups.indexOf(record));
|
||||
}else{
|
||||
const delete_row = this.groups.indexOf(record)
|
||||
this.groups.splice(delete_row,1)
|
||||
}
|
||||
},
|
||||
changeUploadImage(file) {
|
||||
file.has_watermark = true;
|
||||
file.has_thumb = false;
|
||||
file.business_card = false;
|
||||
file.subject = null;
|
||||
file.alt = null;
|
||||
file.description = null;
|
||||
},
|
||||
cancel() {
|
||||
this.visible = false;
|
||||
},
|
||||
isSubTitle(value){
|
||||
if(value) this.subtitle = true
|
||||
},
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
if (this.$route.params.id) {
|
||||
try {
|
||||
values.icon = this.icon_src;
|
||||
values.thumb = this.img_src;
|
||||
values.groups = this.data.groups;
|
||||
await this.$store.dispatch('collection/submitCollection', {
|
||||
id: this.$route.params.id,
|
||||
data: values
|
||||
});
|
||||
console.log('555 ===> ', 555);
|
||||
this.$router.push('/category/list');
|
||||
this.form.resetFields();
|
||||
this.$ntSet();
|
||||
} catch (e) {
|
||||
console.log(e.response);
|
||||
this.$ntSetError();
|
||||
} finally {
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
if (!values.groups) values.groups = [] ;
|
||||
values.groups = this.groups;
|
||||
values.icon = this.icon_src;
|
||||
values.thumb = this.img_src;
|
||||
await this.submitCollection(values);
|
||||
this.$router.push('/category/list');
|
||||
this.form.resetFields();
|
||||
this.$ntSet();
|
||||
} catch (e) {
|
||||
console.log(e.response);
|
||||
this.$ntSetError();
|
||||
} finally {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
async getCollection() {
|
||||
try {
|
||||
const {data} = await axios.get('admin/collection/user');
|
||||
console.log(data, 'datass');
|
||||
this.collection = data;
|
||||
} catch (e) {
|
||||
|
||||
} finally {
|
||||
|
||||
}
|
||||
},
|
||||
async getFatherCollection() {
|
||||
try {
|
||||
const {data} = await axios.get('admin/collection/parent');
|
||||
console.log(data);
|
||||
this.manegerCollection = data;
|
||||
} catch (e) {
|
||||
|
||||
} finally {
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
async groupCollections() {
|
||||
try {
|
||||
const {data} = await axios.get('admin/collection/group');
|
||||
console.log(data, 'datassss');
|
||||
this.groupCollection = data;
|
||||
} catch (e) {
|
||||
|
||||
} finally {
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
successUpload() {
|
||||
console.log('ok');
|
||||
this.$vs.notify({
|
||||
color: 'success',
|
||||
title: 'Upload Success',
|
||||
text: 'Lorem ipsum dolor sit amet, consectetur'
|
||||
});
|
||||
},
|
||||
imgChange(src) {
|
||||
this.img_src = src;
|
||||
},
|
||||
iconChange(src) {
|
||||
this.icon_src = src;
|
||||
},
|
||||
filterOption(input, option) {
|
||||
return (
|
||||
option.componentOptions.children[0].text.indexOf(input) >= 0
|
||||
);
|
||||
},
|
||||
AddRowGroups() {
|
||||
this.visible = true;
|
||||
this.tempRow = {};
|
||||
this.groupCollections();
|
||||
},
|
||||
submit() {
|
||||
try {
|
||||
this.tempRow.group = this.groupCollection[this.tempRow.group_attribute_id] || {};
|
||||
if(this.editCollectionById){
|
||||
this.$store.commit('collection/SET_ROW_ATTR', this.tempRow);
|
||||
}else{
|
||||
this.groups.push(this.tempRow)
|
||||
}
|
||||
this.formGroups.resetFields();
|
||||
this.visible = false;
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
},
|
||||
isShowSubtitle(){
|
||||
if(this.data['parent_id']) this.subtitle = true
|
||||
else this.subtitle = false
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$store.state.collection.loading;
|
||||
},
|
||||
editCollectionById() {
|
||||
return this.$route.params && this.$route.params.id != undefined;
|
||||
},
|
||||
data() {
|
||||
return this.$store.state.collection.collectionSingle;
|
||||
},
|
||||
isResultTrue() {
|
||||
return this.$store.state.collection.successData;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getCollection();
|
||||
this.getFatherCollection();
|
||||
if (this.editCollectionById) {
|
||||
this.$store.dispatch('collection/collectionId', this.$route.params.id).then(() => {
|
||||
this.isShowSubtitle()
|
||||
this.data.sub_title = this.data.sub_title == "null" ? this.data.sub_title = '' : this.data.sub_title
|
||||
// this.data.title_payment = this.data.title_payment=="null" ? `${this.data.title_payment}` : ''
|
||||
this.form.setFieldsValue(this.data);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
[dir=rtl] .ant-modal-footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 940px) {
|
||||
.checkbox {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
[dir] .ant-form-item {
|
||||
margin-bottom: 0
|
||||
}
|
||||
}
|
||||
|
||||
.content-area__content {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-notification {
|
||||
z-index: 100000000 !important;
|
||||
}
|
||||
|
||||
.v-nav-menu .vs-sidebar {
|
||||
z-index: 1 !important;
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-checkbox-wrapper + .ant-checkbox-wrapper {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
.ant-checkbox-wrapper {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-checkbox-checked .ant-checkbox-inner::after {
|
||||
border-left: 0 !important;
|
||||
-webkit-transform: rotate(45deg) scale(1) translate(-100%, -25%) !important;
|
||||
transform: rotate(45deg) scale(1) translate(-100%, -25%) !important;
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-checkbox-checked .ant-checkbox-inner::after {
|
||||
-webkit-transform: rotate(-45deg) scale(1) translate(50%, -50%);
|
||||
transform: rotate(-45deg) scale(1) translate(50%, -50%);
|
||||
}
|
||||
|
||||
.ant-input-number {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.grow-space {
|
||||
padding: 0 10px
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-checkbox-wrapper + .ant-checkbox-wrapper[data-v-6c853ba7] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-table .ant-table-row-indent + .ant-table-row-expand-icon{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
[dir=rtl] .ant-checkbox-inner::after {
|
||||
right: 18%;
|
||||
top: 42%;
|
||||
border-left: 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import XTbl, {Xtc} from '../../../components/x-table';
|
||||
|
||||
const tbl = new XTbl('/admin/collection/attribute', '');
|
||||
|
||||
tbl.add(new Xtc('title', 'نام صفت'));
|
||||
tbl.add(new Xtc('value', 'مقادیر').renderSlot('values'));
|
||||
tbl.add(new Xtc('required', 'ورود الزامی').renderSlot('required'));
|
||||
tbl.add(new Xtc('show_thumb', 'نمایش بندانگشت').renderSlot('show_thumb'));
|
||||
tbl.add(new Xtc('show_lta', 'نمایش گوش به زنگ').renderSlot('show_lta'));
|
||||
tbl.add(new Xtc('show_filter', 'نمایش در فبلتر').renderSlot('show_filter'));
|
||||
tbl.add(new Xtc('show_exchange', 'معاوضه').renderSlot('show_exchange'));
|
||||
tbl.add(new Xtc('opt', 'عملیات').noSort().renderSlot('opt'));
|
||||
|
||||
export default tbl;
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<template>
|
||||
<Add/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Add from "./Add";
|
||||
export default {
|
||||
components: {
|
||||
Add
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,266 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card
|
||||
ref="filterCard"
|
||||
refresh-content-action
|
||||
:removeCardAction="false"
|
||||
@refresh="fetch"
|
||||
title="لیست دسته بندی ها" class="vx-card">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="flex flex-wrap items-center mb-4">
|
||||
|
||||
|
||||
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
|
||||
<div class="flex-1">
|
||||
<a-input class="md:w-1/2" @keyup.enter="fetch" v-model="searchQuery" placeholder="جستجو">
|
||||
<a-icon slot="prefix" type="search"/>
|
||||
</a-input>
|
||||
</div>
|
||||
|
||||
<AButton type="primary" class="mr-6" @click="()=>$router.push({name:'category-add'})">افزودن دسته</AButton>
|
||||
<a-dropdown-button>
|
||||
عملیات
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="2">
|
||||
خروجی اکسل
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown-button>
|
||||
</div>
|
||||
<VsDivider/>
|
||||
|
||||
<AModal :visible.sync="detailsPopup" @cancel="()=>detailsPopup = false" :zIndex="410000" width="80%"
|
||||
:footer="null">
|
||||
<div>
|
||||
<h2>مشاهده اطلاعات </h2>
|
||||
<ASkeleton/>
|
||||
</div>
|
||||
</AModal>
|
||||
|
||||
<ATable
|
||||
class="p-0 m-0"
|
||||
:pagination="false"
|
||||
:locale="{emptyText:'داده ای یافت نشد'}"
|
||||
:columns="cols" :data-source="data">
|
||||
|
||||
<div slot="gold" slot-scope="data">
|
||||
<FeatherIcon icon="ArrowDownIcon" class="text-danger" svgClasses="w-4 h-4"/>
|
||||
{{data}}
|
||||
</div>
|
||||
<div slot="rial" slot-scope="data">
|
||||
<FeatherIcon icon="ArrowDownIcon" class="text-danger" svgClasses="w-4 h-4"/>
|
||||
{{data}}
|
||||
</div>
|
||||
<div slot="price" slot-scope="data">
|
||||
{{data | priceUnit}}
|
||||
</div>
|
||||
<div slot="ojrat" slot-scope="data">
|
||||
{{data | priceUnit}}
|
||||
</div>
|
||||
<div slot="op" slot-scope="data, row">
|
||||
<ATooltip>
|
||||
<span slot="title">ویرایش</span>
|
||||
<FeatherIcon icon="EditIcon" @click="toEdit(row)" svgClasses="h-6 w-6 text-primary"
|
||||
class="cursor-pointer mx-1"/>
|
||||
</ATooltip>
|
||||
<ATooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر" @confirm="confirmDelete(row.id)">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="h-6 w-6 text-danger" class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</ATooltip>
|
||||
</div>
|
||||
</ATable>
|
||||
<vs-pagination
|
||||
class="mt-4"
|
||||
:total="totalPages"
|
||||
:max="7"
|
||||
v-model="currentPage"/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
// Store Module
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
// Cell Renderer
|
||||
import CellRendererLink from '../user/user-list/cell-renderer/CellRendererLink.vue'
|
||||
import CellRendererStatus from '../user/user-list/cell-renderer/CellRendererStatus.vue'
|
||||
import CellRendererVerified from '../user/user-list/cell-renderer/CellRendererVerified.vue'
|
||||
import CellRendererActions from '../user/user-list/cell-renderer/CellRendererActions.vue'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from "@/table/category";
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CustomerView,
|
||||
vSelect,
|
||||
// Cell Renderer
|
||||
FeatherIcon,
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Filter Options
|
||||
filterType: 'all',
|
||||
filterSts: 'all',
|
||||
detailsPopup: false,
|
||||
typeOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'کیفی', value: 'active'},
|
||||
{label: 'عمده ای', value: 'deactivated'},
|
||||
{label: 'تک فروشی', value: 'blocked'}
|
||||
],
|
||||
statusOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'فعال', value: 'active'},
|
||||
{label: 'غیر فعال', value: 'deactivated'}
|
||||
],
|
||||
// AgGrid
|
||||
gridApi: null,
|
||||
cols: null,
|
||||
gridOptions: {},
|
||||
defaultColDef: {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
suppressMenu: true
|
||||
},
|
||||
// Cell Renderer Components
|
||||
components: {
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleFilter(obj) {
|
||||
this.setColumnFilter('role', obj.value)
|
||||
},
|
||||
statusFilter(obj) {
|
||||
this.setColumnFilter('status', obj.value)
|
||||
},
|
||||
isVerifiedFilter(obj) {
|
||||
const val = obj.value === 'all' ? 'all' : obj.value === 'yes' ? 'true' : 'false'
|
||||
this.setColumnFilter('is_verified', val)
|
||||
},
|
||||
departmentFilter(obj) {
|
||||
this.setColumnFilter('department', obj.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
usersData() {
|
||||
return this.$store.state.userManagement.users
|
||||
},
|
||||
data() {
|
||||
return this.$store.state.category.rows;
|
||||
},
|
||||
paginationPageSize() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetPageSize()
|
||||
else return 10
|
||||
},
|
||||
totalPages() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetTotalPages()
|
||||
else return 0
|
||||
},
|
||||
currentPage: {
|
||||
get() {
|
||||
// if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1
|
||||
return 1
|
||||
},
|
||||
set(val) {
|
||||
// this.gridApi.paginationGoToPage(val - 1)
|
||||
}
|
||||
},
|
||||
searchQuery: {
|
||||
get() {
|
||||
return this.$store.state.category.searchQuery;
|
||||
},
|
||||
set(val) {
|
||||
this.$store.commit('category/SEARCH_QUERY_SET', val);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setColumnFilter(column, val) {
|
||||
const filter = this.gridApi.getFilterInstance(column)
|
||||
let modelObj = null
|
||||
|
||||
if (val !== 'all') {
|
||||
modelObj = {type: 'equals', filter: val}
|
||||
}
|
||||
|
||||
filter.setModel(modelObj)
|
||||
this.gridApi.onFilterChanged()
|
||||
},
|
||||
toEdit(row) {
|
||||
this.$router.push({name: 'category-edit', params: {id: row.id}})
|
||||
},
|
||||
async confirmDelete(id) {
|
||||
try {
|
||||
await this.$store.dispatch('category/remove', {id});
|
||||
console.log("id ==> ", id);
|
||||
this.$ntSet();
|
||||
} catch (e) {
|
||||
this.$ntSetError();
|
||||
console.log("e ==> ", e);
|
||||
throw e;
|
||||
} finally {
|
||||
console.log("id ==> ", id);
|
||||
}
|
||||
},
|
||||
resetColFilters() {
|
||||
this.$refs.filterCard.removeRefreshAnimation()
|
||||
},
|
||||
async fetch() {
|
||||
try {
|
||||
this.$refs.filterCard.visibleAnimation();
|
||||
return this.$store.dispatch('category/fetch');
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this.$refs.filterCard.removeRefreshAnimation();
|
||||
}
|
||||
},
|
||||
updateSearchQuery(val) {
|
||||
this.gridApi.setQuickFilter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cols = TableCol.default;
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('category/fetch');
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,249 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: Chat.vue
|
||||
Description: Chat Application - Stay connected
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div id="chat-app" class="border border-solid d-theme-border-grey-light rounded relative overflow-hidden">
|
||||
<vs-sidebar class="items-no-padding" parent="#chat-app" :click-not-close="clickNotClose" :hidden-background="clickNotClose" v-model="isChatSidebarActive" id="chat-list-sidebar">
|
||||
|
||||
<!-- USER PROFILE SIDEBAR -->
|
||||
<user-profile :active="activeProfileSidebar" :userId="userProfileId" class="user-profile-container" :isLoggedInUser="isLoggedInUserProfileView" @closeProfileSidebar="closeProfileSidebar"></user-profile>
|
||||
|
||||
<div class="chat__profile-search flex p-4">
|
||||
<div class="relative inline-flex">
|
||||
<vs-avatar v-if="activeUser.photoURL" class="m-0 border-2 border-solid border-white" :src="activeUser.photoURL" size="40px" @click="showProfileSidebar(Number(activeUser.uid), true)" />
|
||||
<div class="h-3 w-3 border-white border border-solid rounded-full absolute right-0 bottom-0" :class="'bg-' + getStatusColor(true)"></div>
|
||||
</div>
|
||||
<vs-input icon-no-border icon="icon-search" icon-pack="feather" class="w-full mx-5 input-rounded-full" placeholder="Search or start a new chat" v-model="searchQuery"/>
|
||||
|
||||
<feather-icon class="md:inline-flex lg:hidden -ml-3 cursor-pointer" icon="XIcon" @click="toggleChatSidebar(false)" />
|
||||
</div>
|
||||
|
||||
<vs-divider class="d-theme-border-grey-light m-0" />
|
||||
<component :is="scrollbarTag" class="chat-scroll-area pt-4" :settings="settings" :key="$vs.rtl">
|
||||
|
||||
<!-- ACTIVE CHATS LIST -->
|
||||
<div class="chat__chats-list mb-8">
|
||||
<h3 class="text-primary mb-5 px-4">Chats</h3>
|
||||
<ul class="chat__active-chats bordered-items">
|
||||
<li class="cursor-pointer" v-for="(contact, index) in chatContacts" :key="index" @click="updateActiveChatUser(contact.uid)">
|
||||
<chat-contact showLastMsg :contact="contact" :lastMessaged="chatLastMessaged(contact.uid).time" :unseenMsg="chatUnseenMessages(contact.uid)" :isActiveChatUser="isActiveChatUser(contact.uid)"></chat-contact>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- CONTACTS LIST -->
|
||||
<div class="chat__contacts">
|
||||
<h3 class="text-primary mb-5 px-4">Contacts</h3>
|
||||
<ul class="chat__contacts bordered-items">
|
||||
<li class="cursor-pointer" v-for="contact in contacts" :key="contact.uid" @click="updateActiveChatUser(contact.uid)">
|
||||
<chat-contact :contact="contact"></chat-contact>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</component>
|
||||
</vs-sidebar>
|
||||
|
||||
<!-- RIGHT COLUMN -->
|
||||
<div class="chat__bg no-scroll-content chat-content-area border border-solid d-theme-border-grey-light border-t-0 border-r-0 border-b-0" :class="{'sidebar-spacer--wide': clickNotClose, 'flex items-center justify-center': activeChatUser === null}">
|
||||
<template v-if="activeChatUser">
|
||||
<div class="chat__navbar">
|
||||
<chat-navbar :isSidebarCollapsed="!clickNotClose" :user-id="activeChatUser" :isPinnedProp="isChatPinned" @openContactsSidebar="toggleChatSidebar(true)" @showProfileSidebar="showProfileSidebar" @toggleIsChatPinned="toggleIsChatPinned"></chat-navbar>
|
||||
</div>
|
||||
<component :is="scrollbarTag" class="chat-content-scroll-area border border-solid d-theme-border-grey-light" :settings="settings" ref="chatLogPS" :key="$vs.rtl">
|
||||
<div class="chat__log" ref="chatLog">
|
||||
<chat-log :userId="activeChatUser" v-if="activeChatUser"></chat-log>
|
||||
</div>
|
||||
</component>
|
||||
<div class="chat__input flex p-4 bg-white">
|
||||
<vs-input class="flex-1" placeholder="Type Your Message" v-model="typedMessage" @keyup.enter="sendMsg" />
|
||||
<vs-button class="bg-primary-gradient ml-4" type="filled" @click="sendMsg">Send</vs-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="flex flex-col items-center">
|
||||
<feather-icon icon="MessageSquareIcon" class="mb-4 bg-white p-8 shadow-md rounded-full" svgClasses="w-16 h-16"></feather-icon>
|
||||
<h4 class=" py-2 px-4 bg-white shadow-md rounded-full cursor-pointer" @click.stop="toggleChatSidebar(true)">Start Conversation</h4>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ChatContact from './ChatContact.vue'
|
||||
import ChatLog from './ChatLog.vue'
|
||||
import ChatNavbar from './ChatNavbar.vue'
|
||||
import UserProfile from './UserProfile.vue'
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
import moduleChat from '@/store/chat/moduleChat.js'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
active : true,
|
||||
isHidden : false,
|
||||
searchContact : '',
|
||||
activeProfileSidebar : false,
|
||||
activeChatUser : null,
|
||||
userProfileId : -1,
|
||||
typedMessage : '',
|
||||
isChatPinned : false,
|
||||
settings : {
|
||||
maxScrollbarLength : 60,
|
||||
wheelSpeed : 0.70
|
||||
},
|
||||
clickNotClose : true,
|
||||
isChatSidebarActive : true,
|
||||
isLoggedInUserProfileView: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
windowWidth () {
|
||||
this.setSidebarWidth()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
chatLastMessaged () {
|
||||
return (userId) => this.$store.getters['chat/chatLastMessaged'](userId)
|
||||
},
|
||||
chatUnseenMessages () {
|
||||
return (userId) => {
|
||||
const unseenMsg = this.$store.getters['chat/chatUnseenMessages'](userId)
|
||||
if (unseenMsg) return unseenMsg
|
||||
}
|
||||
},
|
||||
activeUser () {
|
||||
return this.$store.state.AppActiveUser
|
||||
},
|
||||
getStatusColor () {
|
||||
return (isActiveUser) => {
|
||||
const userStatus = this.getUserStatus(isActiveUser)
|
||||
|
||||
if (userStatus === 'online') {
|
||||
return 'success'
|
||||
} else if (userStatus === 'do not disturb') {
|
||||
return 'danger'
|
||||
} else if (userStatus === 'away') {
|
||||
return 'warning'
|
||||
} else {
|
||||
return 'grey'
|
||||
}
|
||||
}
|
||||
},
|
||||
chatContacts () {
|
||||
return this.$store.getters['chat/chatContacts']
|
||||
},
|
||||
contacts () {
|
||||
return this.$store.getters['chat/contacts']
|
||||
},
|
||||
searchQuery: {
|
||||
get () {
|
||||
return this.$store.state.chat.chatSearchQuery
|
||||
},
|
||||
set (val) {
|
||||
this.$store.dispatch('chat/setChatSearchQuery', val)
|
||||
}
|
||||
},
|
||||
scrollbarTag () {
|
||||
return this.$store.getters.scrollbarTag
|
||||
},
|
||||
isActiveChatUser () {
|
||||
return (userId) => userId === this.activeChatUser
|
||||
},
|
||||
windowWidth () {
|
||||
return this.$store.state.windowWidth
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getUserStatus (isActiveUser) {
|
||||
// return "active"
|
||||
return isActiveUser ? this.$store.state.AppActiveUser.status : this.contacts[this.activeChatUser].status
|
||||
},
|
||||
closeProfileSidebar (value) {
|
||||
this.activeProfileSidebar = value
|
||||
},
|
||||
updateActiveChatUser (contactId) {
|
||||
this.activeChatUser = contactId
|
||||
if (this.$store.getters['chat/chatDataOfUser'](this.activeChatUser)) {
|
||||
this.$store.dispatch('chat/markSeenAllMessages', contactId)
|
||||
}
|
||||
const chatData = this.$store.getters['chat/chatDataOfUser'](this.activeChatUser)
|
||||
if (chatData) this.isChatPinned = chatData.isPinned
|
||||
else this.isChatPinned = false
|
||||
this.toggleChatSidebar()
|
||||
this.typedMessage = ''
|
||||
},
|
||||
showProfileSidebar (userId, openOnLeft = false) {
|
||||
this.userProfileId = userId
|
||||
this.isLoggedInUserProfileView = openOnLeft
|
||||
this.activeProfileSidebar = !this.activeProfileSidebar
|
||||
},
|
||||
sendMsg () {
|
||||
if (!this.typedMessage) return
|
||||
const payload = {
|
||||
'isPinned': this.isChatPinned,
|
||||
'msg': {
|
||||
'textContent' : this.typedMessage,
|
||||
'time' : String(new Date()),
|
||||
'isSent' : true,
|
||||
'isSeen' : false
|
||||
},
|
||||
'id': this.activeChatUser
|
||||
}
|
||||
this.$store.dispatch('chat/sendChatMessage', payload)
|
||||
this.typedMessage = ''
|
||||
|
||||
const scroll_el = this.$refs.chatLogPS.$el || this.$refs.chatLogPS
|
||||
scroll_el.scrollTop = this.$refs.chatLog.scrollHeight
|
||||
},
|
||||
toggleIsChatPinned (value) {
|
||||
this.isChatPinned = value
|
||||
},
|
||||
setSidebarWidth () {
|
||||
if (this.windowWidth < 1200) {
|
||||
this.isChatSidebarActive = this.clickNotClose = false
|
||||
} else {
|
||||
this.isChatSidebarActive = this.clickNotClose = true
|
||||
}
|
||||
},
|
||||
toggleChatSidebar (value = false) {
|
||||
if (!value && this.clickNotClose) return
|
||||
this.isChatSidebarActive = value
|
||||
}
|
||||
},
|
||||
components: {
|
||||
VuePerfectScrollbar,
|
||||
ChatContact,
|
||||
UserProfile,
|
||||
ChatNavbar,
|
||||
ChatLog
|
||||
},
|
||||
created () {
|
||||
this.$store.registerModule('chat', moduleChat)
|
||||
this.$store.dispatch('chat/fetchContacts')
|
||||
this.$store.dispatch('chat/fetchChatContacts')
|
||||
this.$store.dispatch('chat/fetchChats')
|
||||
this.setSidebarWidth()
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$store.unregisterModule('chat')
|
||||
},
|
||||
mounted () {
|
||||
this.$store.dispatch('chat/setChatSearchQuery', '')
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/apps/chat.scss";
|
||||
</style>
|
||||
@@ -1,40 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ChatContact.vue
|
||||
Description: Chat contact - single component for chat
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div class="chat__contact flex items-center px-2 pt-4 pb-2" :class="{'bg-primary-gradient text-white shadow-lg': isActiveChatUser}">
|
||||
<div class="contact__avatar mr-1">
|
||||
<vs-avatar class="border-2 border-solid border-white" :src="contact.photoURL" size="42px" />
|
||||
</div>
|
||||
<div class="contact__container w-full flex items-center justify-between overflow-hidden">
|
||||
<div class="contact__info flex flex-col truncate w-5/6">
|
||||
<h5 class="font-semibold" :class="{'text-white': isActiveChatUser}">{{ contact.displayName }}</h5>
|
||||
<span class="truncate">{{ showLastMsg ? $store.getters['chat/chatLastMessaged'](contact.uid).textContent : contact.about }}</span>
|
||||
</div>
|
||||
|
||||
<div class="chat__contact__meta flex self-start flex-col items-end w-1/6">
|
||||
<span class="whitespace-no-wrap">{{ lastMessaged | date }}</span>
|
||||
<vs-chip class="number" color="primary" v-if="unseenMsg">{{ unseenMsg }}</vs-chip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
contact : { type: Object, required: true },
|
||||
isActiveChatUser : { type: Boolean },
|
||||
lastMessaged : { type: String, default : '' },
|
||||
showLastMsg : { type: Boolean, default: false },
|
||||
unseenMsg : { type: Number, default : 0 }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ChatLog.vue
|
||||
Description: Chat Application - Log of chat
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="component-chat-log" class="m-8" v-if="chatData">
|
||||
<div v-for="(msg, index) in chatData.msg" class="msg-grp-container" :key="index">
|
||||
|
||||
<!-- If previous msg is older than current time -->
|
||||
<template v-if="chatData.msg[index-1]">
|
||||
<vs-divider v-if="!isSameDay(msg.time, chatData.msg[index-1].time)" class="msg-time">
|
||||
<span>{{ toDate(msg.time) }}</span>
|
||||
</vs-divider>
|
||||
<div class="spacer mt-8" v-if="!hasSentPreviousMsg(chatData.msg[index-1].isSent, msg.isSent)"></div>
|
||||
</template>
|
||||
|
||||
<div class="flex items-start" :class="[{'flex-row-reverse' : msg.isSent}]">
|
||||
|
||||
<template v-if="chatData.msg[index-1]">
|
||||
<template v-if="(!hasSentPreviousMsg(chatData.msg[index-1].isSent, msg.isSent) || !isSameDay(msg.time, chatData.msg[index-1].time))">
|
||||
<vs-avatar size="40px" class="border-2 shadow border-solid border-white m-0 flex-shrink-0" :class="msg.isSent ? 'sm:ml-5 ml-3' : 'sm:mr-5 mr-3'" :src="senderImg(msg.isSent)"></vs-avatar>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-if="index == 0">
|
||||
<vs-avatar size="40px" class="border-2 shadow border-solid border-white m-0 flex-shrink-0" :class="msg.isSent ? 'sm:ml-5 ml-3' : 'sm:mr-5 mr-3'" :src="senderImg(msg.isSent)"></vs-avatar>
|
||||
</template>
|
||||
|
||||
<template v-if="chatData.msg[index-1]">
|
||||
<div class="mr-16" v-if="!(!hasSentPreviousMsg(chatData.msg[index-1].isSent, msg.isSent) || !isSameDay(msg.time, chatData.msg[index-1].time))"></div>
|
||||
</template>
|
||||
|
||||
<div class="msg break-words relative shadow-md rounded py-3 px-4 mb-2 rounded-lg max-w-sm" :class="{'bg-primary-gradient text-white': msg.isSent, 'border border-solid border-transparent bg-white': !msg.isSent}">
|
||||
<span>{{ msg.textContent }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default{
|
||||
props: {
|
||||
userId: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
chatData () {
|
||||
return this.$store.getters['chat/chatDataOfUser'](this.userId)
|
||||
},
|
||||
activeUserImg () {
|
||||
return this.$store.state.AppActiveUser.photoURL
|
||||
},
|
||||
senderImg () {
|
||||
return (isSentByActiveUser) => {
|
||||
if (isSentByActiveUser) return this.$store.state.AppActiveUser.photoURL
|
||||
else return this.$store.getters['chat/contact'](this.userId).photoURL
|
||||
}
|
||||
},
|
||||
hasSentPreviousMsg () {
|
||||
return (last_sender, current_sender) => last_sender === current_sender
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isSameDay (time_to, time_from) {
|
||||
const date_time_to = new Date(Date.parse(time_to))
|
||||
const date_time_from = new Date(Date.parse(time_from))
|
||||
return date_time_to.getFullYear() === date_time_from.getFullYear() &&
|
||||
date_time_to.getMonth() === date_time_from.getMonth() &&
|
||||
date_time_to.getDate() === date_time_from.getDate()
|
||||
},
|
||||
toDate (time) {
|
||||
const locale = 'en-us'
|
||||
const date_obj = new Date(Date.parse(time))
|
||||
const monthName = date_obj.toLocaleString(locale, {
|
||||
month: 'short'
|
||||
})
|
||||
return `${date_obj.getDate() } ${ monthName}`
|
||||
},
|
||||
scrollToBottom () {
|
||||
this.$nextTick(() => {
|
||||
this.$parent.$el.scrollTop = this.$parent.$el.scrollHeight
|
||||
})
|
||||
}
|
||||
},
|
||||
updated () {
|
||||
this.scrollToBottom()
|
||||
},
|
||||
mounted () {
|
||||
this.scrollToBottom()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,85 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ChatNavbar.vue
|
||||
Description: Chat Application - Chat navbar
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div v-if="userId != null" class="chat__header">
|
||||
<vs-navbar class="p-4 flex navbar-custom" color="white" type="flat">
|
||||
<div class="relative flex mr-4">
|
||||
<feather-icon icon="MenuIcon" class="mr-4 cursor-pointer" v-if="isSidebarCollapsed" @click.stop="$emit('openContactsSidebar')" />
|
||||
<vs-avatar class="m-0 border-2 border-solid border-white" size="40px" :src="userDetails.photoURL" @click.stop="$emit('showProfileSidebar', userId)" />
|
||||
<div class="h-3 w-3 border-white border border-solid rounded-full absolute right-0 bottom-0" :class="'bg-' + getStatusColor(false)"></div>
|
||||
</div>
|
||||
<h6>{{ userDetails.displayName }}</h6>
|
||||
<vs-spacer></vs-spacer>
|
||||
<feather-icon icon="StarIcon" class="cursor-pointer" :svgClasses="[{'text-warning stroke-current': isPinnedLocal}, 'w-6', 'h-6']" @click.stop="isPinnedLocal = !isPinnedLocal"></feather-icon>
|
||||
</vs-navbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
userId: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
isPinnedProp: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isSidebarCollapsed: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isPinnedLocal: {
|
||||
get () {
|
||||
return this.isPinnedProp
|
||||
},
|
||||
set (val) {
|
||||
const chatData = this.$store.getters['chat/chatDataOfUser'](this.userId)
|
||||
if (chatData) {
|
||||
const payload = { id: this.userId, value: val }
|
||||
this.$store.dispatch('chat/toggleIsPinned', payload)
|
||||
.then(() => { this.$emit('toggleIsChatPinned', val) })
|
||||
.catch((err) => { console.error(err) })
|
||||
} else {
|
||||
this.$emit('toggleIsChatPinned', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
userDetails () {
|
||||
return this.$store.getters['chat/contact'](this.userId)
|
||||
},
|
||||
getStatusColor () {
|
||||
return (isActiveUser) => {
|
||||
const userStatus = this.getUserStatus(isActiveUser)
|
||||
|
||||
if (userStatus === 'online') {
|
||||
return 'success'
|
||||
} else if (userStatus === 'do not disturb') {
|
||||
return 'danger'
|
||||
} else if (userStatus === 'away') {
|
||||
return 'warning'
|
||||
} else {
|
||||
return 'grey'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getUserStatus (isActiveUser) {
|
||||
return isActiveUser ? this.$store.state.AppActiveUser.status : this.userDetails.status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserProfile.vue
|
||||
Description: user profile sidebar
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="parentx-demo-2">
|
||||
|
||||
<vs-sidebar parent="#chat-app" :position-right="!isLoggedInUser" :hidden-background="false" v-model="activeLocal" id="chat-profile-sidebar" class="items-no-padding">
|
||||
|
||||
<div class="header-sidebar relative flex flex-col p-0" slot="header">
|
||||
<feather-icon icon="XIcon" svgClasses="m-2 cursor-pointer absolute top-0 right-0" @click="$emit('closeProfileSidebar', false)"></feather-icon>
|
||||
|
||||
|
||||
<div class="relative inline-flex mx-auto mb-5 mt-6">
|
||||
<vs-avatar class="m-0 border-white border-2 border-solid shadow-md" :src="chatUser.photoURL" size="70px" />
|
||||
<div class="h-5 w-5 border-white border-2 border-solid rounded-full absolute right-0 bottom-0" :class="'bg-' + statusColor"></div>
|
||||
</div>
|
||||
|
||||
<h4 class="mr-2 self-center">{{ chatUser.displayName }}</h4>
|
||||
</div>
|
||||
|
||||
<component :is="scrollbarTag" class="scroll-area" :settings="settings" :key="$vs.rtl">
|
||||
<div class="p-8">
|
||||
|
||||
<h6 class="mb-2" :class="{'ml-4': isLoggedInUser}">About</h6>
|
||||
<vs-textarea class="mb-10" counter="120" maxlength="120" :counter-danger.sync="counterDanger" v-model="about" rows="5" v-if="isLoggedInUser" />
|
||||
<p v-else>{{ chatUser.about }}</p>
|
||||
|
||||
<div class="userProfile__status" v-if="isLoggedInUser">
|
||||
<h6 class="mb-4">Status</h6>
|
||||
<ul>
|
||||
<li class="mb-2">
|
||||
<vs-radio v-model="status" vs-value="online" color="success">Active</vs-radio>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<vs-radio v-model="status" vs-value="do not disturb" color="danger">Do Not Disturb</vs-radio>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<vs-radio v-model="status" vs-value="away" color="warning">Away</vs-radio>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<vs-radio v-model="status" vs-value="offline" color="grey">Offline</vs-radio>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</component>
|
||||
</vs-sidebar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
userId: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
active: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isLoggedInUser: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
counterDanger: false,
|
||||
settings: { // perfectscrollbar settings
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed: .60
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
chatUser () {
|
||||
return this.$store.getters['chat/chatUser'](this.userId)
|
||||
},
|
||||
activeLocal: {
|
||||
get () { return this.active },
|
||||
set (value) { this.$emit('closeProfileSidebar', value) }
|
||||
},
|
||||
about: {
|
||||
get () { return this.chatUser.about },
|
||||
set (value) { this.$store.dispatch('updateUserInfo', { about: value }) }
|
||||
},
|
||||
status: {
|
||||
get () { return this.chatUser.status },
|
||||
set (value) { this.$store.dispatch('updateUserInfo', { status: value }) }
|
||||
},
|
||||
statusColor () {
|
||||
const userStatus = this.chatUser.status
|
||||
|
||||
if (userStatus === 'online') {
|
||||
return 'success'
|
||||
} else if (userStatus === 'do not disturb') {
|
||||
return 'danger'
|
||||
} else if (userStatus === 'away') {
|
||||
return 'warning'
|
||||
} else {
|
||||
return 'grey'
|
||||
}
|
||||
},
|
||||
scrollbarTag () {
|
||||
return this.$store.getters.scrollbarTag
|
||||
}
|
||||
},
|
||||
components: {
|
||||
VuePerfectScrollbar
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="مشاهده درخواست های فعالسازی اکانت" class="mb-base">
|
||||
<XTable :model="getColTable" ref="activeAccount">
|
||||
<span slot="names" slot-scope="text,record">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>مشاهده</span>
|
||||
</template>
|
||||
<feather-icon icon="EyeIcon" @click="showModal(text.record.id,text.record.customer_id)" svgClasses="w-5 h-5 text-warning" style="cursor: pointer"/>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</XTable>
|
||||
|
||||
<a-modal v-model="visible" title="" @ok="handleActiveAccount" @cancel="handleCancel" ok-text="فعالسازی" cancel-text="ردکردن" :cancel-button-props="{ props: { disabled: true } }">
|
||||
<div v-if="modalLoading">
|
||||
<ASkeleton />
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-descriptions >
|
||||
<a-descriptions-item label="نام">
|
||||
{{DataModal.name}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شماره موبایل">
|
||||
{{ DataModal.mobile }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="اهرازهویت شده" v-if="DataModal.meta">
|
||||
{{ DataModal.meta.sts_str}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="توضیحات" v-if="DataModal.meta">
|
||||
{{ DataModal.meta.reason_active }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<a-button type="primary" @click="sendMessageModal">
|
||||
ارسال پیام
|
||||
</a-button>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<a-modal v-model="visibleSendMessage" title="ارسال پیام" :width="700" :ok-button-props="{ props: { disabled: true } }" :cancel-button-props="{ props: { disabled: true } }" ok-text="ارسال" cancel-text="ردکردن">
|
||||
<a-form :form="formSendMessage" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" @submit="submitSendMessage">
|
||||
<a-form-item label="توضیحات">
|
||||
<a-textarea
|
||||
v-decorator="['message', { rules: [{ required: true, message: 'وارد کردن مقدار الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-button type="primary" html-type="submit">
|
||||
ارسال پیامک
|
||||
</a-button>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableActiveAccount'
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "list-customer",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
getColTable: undefined,
|
||||
visible: false,
|
||||
visibleSendMessage: false,
|
||||
modalLoading: false,
|
||||
DataModal: {},
|
||||
tempRow:undefined,
|
||||
formSendMessage: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
tempCustomerId:undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sendMessageModal(){
|
||||
this.visibleSendMessage = true
|
||||
},
|
||||
showModal(id) {
|
||||
this.tempRow = id
|
||||
this.tempCustomerId = id
|
||||
this.modalLoading = true;
|
||||
this.visible = true;
|
||||
this.getDtaModal(id);
|
||||
},
|
||||
async handleActiveAccount() {
|
||||
const id = this.tempRow
|
||||
this.visible = false;
|
||||
try{
|
||||
await this.$store.dispatch('customer/saveActiveAccount',{
|
||||
active:true,
|
||||
id:id
|
||||
})
|
||||
this.$refs.activeAccount.fetch()
|
||||
this.visible = false
|
||||
this.$ntSet('فعالسازی اکانت با موفقیت انجام شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError('مشکلی در شبکه وجود دارد.')
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
handleCancel() {
|
||||
this.visible = false;
|
||||
},
|
||||
async getDtaModal(id) {
|
||||
try {
|
||||
const {data} = await axios.get(`admin/customer/${id}`)
|
||||
this.DataModal = data;
|
||||
} catch (e) {
|
||||
this.visible = false;
|
||||
} finally {
|
||||
this.modalLoading = false;
|
||||
}
|
||||
},
|
||||
submitSendMessage(e){
|
||||
e.preventDefault();
|
||||
this.formSendMessage.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try {
|
||||
const id = this.tempCustomerId
|
||||
await this.$store.dispatch('customer/sendMessage',{
|
||||
customer_id: id,
|
||||
message: values.message
|
||||
})
|
||||
this.$refs.activeAccount.fetch()
|
||||
this.formSendMessage.resetFields()
|
||||
this.visibleSendMessage = false
|
||||
this.visible = false
|
||||
this.$ntSet('ارسال پیامک با موفقیت انجام شد. ')
|
||||
}catch (e) {
|
||||
this.$ntSetError('دوباره تلاش کنید.')
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
computed:{
|
||||
loading() {
|
||||
return this.$store.state.customer.loading;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getColTable = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,257 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserView.vue
|
||||
Description: User View page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div id="page-user-view">
|
||||
|
||||
<div id="user-data">
|
||||
<a-form :form="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" @submit="handleSubmit">
|
||||
|
||||
<ASpin type="loading" :spinning="loading">
|
||||
<vx-card title="اطلاعات پایه" class="mb-base">
|
||||
<!-- Avatar -->
|
||||
<div class="vx-row">
|
||||
<!-- Information - Col 1 -->
|
||||
<div class="vx-col flex-1" id="account-info-col-1">
|
||||
<a-form-item label="نام ">
|
||||
<a-input
|
||||
v-decorator="['user_id.fname', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="نام خانوادگی">
|
||||
<a-input
|
||||
v-decorator="['user_id.lname', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="کد مشتری">
|
||||
<a-input
|
||||
v-decorator="['cargo_code', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
</div>
|
||||
<!-- /Information - Col 1 -->
|
||||
|
||||
<!-- Information - Col 2 -->
|
||||
<div class="vx-col flex-1" id="account-info-col-2">
|
||||
<a-form-item label="شماره تلفن همراه">
|
||||
<a-input
|
||||
v-decorator="['user_id.phone', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
<ASpin :spinning="loading">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<vx-card title="اطلاعات تجاری" class="mb-base">
|
||||
<div class="flex">
|
||||
<div class="w-full md:w-1/2">
|
||||
<a-form-item label="نام کیفی">
|
||||
|
||||
<a-input
|
||||
v-decorator="['fee',{ rules: [{ required: true, message: '' }] },]"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="در صد روی محصول">
|
||||
|
||||
<a-input-number
|
||||
v-decorator="['ojratr',{ rules: [{ required: true, message: '' }] },]"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="سقف اعتبار">
|
||||
|
||||
<a-input-number
|
||||
v-decorator="['ojrat',{ rules: [{ required: true, message: '' }] },]"/>
|
||||
</a-form-item>
|
||||
|
||||
</div>
|
||||
<div class="w-full md:w-1/2">
|
||||
<a-form-item label="مدت تسویه به روز">
|
||||
|
||||
<a-input-number
|
||||
v-decorator="['w',{ rules: [{ required: true, message: '' }] },]"/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
</ASpin>
|
||||
<ASpin :spinning="loading">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<vx-card title="اطلاعات تکمیلی" class="mb-base">
|
||||
<div class="flex">
|
||||
<div class="w-full md:w-1/2">
|
||||
<a-form-item label="استان">
|
||||
<a-input
|
||||
v-decorator="['province',{ rules: [] },]"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="شهر">
|
||||
<a-input
|
||||
v-decorator="['city',{ rules: [] },]"/>
|
||||
</a-form-item>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<a-form-item label="آدرس">
|
||||
<a-input
|
||||
v-decorator="['address',{ rules: [] },]"/>
|
||||
</a-form-item>
|
||||
<div class="w-full md:w-1/2">
|
||||
<a-form-item label="تلفن ثابت">
|
||||
<a-input
|
||||
v-decorator="['fixed_phone',{ rules: [] },]"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="کد ملی">
|
||||
<a-input
|
||||
v-decorator="['national_code',{ rules: [] },]"/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
</ASpin>
|
||||
<!-- /Information - Col 2 -->
|
||||
<div class="vx-col w-full flex" id="account-manage-buttons">
|
||||
<vs-button icon-pack="feather" icon="icon-edit" @click="sub" class="mr-4">ویرایش
|
||||
</vs-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
user_data: {},
|
||||
loading: false,
|
||||
formLayout: 'horizontal',
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
user_not_found: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
id() {
|
||||
return this.$router.history.current.params.id;
|
||||
},
|
||||
data() {
|
||||
return this.$store.state.customer.model;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
try {
|
||||
this.loading = true;
|
||||
this.$store.dispatch('customer/save', values);
|
||||
this.$ntSet()
|
||||
} catch (e) {
|
||||
this.$ntSetError()
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
async getData() {
|
||||
if (this.id) {
|
||||
try {
|
||||
this.loading = true;
|
||||
await this.$store.dispatch('customer/getEditData', {id: this.id});
|
||||
this.form.setFieldsValue(this.data);
|
||||
} catch (e) {
|
||||
this.$ntGetError();
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
showDeleteSuccess() {
|
||||
this.$vs.notify({
|
||||
color: 'success',
|
||||
title: 'User Deleted',
|
||||
text: 'The selected user was successfully deleted'
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getData();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#avatar-col {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
#page-user-view {
|
||||
table {
|
||||
td {
|
||||
vertical-align: top;
|
||||
min-width: 140px;
|
||||
padding-bottom: .8rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
&:not(.permissions-table) {
|
||||
td {
|
||||
@media screen and (max-width: 370px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #account-info-col-1 {
|
||||
// // flex-grow: 1;
|
||||
// width: 30rem !important;
|
||||
// @media screen and (min-width:1200px) {
|
||||
// & {
|
||||
// flex-grow: unset !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@media screen and (min-width: 1201px) and (max-width: 1211px),
|
||||
only screen and (min-width: 636px) and (max-width: 991px) {
|
||||
#account-info-col-1 {
|
||||
width: calc(100% - 12rem) !important;
|
||||
}
|
||||
|
||||
// #account-manage-buttons {
|
||||
// width: 12rem !important;
|
||||
// flex-direction: column;
|
||||
|
||||
// > button {
|
||||
// margin-right: 0 !important;
|
||||
// margin-bottom: 1rem;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,135 +0,0 @@
|
||||
<template>
|
||||
<ASpin type="loading" :spinning="loading">
|
||||
<vx-card title="تعداد آگهی دهندگان در بازه های زمانی مختلف" style="margin-top: 2rem">
|
||||
<a-form :form="formdate" class="flex grid sm:gap-y-4 sm:grid-cols-1 md:flex md:space-x-4" @submit="submitCustomerSingUp">
|
||||
<div>
|
||||
<a-form-item>
|
||||
<a-input
|
||||
placeholder="تاریخ شروع"
|
||||
v-model="start_sign_up_customer"
|
||||
id="start_adv_sum_at"
|
||||
style="width: 200px"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#4f72ab"
|
||||
v-model="start_sign_up_customer"
|
||||
element="start_adv_sum_at"
|
||||
placeholder="تاریخ شروع"
|
||||
class="mt-1"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<a-form-item>
|
||||
<a-input
|
||||
placeholder="تاریخ پایان"
|
||||
v-model="end_sign_up_customer"
|
||||
id="end_adv_sum_at"
|
||||
style="width: 200px"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#4f72ab"
|
||||
v-model="end_sign_up_customer"
|
||||
element="end_adv_sum_at"
|
||||
placeholder="تاریخ پایان"
|
||||
/>
|
||||
</div>
|
||||
<a-button type="primary" html-type="submit" class="w-1/8 mt-1">
|
||||
بررسی
|
||||
</a-button>
|
||||
</a-form>
|
||||
<div v-if="isShow" class="overflow_mobile">
|
||||
<apexchart height="400" type="line" :options="optionsCustomerSingUp" :series="seriesCustomerSingUp"></apexchart>
|
||||
</div>
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import VueApexCharts from 'vue-apexcharts'
|
||||
import axios from '@/axios'
|
||||
import VuePersianDatetimePicker from 'vue-persian-datetime-picker'
|
||||
import * as moment from 'jalali-moment';
|
||||
|
||||
export default {
|
||||
name: "ChartCustomer",
|
||||
components:{
|
||||
apexchart:VueApexCharts,
|
||||
datePicker: VuePersianDatetimePicker
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
formdate: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
isShow:false,
|
||||
seriesCustomerSingUp: [],
|
||||
optionsCustomerSingUp: {},
|
||||
start_sign_up_customer:null,
|
||||
end_sign_up_customer:null,
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
submitCustomerSingUp(e){
|
||||
e.preventDefault();
|
||||
this.formdate.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try{
|
||||
values.start_at = moment(this.start_sign_up_customer,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
values.end_at = moment(this.end_sign_up_customer,'jYYYY/jM/jD').format('YYYY-M-D');
|
||||
const {data} = await this.$store.dispatch('customer/SendCustomerSingUp', values);
|
||||
const x = data.map((chart)=> moment(chart.date,'YYYY-M-D').format('jYYYY/jM/jD'));
|
||||
const y = data.map((chart)=>chart.total);
|
||||
this.seriesCustomerSingUp = [
|
||||
{
|
||||
name:"تعداد آگهی دهندگان",
|
||||
data: y
|
||||
}
|
||||
]
|
||||
this.optionsCustomerSingUp = {
|
||||
colors: ['#4f72ab'],
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: x
|
||||
}
|
||||
}
|
||||
this.isShow = true
|
||||
this.$ntSet()
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$store.state.customer.loading;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media (max-width: 768px) {
|
||||
#content-area{
|
||||
width:100%
|
||||
}
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.overflow_mobile{
|
||||
overflow-x: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,289 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserView.vue
|
||||
Description: User View page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="page-user-view">
|
||||
|
||||
<div id="user-data">
|
||||
<vx-card title="اطلاعات مشتری" class="mb-base">
|
||||
<!-- Avatar -->
|
||||
<div class="vx-row">
|
||||
<!-- Avatar Col -->
|
||||
<div class="vx-col" id="avatar-col">
|
||||
<div class="img-container mb-4">
|
||||
<img :src="user_data.avatar" class="rounded w-full"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Information - Col 1 -->
|
||||
<div class="vx-col flex-1" id="account-info-col-1">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="font-semibold">نام</td>
|
||||
<td>علی</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">کد ملی</td>
|
||||
<td>اشکانی</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">تلفن همراه</td>
|
||||
<td>09128081392</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">نوع مشتری</td>
|
||||
<td>کیفی</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!-- /Information - Col 1 -->
|
||||
|
||||
<!-- Information - Col 2 -->
|
||||
<div class="vx-col flex-1" id="account-info-col-2">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="font-semibold">وضعیت</td>
|
||||
<td>فعال</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">سطح کاربری</td>
|
||||
<td>عمده فروش</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">نام کیفی</td>
|
||||
<td>علی دوم</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">نام تجاری</td>
|
||||
<td>درین</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="w-full p-6">
|
||||
<div class="font-semibold">آدرس</div>
|
||||
<div>-</div>
|
||||
</div>
|
||||
<!-- /Information - Col 2 -->
|
||||
<div class="vx-col w-full flex" id="account-manage-buttons">
|
||||
<vs-button icon-pack="feather" icon="icon-edit" class="mr-4">ویرایش</vs-button>
|
||||
<APopconfirm placement="top" ok-text="بله" cancel-text="خیر" @confrim="()=>{}">
|
||||
<template slot="title">
|
||||
<span >مطمئنی؟</span>
|
||||
</template>
|
||||
<vs-button type="border" color="danger" icon-pack="feather" icon="icon-trash">
|
||||
غیر فعال کردن مشتری
|
||||
</vs-button>
|
||||
</APopconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</vx-card>
|
||||
|
||||
<div class="vx-row">
|
||||
<div class="vx-col lg:w-1/2 w-full">
|
||||
<vx-card title="اطلاعات مالی" class="mb-base">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="font-semibold">درصد روی محصول</td>
|
||||
<td>0.7 درصد</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">میزان فروش</td>
|
||||
<td>{{1550000 | priceUnit}} </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">میزان بدهی</td>
|
||||
<td>{{250000 | priceUnit}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">سقف اعتبار</td>
|
||||
<td>{{250000 | priceUnit}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">میزان بدهی گرمی</td>
|
||||
<td>250 گرم</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font-semibold">مدت تسویه</td>
|
||||
<td>20 روز</td>
|
||||
</tr>
|
||||
</table>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
<div class="vx-col lg:w-1/2 w-full">
|
||||
<vx-card title="آمار فروش">
|
||||
<div v-for="(browser, index) in browserStatistics" :key="browser.id" :class="{'mt-4': index}">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex flex-col">
|
||||
<span class="mb-1">{{ browser.title }}</span>
|
||||
<h4>{{ browser.value | priceUnit }}</h4>
|
||||
</div>
|
||||
<div class="flex flex-col text-right">
|
||||
<span class="flex -mr-1">
|
||||
<span class="mr-1">{{ browser.comparedResult }}</span>
|
||||
<feather-icon :icon=" browser.comparedResult < 0 ? 'ArrowDownIcon' : 'ArrowUpIcon'" :svgClasses="[browser.comparedResult < 0 ? 'text-danger' : 'text-success' ,'stroke-current h-4 w-4 mb-1 mr-1']"></feather-icon>
|
||||
</span>
|
||||
<span class="text-grey">{{ browser.percent }}%</span>
|
||||
</div>
|
||||
</div>
|
||||
<vs-progress :percent="browser.ratio"></vs-progress>
|
||||
</div>
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
export default {
|
||||
name: 'CustomerView',
|
||||
data() {
|
||||
return {
|
||||
user_data: null,
|
||||
browserStatistics:[
|
||||
{
|
||||
title:"فروش هفته جاری",
|
||||
percent:"5",
|
||||
value:"1500000",
|
||||
ratio:50,
|
||||
},
|
||||
{
|
||||
title:"فروش هفته گذشته",
|
||||
percent:"4",
|
||||
value:"12000000",
|
||||
ratio:75,
|
||||
},
|
||||
{
|
||||
title:"فروش ماه گذشته",
|
||||
percent:"10",
|
||||
value:"125000000",
|
||||
ratio:42,
|
||||
}
|
||||
],
|
||||
user_not_found: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userAddress() {
|
||||
let str = ''
|
||||
for (const field in this.user_data.location) {
|
||||
str += `${field} `
|
||||
}
|
||||
return str
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
confirmDeleteRecord() {
|
||||
this.$vs.dialog({
|
||||
type: 'confirm',
|
||||
color: 'danger',
|
||||
title: 'Confirm Delete',
|
||||
text: `You are about to delete "${this.user_data.username}"`,
|
||||
accept: this.deleteRecord,
|
||||
acceptText: 'Delete'
|
||||
})
|
||||
},
|
||||
deleteRecord() {
|
||||
/* Below two lines are just for demo purpose */
|
||||
this.$router.push({name: 'app-user-list'})
|
||||
this.showDeleteSuccess()
|
||||
|
||||
/* UnComment below lines for enabling true flow if deleting user */
|
||||
// this.$store.dispatch("userManagement/removeRecord", this.user_data.id)
|
||||
// .then(() => { this.$router.push({name:'app-user-list'}); this.showDeleteSuccess() })
|
||||
// .catch(err => { console.error(err) })
|
||||
},
|
||||
showDeleteSuccess() {
|
||||
this.$vs.notify({
|
||||
color: 'success',
|
||||
title: 'User Deleted',
|
||||
text: 'The selected user was successfully deleted'
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// Register Module UserManagement Module
|
||||
if (!moduleUserManagement.isRegistered) {
|
||||
this.$store.registerModule('userManagement', moduleUserManagement)
|
||||
moduleUserManagement.isRegistered = true
|
||||
}
|
||||
|
||||
this.$store.dispatch('userManagement/fetchUser', 268)
|
||||
.then(res => {
|
||||
this.user_data = res.data
|
||||
})
|
||||
.catch(err => {
|
||||
if (err.response.status === 404) {
|
||||
this.user_not_found = true
|
||||
return
|
||||
}
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#avatar-col {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
#page-user-view {
|
||||
table {
|
||||
td {
|
||||
vertical-align: top;
|
||||
min-width: 140px;
|
||||
padding-bottom: .8rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
&:not(.permissions-table) {
|
||||
td {
|
||||
@media screen and (max-width: 370px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #account-info-col-1 {
|
||||
// // flex-grow: 1;
|
||||
// width: 30rem !important;
|
||||
// @media screen and (min-width:1200px) {
|
||||
// & {
|
||||
// flex-grow: unset !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@media screen and (min-width: 1201px) and (max-width: 1211px),
|
||||
only screen and (min-width: 636px) and (max-width: 991px) {
|
||||
#account-info-col-1 {
|
||||
width: calc(100% - 12rem) !important;
|
||||
}
|
||||
|
||||
// #account-manage-buttons {
|
||||
// width: 12rem !important;
|
||||
// flex-direction: column;
|
||||
|
||||
// > button {
|
||||
// margin-right: 0 !important;
|
||||
// margin-bottom: 1rem;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<AddCustomer/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AddCustomer from "./AddCustomer";
|
||||
export default {
|
||||
name: "Edit",
|
||||
components: {
|
||||
AddCustomer
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,254 +0,0 @@
|
||||
|
||||
<template>
|
||||
<div id="page-user-view">
|
||||
<div id="user-data">
|
||||
<a-form :form="form" @submit="handleSubmit">
|
||||
|
||||
<ASpin type="loading" :spinning="loading">
|
||||
<vx-card title="ویرایش اطلاعات مشتری">
|
||||
<div class="grid grid-col-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 md:gap-0 xl:grid-cols-2 lg:gap-4 xl:gap-4">
|
||||
<a-form-item label="نام ">
|
||||
<a-input
|
||||
v-decorator="['fname', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="نام خانوادگی">
|
||||
<a-input
|
||||
v-decorator="['lname', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="ایمیل">
|
||||
<a-input
|
||||
v-decorator="['email', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="شماره موبایل">
|
||||
<a-input
|
||||
v-decorator="['mobile', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label=" عکس کارت ملی">
|
||||
<Xupload url="admin/file" @input="changeUploadCart" @change="changeUploadImage"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="پروفایل" >
|
||||
<Xupload url="admin/file" @change="changeUploadImage"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="دسته">
|
||||
<a-select v-decorator="['collection_id',{ rules: [{ required: true }] },]">
|
||||
|
||||
<a-select-option v-for="(item,index) in getCollection" :key="index" :value="item.id">
|
||||
{{ item.title }}
|
||||
</a-select-option>
|
||||
|
||||
</a-select>
|
||||
|
||||
</a-form-item>
|
||||
<a-form-item label="آدرس">
|
||||
<a-textarea
|
||||
v-decorator="['default_address.address']"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="کد ملی">
|
||||
<a-input
|
||||
v-decorator="['n_code', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="شماره شبا" style="width:100%">
|
||||
<a-input
|
||||
v-decorator="['shaba_number', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<div class="birth-day">
|
||||
<label style="padding-top: .5em">تاریخ تولد:</label>
|
||||
<date-picker
|
||||
:auto-submit="true"
|
||||
color="#ff9800"
|
||||
v-model="birth_day"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<a-button type="primary" html-type="submit" style="margin-top: 3em">
|
||||
ویرایش
|
||||
</a-button>
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import axios from '@/axios'
|
||||
import VuePersianDatetimePicker from 'vue-persian-datetime-picker'
|
||||
import * as moment from 'jalali-moment';
|
||||
import Xupload from '../../../components/x-upload/XUpload'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
datePicker: VuePersianDatetimePicker,
|
||||
Xupload
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
user_data: {},
|
||||
formLayout: 'horizontal',
|
||||
dateFormat: 'YYYY/MM/DD',
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
user_not_found: false,
|
||||
getCollection:[],
|
||||
birth_day:'',
|
||||
src_n_code:null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
id() {
|
||||
return this.$router.history.current.params.id;
|
||||
},
|
||||
data() {
|
||||
return this.$store.state.customer.getDataCustomer;
|
||||
},
|
||||
editCustomer() {
|
||||
return this.$route.params && this.$route.params.id != undefined
|
||||
},
|
||||
loading() {
|
||||
if (this.$route.params.id) {
|
||||
console.log(this.$store.state.customer.loading,'loading')
|
||||
return this.$store.state.customer.loading;
|
||||
}
|
||||
},
|
||||
isResultTrue() {
|
||||
return this.$store.state.customer.successData;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields((err, values) => {
|
||||
if(!err){
|
||||
try{
|
||||
values.n_cart = this.src_n_code
|
||||
values.birth_day = moment(this.birth_day,'jYYYY/jM/jD').format('YYYY-M-D')
|
||||
this.$store.dispatch('customer/editCustomer',{
|
||||
id: this.$route.params.id,
|
||||
data: values
|
||||
}).then(()=>{
|
||||
if(this.isResultTrue) this.$router.push('/customer/list')
|
||||
})
|
||||
// this.form.resetFields()
|
||||
}catch (e) {
|
||||
console.log(e.response,'er')
|
||||
}finally {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
changeUploadImage(file){
|
||||
file.has_watermark = false
|
||||
},
|
||||
showDeleteSuccess() {
|
||||
this.$vs.notify({
|
||||
color: 'success',
|
||||
title: 'User Deleted',
|
||||
text: 'The selected user was successfully deleted'
|
||||
})
|
||||
},
|
||||
getDataCollection(){
|
||||
axios.get('admin/user/collection').then((res)=>{
|
||||
this.getCollection = res.data
|
||||
})
|
||||
},
|
||||
normFile(e) {
|
||||
if (Array.isArray(e)) {
|
||||
return e;
|
||||
}
|
||||
return e && e.fileList;
|
||||
},
|
||||
changeUploadCart(src){
|
||||
console.log(src,'src')
|
||||
this.src_n_code = src
|
||||
}
|
||||
},
|
||||
|
||||
mounted(){
|
||||
this.getDataCollection()
|
||||
if(this.editCustomer){
|
||||
this.$store.dispatch('customer/CustomerId',this.$route.params.id).then(()=>{
|
||||
this.birth_day = this.data.bdj
|
||||
this.data.collection_id = this.data.collection_id
|
||||
this.form.setFieldsValue(this.data)
|
||||
});
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getData();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#avatar-col {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
.birth-day label{
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
|
||||
#page-user-view {
|
||||
table {
|
||||
td {
|
||||
vertical-align: top;
|
||||
min-width: 140px;
|
||||
padding-bottom: .8rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
&:not(.permissions-table) {
|
||||
td {
|
||||
@media screen and (max-width: 370px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #account-info-col-1 {
|
||||
// // flex-grow: 1;
|
||||
// width: 30rem !important;
|
||||
// @media screen and (min-width:1200px) {
|
||||
// & {
|
||||
// flex-grow: unset !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@media screen and (min-width: 1201px) and (max-width: 1211px),
|
||||
only screen and (min-width: 636px) and (max-width: 991px) {
|
||||
#account-info-col-1 {
|
||||
width: calc(100% - 12rem) !important;
|
||||
}
|
||||
|
||||
// #account-manage-buttons {
|
||||
// width: 12rem !important;
|
||||
// flex-direction: column;
|
||||
|
||||
// > button {
|
||||
// margin-right: 0 !important;
|
||||
// margin-bottom: 1rem;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,212 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="مشاهده درخواست های اهرازهویت" class="mb-base">
|
||||
<XTable :model="getColTable" ref="authentication">
|
||||
<span slot="names" slot-scope="text,record">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>مشاهده</span>
|
||||
</template>
|
||||
<feather-icon icon="EyeIcon" @click="authentication(text.record.id,text.record.customer_id)" svgClasses="w-5 h-5 text-warning" style="cursor: pointer"/>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</XTable>
|
||||
|
||||
<a-modal v-model="visible" :width="700" @ok="handleOk" @cancel="handleCancel" ok-text="اهرازهویت شود" cancel-text="ردکردن">
|
||||
<div v-if="modalLoading">
|
||||
<ASkeleton />
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-descriptions title="مشاهده اطلاعات اهراز هویت">
|
||||
<a-descriptions-item label="نام">
|
||||
{{DataModal.name}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شماره موبایل">
|
||||
{{ DataModal.mobile }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شهر">
|
||||
{{ DataModal.city }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شماره ملی">
|
||||
{{ DataModal.n_code }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="ایمیل">
|
||||
{{DataModal.email}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شبا">
|
||||
{{DataModal.shaba_number}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="تاریخ تولد">
|
||||
{{DataModal.birth_day}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="آدرس ">
|
||||
{{DataModal.address}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="کدپستی">
|
||||
{{DataModal.zipcode}}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<a-button type="primary" @click="sendMessageModal">
|
||||
ارسال پیام
|
||||
</a-button>
|
||||
</div>
|
||||
</a-modal>
|
||||
<a-modal v-model="visibleReasonCancel" title="دلیل رد شدن" :width="700" :ok-button-props="{ props: { disabled: true } }"
|
||||
:cancel-button-props="{ props: { disabled: true } }" ok-text="ارسال" cancel-text="ردکردن">
|
||||
<a-form :form="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" @submit="submitReasonReject">
|
||||
<a-form-item label="دلیل رد">
|
||||
<a-input
|
||||
v-decorator="['reject_reason', { rules: [{ required: true, message: 'وارد کردن مقدار الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-button type="primary" html-type="submit">
|
||||
ارسال دلیل
|
||||
</a-button>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
<a-modal v-model="visibleSendMessage" title="ارسال پیام" :width="700" :ok-button-props="{ props: { disabled: true } }" :cancel-button-props="{ props: { disabled: true } }" ok-text="ارسال" cancel-text="ردکردن">
|
||||
<a-form :form="formSendMessage" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" @submit="submitSendMessage">
|
||||
<a-form-item label="توضیحات">
|
||||
<a-textarea
|
||||
v-decorator="['message', { rules: [{ required: true, message: 'وارد کردن مقدار الزامی است.' }] }]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-button type="primary" html-type="submit">
|
||||
ارسال پیامک
|
||||
</a-button>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableManagement'
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "list-customer",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
getColTable: undefined,
|
||||
visible: false,
|
||||
visibleReasonCancel: false,
|
||||
visibleSendMessage: false,
|
||||
modalLoading: false,
|
||||
DataModal: {},
|
||||
tempCustomerId:undefined,
|
||||
form: this.$form.createForm(this, { name: 'coordinated' }),
|
||||
formSendMessage: this.$form.createForm(this, { name: 'coordinated' })
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
authentication(id,customer_id) {
|
||||
this.modalLoading = true;
|
||||
this.tempCustomerId = customer_id
|
||||
this.visible = true;
|
||||
this.getDtaModal(id);
|
||||
},
|
||||
async handleOk() {
|
||||
this.visible = false;
|
||||
try{
|
||||
const customer_id = this.tempCustomerId
|
||||
await this.$store.dispatch('customer/Authentication',{
|
||||
sts: 1,
|
||||
id: customer_id
|
||||
})
|
||||
this.$refs.authentication.fetch()
|
||||
this.$ntSet('اهرازهویت با موفقیت انجام شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError('دوباره تلاش کنید.')
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
handleCancel() {
|
||||
this.visible = false
|
||||
this.visibleReasonCancel = true
|
||||
},
|
||||
sendMessageModal() {
|
||||
this.$nextTick(()=>{
|
||||
this.visibleReasonCancel = false
|
||||
})
|
||||
this.visibleSendMessage = true
|
||||
},
|
||||
submitReasonReject(e){
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try {
|
||||
const customer_id = this.tempCustomerId
|
||||
await this.$store.dispatch('customer/reject',{
|
||||
sts:5,
|
||||
id:customer_id,
|
||||
reject_reason: values.reject_reason
|
||||
})
|
||||
this.$refs.authentication.fetch()
|
||||
this.form.resetFields()
|
||||
this.visible = false
|
||||
this.visibleReasonCancel = false
|
||||
this.$ntSet('عملیات با موفقیت انجام شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError('دوباره تلاش کنید.')
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
submitSendMessage(e){
|
||||
e.preventDefault();
|
||||
this.formSendMessage.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try {
|
||||
const id = this.tempCustomerId
|
||||
await this.$store.dispatch('customer/sendMessage',{
|
||||
customer_id: id,
|
||||
message: values.message
|
||||
})
|
||||
this.$refs.authentication.fetch()
|
||||
this.formSendMessage.resetFields()
|
||||
this.$ntSet('ارسال پیامک با موفقیت انجام شد. ')
|
||||
this.visible = false
|
||||
this.visibleSendMessage = false
|
||||
}catch (e) {
|
||||
this.$ntSetError('دوباره تلاش کنید.')
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
async getDtaModal(id) {
|
||||
try {
|
||||
const {data} = await axios.get(`admin/customer/revision/${id}`)
|
||||
this.DataModal = data;
|
||||
} catch (e) {
|
||||
this.visible = false;
|
||||
} finally {
|
||||
this.modalLoading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
computed:{
|
||||
loading() {
|
||||
return this.$store.state.customer.loading;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getColTable = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,95 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserEdit.vue
|
||||
Description: User Edit Page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="page-user-edit">
|
||||
<vs-alert color="danger" title="User Not Found" :active.sync="user_not_found">
|
||||
<span>User record with id: {{ $route.params.userId }} not found. </span>
|
||||
<span>
|
||||
<span>Check </span><router-link :to="{name:'page-user-list'}" class="text-inherit underline">All Users</router-link>
|
||||
</span>
|
||||
</vs-alert>
|
||||
<vx-card v-if="user_data">
|
||||
<div slot="no-body" class="tabs-container px-6 pt-6">
|
||||
<vs-tabs v-model="activeTab" class="tab-action-btn-fill-conatiner">
|
||||
<vs-tab label="اطلاعات کاربری" icon-pack="feather" icon="icon-user">
|
||||
<div class="tab-text">
|
||||
<customer-edit-tab-account class="mt-4" :data="user_data" />
|
||||
</div>
|
||||
</vs-tab>
|
||||
<vs-tab label="اطلاعات مالی" icon-pack="feather" icon="icon-info">
|
||||
<div class="tab-text">
|
||||
<customer-edit-tab-information class="mt-4" :data="user_data" />
|
||||
</div>
|
||||
</vs-tab>
|
||||
</vs-tabs>
|
||||
|
||||
</div>
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CustomerEditTabAccount from './CustomerEditTabAccount.vue'
|
||||
import CustomerEditTabInformation from './CustomerEditTabInformation.vue'
|
||||
import CustomerEditTabSocial from './CustomerEditTabSocial.vue'
|
||||
|
||||
// Store Module
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
export default {
|
||||
name:'CustomerEdit',
|
||||
components: {
|
||||
CustomerEditTabAccount,
|
||||
CustomerEditTabInformation,
|
||||
CustomerEditTabSocial
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
user_data: null,
|
||||
user_not_found: false,
|
||||
|
||||
/*
|
||||
This property is created for fetching latest data from API when tab is changed
|
||||
|
||||
Please check it's watcher
|
||||
*/
|
||||
activeTab: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeTab () {
|
||||
this.fetch_user_data(this.$route.params.userId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetch_user_data (userId) {
|
||||
this.$store.dispatch('userManagement/fetchUser', userId)
|
||||
.then(res => { this.user_data = res.data })
|
||||
.catch(err => {
|
||||
if (err.response.status === 404) {
|
||||
this.user_not_found = true
|
||||
return
|
||||
}
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
// Register Module UserManagement Module
|
||||
if (!moduleUserManagement.isRegistered) {
|
||||
this.$store.registerModule('userManagement', moduleUserManagement)
|
||||
moduleUserManagement.isRegistered = true
|
||||
}
|
||||
this.fetch_user_data(this.$route.params.userId)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,186 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserEditTabInformation.vue
|
||||
Description: User Edit Information Tab content
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="user-edit-tab-info">
|
||||
|
||||
<!-- Avatar Row -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="flex items-start flex-col sm:flex-row">
|
||||
<img :src="data.avatar" class="mr-8 rounded h-24 w-24" />
|
||||
<!-- <vs-avatar :src="data.avatar" size="80px" class="mr-4" /> -->
|
||||
<div>
|
||||
<p class="text-lg font-medium mb-2 mt-4 sm:mt-0">{{ data.name }}</p>
|
||||
<input type="file" class="hidden" ref="update_avatar_input" @change="update_avatar" accept="image/*">
|
||||
|
||||
<!-- Toggle comment of below buttons as one for actual flow & currently shown is only for demo -->
|
||||
<vs-button class="mr-4 mb-4">Change Avatar</vs-button>
|
||||
<!-- <vs-button type="border" class="mr-4" @click="$refs.update_avatar_input.click()">Change Avatar</vs-button> -->
|
||||
|
||||
<vs-button type="border" color="danger">Remove Avatar</vs-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content Row -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col md:w-1/2 w-full">
|
||||
<vs-input class="w-full mt-4" label="Username" v-model="data_local.username" v-validate="'required|alpha_num'" name="username" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('username')">{{ errors.first('username') }}</span>
|
||||
|
||||
<vs-input class="w-full mt-4" label="Name" v-model="data_local.name" v-validate="'required|alpha_spaces'" name="name" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('name')">{{ errors.first('name') }}</span>
|
||||
|
||||
<vs-input class="w-full mt-4" label="Email" v-model="data_local.email" type="email" v-validate="'required|email'" name="email" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('email')">{{ errors.first('email') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vx-col md:w-1/2 w-full">
|
||||
|
||||
<div class="mt-4">
|
||||
<label class="vs-input--label">Status</label>
|
||||
<v-select v-model="status_local" :clearable="false" :options="statusOptions" v-validate="'required'" name="status" :dir="$vs.rtl ? 'rtl' : 'ltr'" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('status')">{{ errors.first('status') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<label class="vs-input--label">Role</label>
|
||||
<v-select v-model="role_local" :clearable="false" :options="roleOptions" v-validate="'required'" name="role" :dir="$vs.rtl ? 'rtl' : 'ltr'" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('role')">{{ errors.first('role') }}</span>
|
||||
</div>
|
||||
|
||||
<vs-input class="w-full mt-4" label="Company" v-model="data_local.company" v-validate="'alpha_spaces'" name="company" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('company')">{{ errors.first('company') }}</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Permissions -->
|
||||
<vx-card class="mt-base" no-shadow card-border>
|
||||
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="flex items-end px-3">
|
||||
<feather-icon svgClasses="w-6 h-6" icon="LockIcon" class="mr-2" />
|
||||
<span class="font-medium text-lg leading-none">Permissions</span>
|
||||
</div>
|
||||
<vs-divider />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<tr>
|
||||
<!--
|
||||
You can also use `Object.keys(Object.values(data_local.permissions)[0])` this logic if you consider,
|
||||
our data structure. You just have to loop over above variable to get table headers.
|
||||
Below we made it simple. So, everyone can understand.
|
||||
-->
|
||||
<th class="font-semibold text-base text-left px-3 py-2" v-for="heading in ['Module', 'Read', 'Write', 'Create', 'Delete']" :key="heading">{{ heading }}</th>
|
||||
</tr>
|
||||
|
||||
<tr v-for="(val, name) in data_local.permissions" :key="name">
|
||||
<td class="px-3 py-2">{{ name }}</td>
|
||||
<td v-for="(permission, name) in val" class="px-3 py-2" :key="name+permission">
|
||||
<vs-checkbox v-model="val[name]" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</vx-card>
|
||||
|
||||
<!-- Save & Reset Button -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="mt-8 flex flex-wrap items-center justify-end">
|
||||
<vs-button class="ml-auto mt-2" @click="save_changes" :disabled="!validateForm">ذخیره تغییرات</vs-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
vSelect
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
data_local: JSON.parse(JSON.stringify(this.data)),
|
||||
|
||||
statusOptions: [
|
||||
{ label: 'Active', value: 'active' },
|
||||
{ label: 'Blocked', value: 'blocked' },
|
||||
{ label: 'Deactivated', value: 'deactivated' }
|
||||
],
|
||||
roleOptions: [
|
||||
{ label: 'Admin', value: 'admin' },
|
||||
{ label: 'User', value: 'user' },
|
||||
{ label: 'Staff', value: 'staff' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
status_local: {
|
||||
get () {
|
||||
return { label: this.capitalize(this.data_local.status), value: this.data_local.status }
|
||||
},
|
||||
set (obj) {
|
||||
this.data_local.status = obj.value
|
||||
}
|
||||
},
|
||||
role_local: {
|
||||
get () {
|
||||
return { label: this.capitalize(this.data_local.role), value: this.data_local.role }
|
||||
},
|
||||
set (obj) {
|
||||
this.data_local.role = obj.value
|
||||
}
|
||||
},
|
||||
validateForm () {
|
||||
return !this.errors.any()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
capitalize (str) {
|
||||
return str.slice(0, 1).toUpperCase() + str.slice(1, str.length)
|
||||
},
|
||||
save_changes () {
|
||||
/* eslint-disable */
|
||||
if (!this.validateForm) return
|
||||
|
||||
// Here will go your API call for updating data
|
||||
// You can get data in "this.data_local"
|
||||
|
||||
/* eslint-enable */
|
||||
},
|
||||
reset_data () {
|
||||
this.data_local = JSON.parse(JSON.stringify(this.data))
|
||||
},
|
||||
update_avatar () {
|
||||
// You can update avatar Here
|
||||
// For reference you can check dataList example
|
||||
// We haven't integrated it here, because data isn't saved in DB
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,160 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserEditTabInformation.vue
|
||||
Description: User Edit Information Tab content
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="user-edit-tab-info">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full md:w-1/2">
|
||||
|
||||
<!-- Col Header -->
|
||||
<div class="flex items-end">
|
||||
<feather-icon icon="UserIcon" class="mr-2" svgClasses="w-5 h-5" />
|
||||
<span class="leading-none font-medium">Personal Information</span>
|
||||
</div>
|
||||
|
||||
<!-- Col Content -->
|
||||
<div>
|
||||
|
||||
<!-- DOB -->
|
||||
<div class="mt-4">
|
||||
<label class="text-sm">Birth Date</label>
|
||||
<flat-pickr v-model="data_local.dob" :config="{ dateFormat: 'd F Y', maxDate: new Date() }" class="w-full" v-validate="'required'" name="dob" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('dob')">{{ errors.first('dob') }}</span>
|
||||
</div>
|
||||
|
||||
<vs-input class="w-full mt-4" label="Mobile" v-model="data_local.mobile" v-validate="{regex: '^\\+?([0-9]+)$' }" name="mobile" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('mobile')">{{ errors.first('mobile') }}</span>
|
||||
|
||||
<vs-input class="w-full mt-4" label="Website" v-model="data_local.website" v-validate="'url:require_protocol'" name="website" data-vv-as="field" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('website')">{{ errors.first('website') }}</span>
|
||||
|
||||
<div class="mt-4">
|
||||
<label class="text-sm">Languages</label>
|
||||
<v-select v-model="data_local.languages_known" multiple :closeOnSelect="false" :options="langOptions" v-validate="'required'" name="lang_known" :dir="$vs.rtl ? 'rtl' : 'ltr'" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('lang_known')">{{ errors.first('lang_known') }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Gender -->
|
||||
<div class="mt-4">
|
||||
<label class="text-sm">Gender</label>
|
||||
<div class="mt-2">
|
||||
<vs-radio v-model="data_local.gender" vs-value="male" class="mr-4">Male</vs-radio>
|
||||
<vs-radio v-model="data_local.gender" vs-value="female" class="mr-4">Female</vs-radio>
|
||||
<vs-radio v-model="data_local.gender" vs-value="other">Other</vs-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<label>Contact Options</label>
|
||||
<div class="flex flex-wrap mt-1">
|
||||
<vs-checkbox v-model="data_local.contact_options" vs-value="email" class="mr-4 mb-2">Email</vs-checkbox>
|
||||
<vs-checkbox v-model="data_local.contact_options" vs-value="message" class="mr-4 mb-2">Message</vs-checkbox>
|
||||
<vs-checkbox v-model="data_local.contact_options" vs-value="Phone" class=" mb-2">Phone</vs-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Address Col -->
|
||||
<div class="vx-col w-full md:w-1/2">
|
||||
|
||||
<!-- Col Header -->
|
||||
<div class="flex items-end md:mt-0 mt-base">
|
||||
<feather-icon icon="MapPinIcon" class="mr-2" svgClasses="w-5 h-5" />
|
||||
<span class="leading-none font-medium">Address</span>
|
||||
</div>
|
||||
|
||||
<!-- Col Content -->
|
||||
<div>
|
||||
<vs-input class="w-full mt-4" label="Address Line 1" v-model="data_local.location.add_line_1" v-validate="'required'" name="addd_line_1" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('addd_line_1')">{{ errors.first('addd_line_1') }}</span>
|
||||
|
||||
<vs-input class="w-full mt-4" label="Address Line 2" v-model="data_local.location.add_line_2" />
|
||||
|
||||
<vs-input class="w-full mt-4" label="Post Code" v-model="data_local.location.post_code" v-validate="'required|numeric'" name="post_code" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('post_code')">{{ errors.first('post_code') }}</span>
|
||||
|
||||
<vs-input class="w-full mt-4" label="City" v-model="data_local.location.city" v-validate="'required|alpha'" name="city" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('city')">{{ errors.first('city') }}</span>
|
||||
|
||||
<vs-input class="w-full mt-4" label="State" v-model="data_local.location.state" v-validate="'required|alpha'" name="state" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('state')">{{ errors.first('state') }}</span>
|
||||
|
||||
<vs-input class="w-full mt-4" label="Country" v-model="data_local.location.country" v-validate="'required|alpha'" name="country" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('country')">{{ errors.first('country') }}</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Save & Reset Button -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="mt-8 flex flex-wrap items-center justify-end">
|
||||
<vs-button class="ml-auto mt-2" @click="save_changes" :disabled="!validateForm">ذخیره تغییرات</vs-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import flatPickr from 'vue-flatpickr-component'
|
||||
import 'flatpickr/dist/flatpickr.css'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
vSelect,
|
||||
flatPickr
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
data_local: JSON.parse(JSON.stringify(this.data)),
|
||||
|
||||
langOptions: [
|
||||
{ label: 'English', value: 'english' },
|
||||
{ label: 'Spanish', value: 'spanish' },
|
||||
{ label: 'French', value: 'french' },
|
||||
{ label: 'Russian', value: 'russian' },
|
||||
{ label: 'German', value: 'german' },
|
||||
{ label: 'Arabic', value: 'arabic' },
|
||||
{ label: 'Sanskrit', value: 'sanskrit' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
validateForm () {
|
||||
return !this.errors.any()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save_changes () {
|
||||
/* eslint-disable */
|
||||
if (!this.validateForm) return
|
||||
|
||||
// Here will go your API call for updating data
|
||||
// You can get data in "this.data_local"
|
||||
|
||||
/* eslint-enable */
|
||||
},
|
||||
reset_data () {
|
||||
this.data_local = Object.assign({}, this.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,134 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserEditTabSocial.vue
|
||||
Description: User Edit Social Tab content
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="user-edit-tab-info">
|
||||
<div class="vx-row">
|
||||
|
||||
<!-- Col 1 -->
|
||||
<div class="vx-col w-full md:w-1/2">
|
||||
<vs-input
|
||||
class="w-full"
|
||||
v-model="data_local.social_links.twitter"
|
||||
icon-pack="feather"
|
||||
icon="icon-twitter"
|
||||
label="Twitter"
|
||||
icon-no-border
|
||||
v-validate="'url:require_protocol'"
|
||||
name="twitter" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('twitter')">{{ errors.first('twitter') }}</span>
|
||||
|
||||
<vs-input
|
||||
class="w-full mt-4"
|
||||
v-model="data_local.social_links.facebook"
|
||||
icon-pack="feather"
|
||||
icon="icon-facebook"
|
||||
label="Facebook"
|
||||
icon-no-border
|
||||
v-validate="'url:require_protocol'"
|
||||
name="facebook" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('facebook')">{{ errors.first('facebook') }}</span>
|
||||
|
||||
<vs-input
|
||||
class="w-full mt-4"
|
||||
v-model="data_local.social_links.instagram"
|
||||
icon-pack="feather"
|
||||
icon="icon-instagram"
|
||||
label="Instagram"
|
||||
icon-no-border
|
||||
v-validate="'url:require_protocol'"
|
||||
name="instagram" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('instagram')">{{ errors.first('instagram') }}</span>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Col 2 -->
|
||||
<div class="vx-col w-full md:w-1/2">
|
||||
<vs-input
|
||||
class="w-full mt-4 md:mt-0"
|
||||
v-model="data_local.social_links.github"
|
||||
icon-pack="feather"
|
||||
icon="icon-github"
|
||||
label="GitHub"
|
||||
icon-no-border
|
||||
v-validate="'url:require_protocol'"
|
||||
name="github" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('github')">{{ errors.first('github') }}</span>
|
||||
|
||||
<vs-input
|
||||
class="w-full mt-4"
|
||||
v-model="data_local.social_links.codepen"
|
||||
icon-pack="feather"
|
||||
icon="icon-codepen"
|
||||
label="CodePen"
|
||||
icon-no-border
|
||||
v-validate="'url:require_protocol'"
|
||||
name="codepen" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('codepen')">{{ errors.first('codepen') }}</span>
|
||||
|
||||
<vs-input
|
||||
class="w-full mt-4"
|
||||
v-model="data_local.social_links.slack"
|
||||
icon-pack="feather"
|
||||
icon="icon-slack"
|
||||
label="Slack"
|
||||
icon-no-border
|
||||
v-validate="'url:require_protocol'"
|
||||
name="slack" />
|
||||
<span class="text-danger text-sm" v-show="errors.has('slack')">{{ errors.first('slack') }}</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Save & Reset Button -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="mt-8 flex flex-wrap items-center justify-end">
|
||||
<vs-button class="ml-auto mt-2" @click="save_changes" :disabled="!validateForm">Save Changes</vs-button>
|
||||
<vs-button class="ml-4 mt-2" type="border" color="warning" @click="reset_data">Reset</vs-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
data_local: JSON.parse(JSON.stringify(this.data))
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
validateForm () {
|
||||
return !this.errors.any()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save_changes () {
|
||||
/* eslint-disable */
|
||||
if (!this.validateForm) return
|
||||
|
||||
// Here will go your API call for updating data (Also remvoe eslint-disable)
|
||||
// You can get data in "this.data_local"
|
||||
|
||||
/* eslint-enable */
|
||||
},
|
||||
reset_data () {
|
||||
this.data_local = Object.assign({}, this.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,166 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="لیست مشتریان" class="mb-base">
|
||||
<XTable :model="getColTable" ref="customer">
|
||||
<span slot="image" slot-scope="text,record">
|
||||
<img :src="text.record.avatar" alt="" width="50" >
|
||||
</span>
|
||||
<span slot="active" slot-scope="text,record">
|
||||
<feather-icon icon="CheckIcon" svgClasses="w-5 h-5 text-success" v-if="text.record.active"/>
|
||||
<feather-icon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</span>
|
||||
<div slot="names" slot-scope="text,record" class="flex space-x-2">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>مشاهده</span>
|
||||
</template>
|
||||
<feather-icon icon="EyeIcon" @click="view(text.record.id)" svgClasses="w-5 h-5" style="cursor: pointer"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>غیرفعالسازی اکانت</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آیامیخواهیداکانت را فعال کنید؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="Active(text.record.id)"
|
||||
@cancel="unActive(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="ActivityIcon" svgClasses="w-5 h-5 text-warning" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<span slot="title_collection" slot-scope="text,record">
|
||||
<div v-for="item in text.record.customer_collection_adv">
|
||||
<ATag>{{ item.title }}</ATag>
|
||||
</div>
|
||||
</span>
|
||||
<span slot="title_post" slot-scope="text,record">
|
||||
<span v-for="item in text.record.customer_collection_post">
|
||||
<ATag>{{ item.title }}</ATag>
|
||||
</span>
|
||||
</span>
|
||||
</XTable>
|
||||
<a-modal title="مشاهده اطلاعات" :visible="visible" layout="vertical" :width="700" @cancel="closeModal">
|
||||
<div v-if="modalLoading">
|
||||
<ASkeleton />
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-descriptions title="مشاهده اطلاعات فردی" v-if="dataModal">
|
||||
<a-descriptions-item label="نام">
|
||||
{{ dataModal.name }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="موبایل">
|
||||
{{ dataModal.mobile }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شهر">
|
||||
{{ dataModal.city }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="ایمیل">
|
||||
{{ dataModal.email }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="کدملی">
|
||||
{{ dataModal.ncode }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
</a-modal>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableCustomer'
|
||||
import axios from '@/axios'
|
||||
import uniq from 'lodash/uniq'
|
||||
|
||||
export default {
|
||||
name: "list-customer",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
getColTable:undefined,
|
||||
visible:false,
|
||||
visibleAccount:false,
|
||||
dataModal:undefined,
|
||||
modalLoading:false,
|
||||
tempRow:undefined,
|
||||
form: this.$form.createForm(this, { name: 'coordinated' }),
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
edit(id){
|
||||
this.$router.push('/customer/edit/'+id)
|
||||
},
|
||||
async confirm(id) {
|
||||
try {
|
||||
await this.$store.dispatch('customer/deleteCustomer',id)
|
||||
this.$ntSet('باموفقیت انجام شد.')
|
||||
this.$refs.customer.fetch()
|
||||
} catch (e) {
|
||||
this.$ntSetError()
|
||||
} finally {
|
||||
|
||||
}
|
||||
},
|
||||
async view(id){
|
||||
try{
|
||||
this.modalLoading = true;
|
||||
this.visible = true
|
||||
const {data} = await axios.get('/admin/customer/'+id)
|
||||
this.dataModal = data
|
||||
}catch (e) {
|
||||
this.visible = false
|
||||
this.$ntSetError('مشکلی در شبکه وجود دارد')
|
||||
}finally {
|
||||
this.modalLoading = false;
|
||||
}
|
||||
|
||||
},
|
||||
closeModal(){
|
||||
this.visible = false
|
||||
},
|
||||
async Active(id){
|
||||
try{
|
||||
await axios.put(`admin/customer/${id}`,{data:{active:true}})
|
||||
this.$refs.customer.fetch()
|
||||
this.$ntSet()
|
||||
}catch ({message}) {
|
||||
this.$ntSetError(message)
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
async unActive(id){
|
||||
try{
|
||||
await axios.put(`admin/customer/${id}`,{data:{active:false}})
|
||||
this.$refs.customer.fetch()
|
||||
this.$ntSet()
|
||||
}catch ({message}) {
|
||||
this.$ntSetError(message)
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getColTable = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
[dir] .ant-modal-footer {
|
||||
padding: 10px 16px;
|
||||
background: transparent;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
border-radius: 0 0 6px 6px;
|
||||
display: none;
|
||||
}
|
||||
[dir=rtl] .ant-modal-footer {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,14 +0,0 @@
|
||||
import XTbl,{Xtc} from '../../../components/x-table/index';
|
||||
const tbl = new XTbl('/admin/customer/deactive', 'مشاهده درخواست های فعالسازی اکانت');
|
||||
|
||||
tbl.add(new Xtc('name', 'نام مشتری').filterText())
|
||||
tbl.add(new Xtc('mobile', 'شماره موبایل').filterNumber())
|
||||
tbl.add(new Xtc('sts_str', 'اهرازهویت').filterSelect())
|
||||
tbl.add(new Xtc('meta.reason_active', 'توضیحات ').filterText())
|
||||
tbl.add(new Xtc('created_at', 'تاریخ').filterDate())
|
||||
tbl.add(new Xtc('reason_deactive', 'توضیح مدیر').filterText())
|
||||
tbl.add(new Xtc('acceptor_id', 'مدیر غیرفعال کننده').filterText())
|
||||
tbl.add(new Xtc('', 'امکانات').noSort().renderSlot('names'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import XTbl,{Xtc} from '../../../components/x-table/index';
|
||||
|
||||
const tbl = new XTbl('/admin/customer/table', 'جدول مشتریان');
|
||||
|
||||
tbl.add(new Xtc('mobile', 'شماره موبایل').filterNumber())
|
||||
tbl.add(new Xtc('name', 'نام مشتری').filterText())
|
||||
tbl.add(new Xtc('avatar', 'عکس پروفایل').hidden().filterSwitch().renderSlot('image'))
|
||||
tbl.add(new Xtc('ncode', 'شماره ملی').filterNumber())
|
||||
tbl.add(new Xtc('email', 'ایمیل').filterText())
|
||||
tbl.add(new Xtc('active', 'وضعیت اکانت').filterSelect().renderSlot('active'))
|
||||
tbl.add(new Xtc('total_adv', 'تعداد آگهی').filterNumber())
|
||||
tbl.add(new Xtc('caj', 'تاریخ عضویت').hidden().filterDate())
|
||||
// tbl.add(new-x-table Xtc('adv', 'دسته های ثبت آگهی').renderSlot('title_collection'))
|
||||
tbl.add(new Xtc('opt', 'عملیات').noSort().renderSlot('names'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
import XTbl,{Xtc} from '../../../components/x-table/index';
|
||||
const tbl = new XTbl('/admin/customer/revision', 'مشاهده درخواست های اهرازهویت');
|
||||
|
||||
tbl.add(new Xtc('name', 'نام مشتری').filterText())
|
||||
tbl.add(new Xtc('mobile', 'شماره موبایل').filterNumber())
|
||||
tbl.add(new Xtc('sts_str', 'وضعیت').filterSelect())
|
||||
tbl.add(new Xtc('caj', 'تاریخ').filterDate())
|
||||
tbl.add(new Xtc('acceptor_id', 'مدیرتاییدکننده').filterText())
|
||||
tbl.add(new Xtc('score_p', 'امتیاز پرداختنی'))
|
||||
tbl.add(new Xtc('', 'عملیات').noSort().renderSlot('names'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,496 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ECommerceCheckout.vue
|
||||
Description: eCommerce Checkout page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="ecommerce-checkout-demo">
|
||||
<form-wizard
|
||||
ref="checkoutWizard"
|
||||
color="rgba(var(--vs-primary), 1)"
|
||||
:title="null"
|
||||
:subtitle="null"
|
||||
:hide-buttons="true">
|
||||
|
||||
<!-- tab 1 content -->
|
||||
<tab-content title="Cart" icon="feather icon-shopping-cart" class="mb-5">
|
||||
|
||||
<!-- IF CART HAVE ITEMS -->
|
||||
<div class="vx-row" v-if="cartItems.length">
|
||||
|
||||
<!-- LEFT COL -->
|
||||
<div class="vx-col lg:w-2/3 w-full relative">
|
||||
<div class="items-list-view" v-for="(item, index) in cartItems" :key="item.objectID">
|
||||
<item-list-view :item="item" class="mb-base">
|
||||
|
||||
<!-- SLOT: ITEM META -->
|
||||
<template slot="item-meta">
|
||||
<h6
|
||||
class="item-name font-semibold mb-1 cursor-pointer hover:text-primary"
|
||||
@click="$router.push({name: 'ecommerce-item-detail-view', params: {item_id: item.objectID }}).catch(() => {})">{{ item.name }}</h6>
|
||||
<p class="text-sm mb-2">By <span class="font-semibold cursor-pointer">{{ item.brand }}</span></p>
|
||||
<p class="text-success text-sm">In Stock</p>
|
||||
|
||||
<p class="mt-4 font-bold text-sm">Quantity</p>
|
||||
<vs-input-number min="1" max="10" :value="item.quantity" @input="updateItemQuantity($event, index)" class="inline-flex" />
|
||||
|
||||
<p class="font-medium text-grey mt-4">Delivery by, {{ item.delivery_date }}</p>
|
||||
<p class="text-success font-medium">{{ item.discount_in_percentage }}% off {{ item.offers_count }} offers Available</p>
|
||||
</template>
|
||||
|
||||
<!-- SLOT: ACTION BUTTONS -->
|
||||
<template slot="action-buttons">
|
||||
|
||||
<!-- PRIMARY BUTTON: REMOVE -->
|
||||
<div class="item-view-primary-action-btn p-3 rounded-lg flex flex-grow items-center justify-center cursor-pointer mb-3" @click="removeItemFromCart(item)">
|
||||
<feather-icon icon="XIcon" svgClasses="h-4 w-4" />
|
||||
<span class="text-sm font-semibold ml-2">REMOVE</span>
|
||||
</div>
|
||||
|
||||
<!-- SECONDARY BUTTON: MOVE-TO/VIEW-IN WISHLIST -->
|
||||
<div class="item-view-secondary-action-btn bg-primary p-3 rounded-lg flex flex-grow items-center justify-center text-white cursor-pointer" @click="wishListButtonClicked(item)">
|
||||
<feather-icon icon="HeartIcon" :svgClasses="[{'text-white fill-current': isInWishList(item.objectID)}, 'h-4 w-4']" />
|
||||
<span class="text-sm font-semibold ml-2" v-if="isInWishList(item.objectID)">WISHLIST</span>
|
||||
<span class="text-sm font-semibold ml-2" v-else>WISHLIST</span>
|
||||
</div>
|
||||
</template>
|
||||
</item-list-view>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RIGHT COL -->
|
||||
<div class="vx-col lg:w-1/3 w-full">
|
||||
<vx-card>
|
||||
<p class="text-grey mb-3">Options</p>
|
||||
<div class="flex justify-between">
|
||||
<span class="font-semibold">Coupons</span>
|
||||
<span class="font-medium text-primary cursor-pointer">Apply</span>
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<p class="font-semibold mb-3">Price Details</p>
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="text-grey">Total MRP</span>
|
||||
<span>$598</span>
|
||||
</div>
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="text-grey">Bag Discount</span>
|
||||
<span class="text-success">-25$</span>
|
||||
</div>
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="text-grey">Estimated Tax</span>
|
||||
<span>$1.3</span>
|
||||
</div>
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="text-grey">EMI Eligibility</span>
|
||||
<a href="#" class="text-primary">Details</a>
|
||||
</div>
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="text-grey">Delivery Charges</span>
|
||||
<span class="text-success">Free</span>
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<div class="flex justify-between font-semibold mb-3">
|
||||
<span>Total</span>
|
||||
<span>$574.3</span>
|
||||
</div>
|
||||
|
||||
<vs-button class="w-full" @click="$refs.checkoutWizard.nextTab()">PLACE ORDER</vs-button>
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IF NO ITEMS IN CART -->
|
||||
<vx-card title="You don't have any items in your cart." v-else>
|
||||
<vs-button @click="$router.push('/apps/eCommerce/shop').catch(() => {})">Browse Shop</vs-button>
|
||||
</vx-card>
|
||||
|
||||
</tab-content>
|
||||
|
||||
<!-- tab 2 content -->
|
||||
<tab-content title="Address" icon="feather icon-home" class="mb-5">
|
||||
|
||||
<div class="vx-row">
|
||||
|
||||
<!-- LEFT COL: NEW ADDRESS -->
|
||||
<div class="vx-col lg:w-2/3 w-full">
|
||||
<vx-card title="Add New Address" subtitle="Be sure to check "Deliver to this address" when you have finished" class="mb-base">
|
||||
|
||||
<form data-vv-scope="add-new-address">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col sm:w-1/2 w-full">
|
||||
|
||||
<vs-input
|
||||
v-validate="'required|alpha_spaces'"
|
||||
data-vv-as="field"
|
||||
name="fullName"
|
||||
label="Full Name:"
|
||||
v-model="fullName"
|
||||
class="w-full mt-5" />
|
||||
<span v-show="errors.has('add-new-x-table-address.fullName')" class="text-danger">{{ errors.first('add-new-x-table-address.fullName') }}</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="vx-col sm:w-1/2 w-full">
|
||||
|
||||
<vs-input
|
||||
v-validate="'required|digits:10'"
|
||||
name="mobileNum"
|
||||
label="Mobile Number:"
|
||||
v-model="mobileNum"
|
||||
class="w-full mt-5" />
|
||||
<span v-show="errors.has('add-new-x-table-address.mobileNum')" class="text-danger">{{ errors.first('add-new-x-table-address.mobileNum') }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="vx-row">
|
||||
|
||||
|
||||
<div class="vx-col sm:w-1/2 w-full">
|
||||
|
||||
<vs-input
|
||||
v-validate="'required'"
|
||||
name="houseNum"
|
||||
label="Flat, House No:"
|
||||
v-model="houseNum"
|
||||
class="w-full mt-5" />
|
||||
<span v-show="errors.has('add-new-x-table-address.houseNum')" class="text-danger">{{ errors.first('add-new-x-table-address.houseNum') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vx-col sm:w-1/2 w-full">
|
||||
|
||||
<vs-input
|
||||
name="landmark"
|
||||
label="Landmark e.g. near apollo hospital:"
|
||||
v-model="landmark"
|
||||
class="w-full mt-5" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="vx-row">
|
||||
|
||||
<div class="vx-col sm:w-1/2 w-full">
|
||||
|
||||
<vs-input
|
||||
v-validate="'required'"
|
||||
name="city"
|
||||
label="Town/City:"
|
||||
v-model="city"
|
||||
class="w-full mt-5" />
|
||||
<span v-show="errors.has('add-new-x-table-address.city')" class="text-danger">{{ errors.first('add-new-x-table-address.city') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vx-col sm:w-1/2 w-full">
|
||||
<vs-input
|
||||
v-validate="'required|min:3|max:6|numeric'"
|
||||
name="pincode"
|
||||
label="Pincode:"
|
||||
v-model="pincode"
|
||||
class="w-full mt-5" />
|
||||
<span v-show="errors.has('add-new-x-table-address.pincode')" class="text-danger">{{ errors.first('add-new-x-table-address.pincode') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-row">
|
||||
|
||||
|
||||
<div class="vx-col sm:w-1/2 w-full">
|
||||
|
||||
<vs-input
|
||||
v-validate="'required'"
|
||||
name="state"
|
||||
label="State:"
|
||||
v-model="state"
|
||||
class="w-full mt-5" />
|
||||
<span v-show="errors.has('add-new-x-table-address.state')" class="text-danger">{{ errors.first('add-new-x-table-address.state') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vx-col sm:w-1/2 w-full">
|
||||
|
||||
<vs-select label="Address Type:" v-model="addressType" class="w-full mt-5">
|
||||
<vs-select-item :key="index" :value="item.value" :text="item.text" v-for="(item,index) in addressTypeOptions" />
|
||||
</vs-select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<vs-button class="mt-6 ml-auto flex" @click.prevent="submitNewAddressForm">SAVE AND DELIVER HERE</vs-button>
|
||||
</form>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
<!-- RIGHT COL: CONTINUE WITH SAVED ADDRESS -->
|
||||
<div class="vx-col lg:w-1/3 w-full">
|
||||
<vx-card title="John Doe">
|
||||
<div>
|
||||
<p>9447 Glen Eagles Drive</p>
|
||||
<p>Lewis Center, OH 43035</p>
|
||||
<p class="my-4">UTC-5: Eastern Standard Time (EST)</p>
|
||||
<p>202-555-0140</p>
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<vs-button class="w-full" @click="$refs.checkoutWizard.nextTab()">DELIVER TO THIS ADDRESS</vs-button>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</tab-content>
|
||||
|
||||
<!-- tab 3 content -->
|
||||
<tab-content title="Payment" icon="feather icon-credit-card" class="mb-5">
|
||||
|
||||
<div class="vx-row">
|
||||
|
||||
<!-- LEFT COL: PAYMENT OPTIONS -->
|
||||
<div class="vx-col lg:w-2/3 w-full">
|
||||
<vx-card title="Payment Options" subtitle="Be sure to click on correct payment option" class="mb-base">
|
||||
|
||||
<div class="mt-3">
|
||||
<ul>
|
||||
<!-- OPTION 1 -->
|
||||
<li>
|
||||
<!-- CARD DETAILS -->
|
||||
<div class="flex flex-wrap justify-between items-center">
|
||||
<vs-radio v-model="paymentMethod" vs-value="debit-card">
|
||||
<div class="flex items-center">
|
||||
<img src="@/assets/images/pages/eCommerce/bank.png" alt="bank-logo" height="40" width="50" class="inline-flex">
|
||||
<span>US Unlocked Debit Card 12XX XXXX XXXX 0000</span>
|
||||
</div>
|
||||
</vs-radio>
|
||||
<span>John Doe</span>
|
||||
<span>11/2020</span>
|
||||
</div>
|
||||
|
||||
<!-- CVV BLOCK -->
|
||||
<form data-vv-scope="cvv-form">
|
||||
<div class="flex items-center flex-wrap">
|
||||
<span class="mt-4">Enter CVV: </span>
|
||||
<vs-input
|
||||
v-validate="'required|digits:3'"
|
||||
name="cvv"
|
||||
v-model="cvv"
|
||||
class="mr-3 ml-2 mt-4" />
|
||||
<vs-button class="mt-4" @click.prevent="makePayment" :disabled="false">CONTINUE</vs-button>
|
||||
</div>
|
||||
<span v-show="errors.has('cvv-form.cvv')" class="text-danger ml-24">{{ errors.first('cvv-form.cvv') }}</span>
|
||||
</form>
|
||||
</li>
|
||||
|
||||
<vs-divider class="my-6" />
|
||||
|
||||
<!-- OPTION 2 -->
|
||||
<li>
|
||||
<vs-radio v-model="paymentMethod" vs-value="credit-debit-atmCard">Credit / Debit / ATM Card</vs-radio>
|
||||
</li>
|
||||
|
||||
<!-- OPTION 3 -->
|
||||
<li class="mt-2">
|
||||
<vs-radio v-model="paymentMethod" vs-value="netBanking">Net Banking</vs-radio>
|
||||
</li>
|
||||
|
||||
<!-- OPTION 4 -->
|
||||
<li class="mt-2">
|
||||
<vs-radio v-model="paymentMethod" vs-value="emi">EMI (Easy Installment)</vs-radio>
|
||||
</li>
|
||||
|
||||
<!-- OPTION 5 -->
|
||||
<li class="mt-2">
|
||||
<vs-radio v-model="paymentMethod" vs-value="cashOnDelivery">Cash On Delivery</vs-radio>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- GIFT CARD -->
|
||||
<div class="inline-flex items-center cursor-pointer">
|
||||
<feather-icon icon="PlusSquareIcon" class="mr-2" svgClasses="h-6 w-6" />
|
||||
<span>Add Gift Card</span>
|
||||
</div>
|
||||
</div>
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
<!-- RIGHT COL: PRICE -->
|
||||
<div class="vx-col lg:w-1/3 w-full">
|
||||
<vx-card title="Price Details">
|
||||
|
||||
<div class="flex justify-between mb-2">
|
||||
<span>Price 3 Items</span>
|
||||
<span class="font-semibold">$699.30</span>
|
||||
</div>
|
||||
<div class="flex justify-between mb-2">
|
||||
<span>Delivery Charges</span>
|
||||
<span class="text-success">Free</span>
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span>Amount Payable</span>
|
||||
<span class="font-semibold">$699.30</span>
|
||||
</div>
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
</tab-content>
|
||||
|
||||
</form-wizard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { FormWizard, TabContent } from 'vue-form-wizard'
|
||||
import 'vue-form-wizard/dist/vue-form-wizard.min.css'
|
||||
const ItemListView = () => import('./components/ItemListView.vue')
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
|
||||
// TAB 2
|
||||
fullName: '',
|
||||
mobileNum: '',
|
||||
pincode: '',
|
||||
houseNum: '',
|
||||
area: '',
|
||||
landmark: '',
|
||||
city: '',
|
||||
state: '',
|
||||
addressType: 1,
|
||||
addressTypeOptions: [
|
||||
{ text: 'Home', value: 1 },
|
||||
{ text: 'Office', value: 2 }
|
||||
],
|
||||
|
||||
// TAB 3
|
||||
paymentMethod: 'debit-card',
|
||||
cvv: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cartItems () {
|
||||
return this.$store.state.eCommerce.cartItems.slice().reverse()
|
||||
},
|
||||
isInWishList () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInWishList'](itemId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
// TAB 1
|
||||
removeItemFromCart (item) {
|
||||
this.$store.dispatch('eCommerce/toggleItemInCart', item)
|
||||
},
|
||||
wishListButtonClicked (item) {
|
||||
// Toggle in Wish List
|
||||
if (this.isInWishList(item.objectID)) this.$router.push('/apps/eCommerce/wish-list').catch(() => {})
|
||||
else {
|
||||
this.toggleItemInWishList(item)
|
||||
this.removeItemFromCart(item)
|
||||
}
|
||||
},
|
||||
toggleItemInWishList (item) {
|
||||
this.$store.dispatch('eCommerce/toggleItemInWishList', item)
|
||||
},
|
||||
updateItemQuantity (event, index) {
|
||||
const itemIndex = Math.abs(index + 1 - this.cartItems.length)
|
||||
this.$store.dispatch('eCommerce/updateItemQuantity', { quantity: event, index: itemIndex })
|
||||
},
|
||||
|
||||
// TAB 2
|
||||
submitNewAddressForm () {
|
||||
return new Promise(() => {
|
||||
this.$validator.validateAll('add-new-x-table-address').then(result => {
|
||||
if (result) {
|
||||
// if form have no errors
|
||||
this.$refs.checkoutWizard.nextTab()
|
||||
} else {
|
||||
this.$vs.notify({
|
||||
title: 'Error',
|
||||
text: 'Please enter valid details',
|
||||
color: 'warning',
|
||||
iconPack: 'feather',
|
||||
icon: 'icon-alert-circle'
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// TAB 3
|
||||
makePayment () {
|
||||
return new Promise(() => {
|
||||
this.$validator.validateAll('cvv-form').then(result => {
|
||||
if (result) {
|
||||
// if form have no errors
|
||||
this.$vs.notify({
|
||||
title: 'Success',
|
||||
text: 'Payment received successfully',
|
||||
color: 'success',
|
||||
iconPack: 'feather',
|
||||
icon: 'icon-check'
|
||||
})
|
||||
} else {
|
||||
this.$vs.notify({
|
||||
title: 'Error',
|
||||
text: 'Please enter valid details',
|
||||
color: 'warning',
|
||||
iconPack: 'feather',
|
||||
icon: 'icon-alert-circle'
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ItemListView,
|
||||
FormWizard,
|
||||
TabContent
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#ecommerce-checkout-demo {
|
||||
.item-view-primary-action-btn {
|
||||
color: #2c2c2c !important;
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.vue-form-wizard {
|
||||
padding-bottom: 0;
|
||||
|
||||
::v-deep .wizard-header {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::v-deep .wizard-tab-content {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
padding-bottom: 0;
|
||||
|
||||
.wizard-tab-container{
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,467 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ECommerceItemDetail.vue
|
||||
Description: eCommerce Item Detail page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="item-detail-page">
|
||||
|
||||
<vs-alert color="danger" title="Error Fetching Product Data" :active.sync="error_occured">
|
||||
<span>{{ error_msg }}. </span>
|
||||
<span>
|
||||
<span>Check </span><router-link :to="{name:'ecommerce-shop'}" class="text-inherit underline">All Items</router-link>
|
||||
</span>
|
||||
</vs-alert>
|
||||
|
||||
<vx-card v-if="item_data" :key="item_data.objectID">
|
||||
|
||||
|
||||
<template slot="no-body">
|
||||
|
||||
<div class="item-content">
|
||||
|
||||
<!-- Item Main Info -->
|
||||
<div class="product-details p-6">
|
||||
<div class="vx-row mt-6">
|
||||
<div class="vx-col md:w-2/5 w-full flex items-center justify-center">
|
||||
<div class="product-img-container w-3/5 mx-auto mb-10 md:mb-0">
|
||||
<img src="https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/products/01.png" :alt="item_data.name" class="responsive">
|
||||
|
||||
<!--
|
||||
UnComment Below line for true flow
|
||||
<img :src="item_data.image" :alt="item_data.name" class="responsive">
|
||||
|
||||
Remove above img tag which is for demo purpose in actual flow
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item Content -->
|
||||
<div class="vx-col md:w-3/5 w-full">
|
||||
|
||||
<h3>{{ item_data.name }}</h3>
|
||||
|
||||
<p class="my-2">
|
||||
<span class="mr-2">by</span>
|
||||
<span>{{ item_data.brand }}</span>
|
||||
</p>
|
||||
<p class="flex items-center flex-wrap">
|
||||
<span class="text-2xl leading-none font-medium text-primary mr-4 mt-2">${{ item_data.price }}</span>
|
||||
<span class="pl-4 mr-2 mt-2 border border-solid d-theme-border-grey-light border-t-0 border-b-0 border-r-0"><star-rating :show-rating="false" :rating="item_data.rating" :star-size="20" read-only /></span>
|
||||
<span class="cursor-pointer leading-none mt-2">424 ratings</span>
|
||||
</p>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<p>{{ item_data.description }}</p>
|
||||
|
||||
<vs-list class="product-sales-meta-list px-0 pt-4">
|
||||
<vs-list-item
|
||||
v-if="item_data.free_shipping"
|
||||
class="p-0 border-none"
|
||||
title="Free Sheeping"
|
||||
icon-pack="feather"
|
||||
icon="icon-truck" />
|
||||
<vs-list-item class="p-0 border-none" title="EMI options available" icon-pack="feather" icon="icon-dollar-sign"></vs-list-item>
|
||||
</vs-list>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- Color -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<span class="text-xl font-medium">Color</span>
|
||||
<div class="flex flex-wrap items-center mt-2">
|
||||
<div
|
||||
:class="{'border-transparent': opt_color != color}"
|
||||
class="color-radio rounded-full mx-1 border-2 border-solid cursor-pointer relative"
|
||||
:style="itemColor({color: color, style: ['borderColor']})"
|
||||
v-for="color in available_item_colors"
|
||||
:key="color"
|
||||
@click="opt_color=color">
|
||||
<div class="h-6 w-6 rounded-full absolute" :style="itemColor({color: color, style: ['backgroundColor']})"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /Color -->
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- Quantity -->
|
||||
<div class="vx-row">
|
||||
|
||||
<div class="vx-col w-full">
|
||||
<p class="my-2">
|
||||
<span>Available</span>
|
||||
<span class="mx-2">-</span>
|
||||
<span class="text-success">In Stock</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="vx-col w-full">
|
||||
<div class="flex flex-wrap items-start mb-4">
|
||||
|
||||
<!-- Add To Cart Button -->
|
||||
<vs-button
|
||||
class="mr-4 mb-4"
|
||||
icon-pack="feather"
|
||||
icon="icon-shopping-cart"
|
||||
v-if="!isInCart(item_data.objectID)"
|
||||
@click="toggleItemInCart(item_data)">
|
||||
ADD TO CART
|
||||
</vs-button>
|
||||
|
||||
<vs-button
|
||||
v-else
|
||||
class="mr-4 mb-4"
|
||||
icon-pack="feather"
|
||||
icon="icon-shopping-cart"
|
||||
@click="$router.push({name: 'ecommerce-checkout'}).catch(err => {})">
|
||||
VIEW IN CART
|
||||
</vs-button>
|
||||
<!-- /Add To Cart Button -->
|
||||
|
||||
<!-- Wishlist Button -->
|
||||
<vs-button
|
||||
v-if="isInWishList(item_data.objectID)"
|
||||
key="filled"
|
||||
class="mb-4"
|
||||
icon-pack="feather"
|
||||
icon="icon-heart"
|
||||
color="danger"
|
||||
@click="toggleItemInWishList(item_data)">
|
||||
WHISHLIST
|
||||
</vs-button>
|
||||
|
||||
<vs-button
|
||||
v-else
|
||||
key="border"
|
||||
class="mb-4"
|
||||
type="border"
|
||||
icon-pack="feather"
|
||||
icon="icon-heart"
|
||||
color="danger"
|
||||
@click="toggleItemInWishList(item_data)">
|
||||
WHISHLIST
|
||||
</vs-button>
|
||||
<!-- /Wishlist Button -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /Quantity -->
|
||||
|
||||
<div class="vx-row">
|
||||
<div class="vx-col flex flex-wrap items-center">
|
||||
<vs-button class="mr-4" type="border" icon-pack="feather" color="#1551b1" icon="icon-facebook" radius></vs-button>
|
||||
<vs-button class="mr-4" type="border" icon-pack="feather" color="#00aaff" icon="icon-twitter" radius></vs-button>
|
||||
<vs-button class="mr-4" type="border" icon-pack="feather" color="#c4302b" icon="icon-youtube" radius></vs-button>
|
||||
<vs-button class="mr-4" type="border" icon-pack="feather" color="#405DE6" icon="icon-instagram" radius></vs-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product Feature/Meta Row -->
|
||||
<div class="py-24 mb-16 mt-10 text-center item-features">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col md:w-1/3 w-full">
|
||||
<div class="w-64 mx-auto mb-16 md:mb-0">
|
||||
<feather-icon icon="AwardIcon" svgClasses="h-12 w-12 text-primary stroke-current" class="block mb-4" />
|
||||
<span class="font-semibold text-lg">100% Original</span>
|
||||
<p class="mt-2">Chocolate bar candy canes ice cream toffee cookie halvah.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vx-col md:w-1/3 w-full">
|
||||
<div class="w-64 mx-auto mb-16 md:mb-0">
|
||||
<feather-icon icon="ClockIcon" svgClasses="h-12 w-12 text-primary stroke-current" class="block mb-4" />
|
||||
<span class="font-semibold text-lg">10 Day Replacement</span>
|
||||
<p class="mt-2">Marshmallow biscuit donut dragée fruitcake wafer.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vx-col md:w-1/3 w-full">
|
||||
<div class="w-64 mx-auto">
|
||||
<feather-icon icon="ShieldIcon" svgClasses="h-12 w-12 text-primary stroke-current" class="block mb-4" />
|
||||
<span class="font-semibold text-lg">1 Year Warranty</span>
|
||||
<p class="mt-2">Cotton candy gingerbread cake I love sugar sweet.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Related Products -->
|
||||
<div class="related-products text-center px-6">
|
||||
|
||||
<div class="related-headings mb-8 text-center">
|
||||
<h2 class="uppercase">Related Products</h2>
|
||||
<p>People also search for this items</p>
|
||||
</div>
|
||||
<swiper :options="swiperOption" :dir="$vs.rtl ? 'rtl' : 'ltr'" :key="$vs.rtl" class="related-product-swiper px-12 py-6">
|
||||
<swiper-slide v-for="item in related_items" :key="item.objectId" class="p-6 rounded cursor-pointer">
|
||||
|
||||
<!-- Item Heading -->
|
||||
<div class="item-heading mb-4">
|
||||
<p class="text-lg font-semibold truncate">{{ item.name }}</p>
|
||||
<p class="text-sm">
|
||||
<span class="mr-2">by</span>
|
||||
<span>{{ item.brand }}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Item Image -->
|
||||
<div class="img-container w-32 mx-auto my-base">
|
||||
<img class="responsive" :src="item.image" :alt="item.name">
|
||||
</div>
|
||||
|
||||
<!-- Item Meta -->
|
||||
<div class="item-meta">
|
||||
<star-rating :show-rating="false" :rating="item.rating" :star-size="14" class="justify-center" read-only />
|
||||
<p class="text-lg font-medium text-primary">${{ item.price }}</p>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
<div class="swiper-button-prev" slot="button-prev"></div>
|
||||
<div class="swiper-button-next" slot="button-next"></div>
|
||||
</swiper>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</vx-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import 'swiper/dist/css/swiper.min.css'
|
||||
import { swiper, swiperSlide } from 'vue-awesome-swiper'
|
||||
import algoliasearch from 'algoliasearch/lite'
|
||||
import StarRating from 'vue-star-rating'
|
||||
|
||||
export default{
|
||||
components: {
|
||||
swiper,
|
||||
swiperSlide,
|
||||
StarRating
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
algolia_index: algoliasearch(
|
||||
'latency',
|
||||
'6be0576ff61c053d5f9a3225e2a90f76'
|
||||
).initIndex('instant_search'),
|
||||
item_data: null,
|
||||
error_occured: false,
|
||||
error_msg: '',
|
||||
|
||||
// Related Products Swiper
|
||||
swiperOption: {
|
||||
slidesPerView: 5,
|
||||
spaceBetween: 55,
|
||||
breakpoints: {
|
||||
1600: {
|
||||
slidesPerView: 4,
|
||||
spaceBetween: 55
|
||||
},
|
||||
1300: {
|
||||
slidesPerView: 3,
|
||||
spaceBetween: 55
|
||||
},
|
||||
900: {
|
||||
slidesPerView: 2,
|
||||
spaceBetween: 55
|
||||
},
|
||||
640: {
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 55
|
||||
}
|
||||
},
|
||||
navigation: {
|
||||
nextEl: '.swiper-button-next',
|
||||
prevEl: '.swiper-button-prev'
|
||||
}
|
||||
},
|
||||
|
||||
// Below is data which is common in any item
|
||||
// Algolia's dataSet don't provide this kind of data. So, here's dummy data for demo
|
||||
available_item_colors: ['#7367F0', '#28C76F', '#EA5455', '#FF9F43', '#1E1E1E'],
|
||||
opt_color: '#7367F0',
|
||||
is_hearted: false,
|
||||
|
||||
related_items: [
|
||||
{
|
||||
'name' : 'Apple - Apple Watch Series 1 42mm Space Gray Aluminum Case Black Sport Band - Space Gray Aluminum',
|
||||
'brand' : 'Apple',
|
||||
'price' : 229,
|
||||
'image' : 'https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/products/01.png',
|
||||
'rating' : 4,
|
||||
'objectID' : '5546604'
|
||||
},
|
||||
{
|
||||
'name' : 'Beats by Dr. Dre - Powerbeats2 Wireless Earbud Headphones - Black/Red',
|
||||
'brand' : 'Beats by Dr. Dre',
|
||||
'price' : 199.99,
|
||||
'image' : 'https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/products/08.png',
|
||||
'rating' : 4,
|
||||
'objectID' : '5565002'
|
||||
},
|
||||
{
|
||||
'name' : 'Amazon - Fire TV Stick with Alexa Voice Remote - Black',
|
||||
'brand' : 'Amazon',
|
||||
'price' : 39.99,
|
||||
'image' : 'https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/products/03.png',
|
||||
'rating' : 4,
|
||||
'objectID' : '5477500'
|
||||
},
|
||||
{
|
||||
'name' : 'Apple - Apple Watch Nike+ 42mm Silver Aluminum Case Silver/Volt Nike Sport Band - Silver Aluminum',
|
||||
'brand' : 'Apple',
|
||||
'price' : 399,
|
||||
'image' : 'https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/products/07.png',
|
||||
'rating' : 4,
|
||||
'objectID' : '5547700'
|
||||
},
|
||||
{
|
||||
'name' : 'Google - Chromecast Ultra - Black',
|
||||
'brand' : 'Google',
|
||||
'price' : 69.99,
|
||||
'image' : 'https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/products/05.png',
|
||||
'rating' : 4,
|
||||
'objectID' : '5578628'
|
||||
},
|
||||
{
|
||||
'name' : 'Beats by Dr. Dre - Beats EP Headphones - White',
|
||||
'brand' : 'Beats by Dr. Dre',
|
||||
'price' : 129.99,
|
||||
'image' : 'https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/products/02.png',
|
||||
'rating' : 4,
|
||||
'objectID' : '5577781'
|
||||
},
|
||||
{
|
||||
'name' : 'LG - 40" Class (39.5" Diag.) - LED - 1080p - HDTV - Black',
|
||||
'brand' : 'LG',
|
||||
'price' : 279.99,
|
||||
'image' : 'https://pixinvent.com/demo/vuexy-vuejs-admin-dashboard-template/products/09.png',
|
||||
'rating' : 4,
|
||||
'objectID' : '5613404'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
item_qty () {
|
||||
const item = this.$store.getters['eCommerce/getCartItem'](this.item_data.objectID)
|
||||
return Object.keys(item).length ? item.quantity : 1
|
||||
},
|
||||
itemColor () {
|
||||
return (obj) => {
|
||||
const style_obj = {}
|
||||
|
||||
obj.style.forEach(p => { style_obj[p] = obj.color })
|
||||
|
||||
return style_obj
|
||||
}
|
||||
},
|
||||
isInWishList () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInWishList'](itemId)
|
||||
},
|
||||
isInCart () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInCart'](itemId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleItemInWishList (item) {
|
||||
this.$store.dispatch('eCommerce/toggleItemInWishList', item)
|
||||
},
|
||||
toggleItemInCart (item) {
|
||||
this.$store.dispatch('eCommerce/toggleItemInCart', item)
|
||||
},
|
||||
fetch_item_details (id) {
|
||||
this.algolia_index.getObject(id, (err, content) => {
|
||||
if (err) {
|
||||
this.error_occured = true
|
||||
this.error_msg = err.message
|
||||
console.error(err)
|
||||
} else {
|
||||
this.item_data = content
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.fetch_item_details(this.$route.params.item_id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@import "@/assets/scss/vuexy/_variables.scss";
|
||||
|
||||
#item-detail-page {
|
||||
.color-radio {
|
||||
height: 2.28rem;
|
||||
width: 2.28rem;
|
||||
|
||||
> div {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.item-features {
|
||||
background-color: #f7f7f7;
|
||||
|
||||
.theme-dark & {
|
||||
background-color: $theme-dark-secondary-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.product-sales-meta-list {
|
||||
.vs-list--icon {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.related-product-swiper {
|
||||
// padding-right: 2rem;
|
||||
// padding-left: 2rem;
|
||||
|
||||
.swiper-wrapper {
|
||||
padding-bottom: 2rem;
|
||||
|
||||
> .swiper-slide {
|
||||
background-color: #f7f7f7;
|
||||
box-shadow: 0 4px 18px 0 rgba(0,0,0,0.1), 0 5px 12px 0 rgba(0,0,0,0.08) !important;
|
||||
|
||||
.theme-dark & {
|
||||
background-color: $theme-light-dark-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-button-next,
|
||||
.swiper-button-prev {
|
||||
transform: scale(.5);
|
||||
filter: hue-rotate(40deg);
|
||||
}
|
||||
|
||||
.swiper-button-next {
|
||||
right: 0
|
||||
}
|
||||
|
||||
.swiper-button-prev {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,490 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ECommerceShop.vue
|
||||
Description: eCommerce Shop Page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<ais-instant-search
|
||||
:search-client="searchClient"
|
||||
index-name="instant_search" id="algolia-instant-search-demo">
|
||||
|
||||
<!-- AIS CONFIG -->
|
||||
<ais-configure :hits-per-page.camel="9" />
|
||||
|
||||
<div class="algolia-header mb-4">
|
||||
<div class="flex md:items-end items-center justify-between flex-wrap">
|
||||
<!-- TOGGLE SIDEBAR BUTTON -->
|
||||
<feather-icon
|
||||
class="inline-flex lg:hidden cursor-pointer mr-4"
|
||||
icon="MenuIcon"
|
||||
@click.stop="toggleFilterSidebar" />
|
||||
|
||||
<p class="lg:inline-flex hidden font-semibold algolia-filters-label">Filters</p>
|
||||
|
||||
<div class="flex justify-between items-end flex-grow">
|
||||
<!-- Stats -->
|
||||
<ais-stats>
|
||||
<p slot-scope="{ hitsPerPage, nbPages, nbHits, page, processingTimeMS, query }" class="font-semibold md:block hidden">
|
||||
{{ nbHits }} results found in {{ processingTimeMS }}ms
|
||||
</p>
|
||||
</ais-stats>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
|
||||
<!-- SORTING -->
|
||||
<ais-sort-by :items="[
|
||||
{ value: 'instant_search', label: 'Featured' },
|
||||
{ value: 'instant_search_price_asc', label: 'Lowest Price' },
|
||||
{ value: 'instant_search_price_desc', label: 'Highest Price' },
|
||||
]">
|
||||
<vs-select
|
||||
:value="currentRefinement"
|
||||
slot-scope="{ items, currentRefinement, refine }"
|
||||
@input="(val) => refine(val)"
|
||||
class="mr-4 vs-input-shadow-drop vs-select-no-border d-theme-input-dark-bg w-48">
|
||||
<vs-select-item v-for="item in items" :key="item.value" :value="item.value" :text="item.label" />
|
||||
</vs-select>
|
||||
</ais-sort-by>
|
||||
|
||||
<!-- ITEM VIEW - GRID/LIST -->
|
||||
<div>
|
||||
<feather-icon
|
||||
icon="GridIcon"
|
||||
@click="currentItemView='item-grid-view'"
|
||||
class="p-2 shadow-drop rounded-lg d-theme-dark-bg cursor-pointer"
|
||||
:svgClasses="{'text-primary stroke-current': currentItemView == 'item-grid-view'}" />
|
||||
<feather-icon
|
||||
icon="ListIcon"
|
||||
@click="currentItemView='item-list-view'"
|
||||
class="p-2 ml-4 shadow-drop rounded-lg d-theme-dark-bg cursor-pointer hidden sm:inline-flex"
|
||||
:svgClasses="{'text-primary stroke-current': currentItemView == 'item-list-view'}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="algolia-content-container" class="relative clearfix">
|
||||
<vs-sidebar
|
||||
class="items-no-padding vs-sidebar-rounded background-absolute"
|
||||
parent="#algolia-content-container"
|
||||
:click-not-close="clickNotClose"
|
||||
:hidden-background="clickNotClose"
|
||||
v-model="isFilterSidebarActive">
|
||||
|
||||
<div class="p-6 filter-container">
|
||||
|
||||
<!-- MULTI RANGE -->
|
||||
<h6 class="font-bold mb-3">Multi Range</h6>
|
||||
<ais-numeric-menu attribute="price" :items="numericItems">
|
||||
<ul slot-scope="{ items, refine, createURL }">
|
||||
<li
|
||||
v-for="item in items"
|
||||
:key="item.value"
|
||||
class="flex items-center cursor-pointer py-1"
|
||||
@click="refine(item.value)">
|
||||
|
||||
<feather-icon icon="CircleIcon" :svgClasses="[{ 'text-primary fill-current': item.isRefined}, 'h-5 w-5']" />
|
||||
<span class="ml-2" :class="{'text-primary': item.isRefined}">{{ item.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</ais-numeric-menu>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- PRICE SLIDER -->
|
||||
<h6 class="font-bold mb-3">Price Slider</h6>
|
||||
<ais-range-input attribute="price">
|
||||
<div slot-scope="{ currentRefinement, range, refine }">
|
||||
<vs-slider
|
||||
class="algolia-price-slider"
|
||||
text-fixed="$"
|
||||
:min="range.min"
|
||||
:max="range.max"
|
||||
:value="toValue(currentRefinement, range)"
|
||||
@input="refine({min: $event[0], max: $event[1]})" />
|
||||
</div>
|
||||
</ais-range-input>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- CATEGORIES -->
|
||||
<h6 class="font-bold mb-4">Category</h6>
|
||||
<ais-hierarchical-menu :attributes="algoliaCategories">
|
||||
<div slot-scope="{
|
||||
items,
|
||||
refine,
|
||||
}">
|
||||
<ul>
|
||||
<li v-for="item in items" :key="item.value" class="flex items-center cursor-pointer py-1" @click="refine(item.value)">
|
||||
<feather-icon icon="CircleIcon" :svgClasses="[{ 'text-primary fill-current': item.isRefined}, 'h-5 w-5']" />
|
||||
<span class="ml-2" :class="{'text-primary': item.isRefined}">{{ item.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</ais-hierarchical-menu>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- Brands -->
|
||||
<h6 class="font-bold mb-4">Brand</h6>
|
||||
<ais-refinement-list attribute="brand">
|
||||
<div slot-scope="{
|
||||
items,
|
||||
isFromSearch,
|
||||
refine,
|
||||
}">
|
||||
<ul>
|
||||
<li v-if="isFromSearch && !items.length">No results.</li>
|
||||
<li v-for="item in items" :key="item.value" class="mb-2 flex items-center justify-between">
|
||||
<vs-checkbox v-model="item.isRefined" class="ml-0" @click="refine(item.value)">{{ item.label }}</vs-checkbox>
|
||||
<span>{{ item.count }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</ais-refinement-list>
|
||||
<vs-divider />
|
||||
|
||||
<!-- Rating -->
|
||||
<h6 class="font-bold mb-3">Rating</h6>
|
||||
<ais-rating-menu attribute="rating">
|
||||
<ul slot-scope="{ items, refine, createURL }">
|
||||
<li v-for="item in items" :key="item.value" class="mb-2">
|
||||
<div @click.prevent="refine(item.value)" class="flex justify-between items-center">
|
||||
<div class="flex items-center flex-wrap">
|
||||
<feather-icon icon="StarIcon" :svgClasses="[{'text-warning': full, 'text-grey': !full, 'ml-1' : index}, 'cursor-pointer stroke-current h-6 w-6']" v-for="(full, index) in item.stars" :key="index" />
|
||||
<span class="ml-2">& up</span>
|
||||
</div>
|
||||
<span>({{ item.count }})</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ais-rating-menu>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<ais-clear-refinements class="flex justify-center">
|
||||
<vs-button class="w-full" slot-scope="{ canRefine, refine, createURL }" @click.prevent="refine" :disabled="!canRefine">Remove Filters</vs-button>
|
||||
</ais-clear-refinements>
|
||||
</div>
|
||||
</vs-sidebar>
|
||||
|
||||
<!-- RIGHT COL -->
|
||||
<div :class="{'sidebar-spacer-with-margin': clickNotClose}">
|
||||
|
||||
<!-- SEARCH BAR -->
|
||||
<ais-search-box>
|
||||
<div slot-scope="{ currentRefinement, isSearchStalled, refine }">
|
||||
<div class="relative mb-8">
|
||||
|
||||
<!-- SEARCH INPUT -->
|
||||
<vs-input class="w-full vs-input-shadow-drop vs-input-no-border d-theme-input-dark-bg" placeholder="Search here" v-model="currentRefinement" @input="refine($event)" @keyup.esc="refine('')" size="large" />
|
||||
|
||||
<!-- SEARCH LOADING -->
|
||||
<p :hidden="!isSearchStalled" class="mt-4 text-grey">
|
||||
<feather-icon icon="ClockIcon" svgClasses="w-4 h-4" class="mr-2 align-middle" />
|
||||
<span>Loading...</span>
|
||||
</p>
|
||||
|
||||
<!-- SEARCH ICON -->
|
||||
<div slot="submit-icon" class="absolute top-0 right-0 py-4 px-6" v-show="!currentRefinement">
|
||||
<feather-icon icon="SearchIcon" svgClasses="h-6 w-6" />
|
||||
</div>
|
||||
|
||||
<!-- CLEAR INPUT ICON -->
|
||||
<div slot="reset-icon" class="absolute top-0 right-0 py-4 px-6" v-show="currentRefinement">
|
||||
<feather-icon icon="XIcon" svgClasses="h-6 w-6 cursor-pointer" @click="refine('')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ais-search-box>
|
||||
|
||||
<!-- SEARCH RESULT -->
|
||||
<ais-hits>
|
||||
<div slot-scope="{ items }">
|
||||
|
||||
<!-- GRID VIEW -->
|
||||
<template v-if="currentItemView == 'item-grid-view'">
|
||||
<div class="items-grid-view vx-row match-height">
|
||||
<div class="vx-col lg:w-1/3 sm:w-1/2 w-full" v-for="item in items" :key="item.objectID">
|
||||
|
||||
<item-grid-view :item="item">
|
||||
|
||||
<!-- SLOT: ACTION BUTTONS -->
|
||||
<template slot="action-buttons">
|
||||
<div class="flex flex-wrap">
|
||||
|
||||
<!-- PRIMARY BUTTON: ADD TO WISH LIST -->
|
||||
<div
|
||||
class="item-view-primary-action-btn p-3 flex flex-grow items-center justify-center cursor-pointer"
|
||||
@click="toggleItemInWishList(item)">
|
||||
<feather-icon icon="HeartIcon" :svgClasses="[{'text-danger fill-current' : isInWishList(item.objectID)}, 'h-4 w-4']" />
|
||||
|
||||
<span class="text-sm font-semibold ml-2">WISHLIST</span>
|
||||
</div>
|
||||
|
||||
<!-- SECONDARY BUTTON: ADD-TO/VIEW-IN CART -->
|
||||
<div
|
||||
class="item-view-secondary-action-btn bg-primary p-3 flex flex-grow items-center justify-center text-white cursor-pointer"
|
||||
@click="cartButtonClicked(item)">
|
||||
<feather-icon icon="ShoppingBagIcon" svgClasses="h-4 w-4" />
|
||||
|
||||
<span class="text-sm font-semibold ml-2" v-if="isInCart(item.objectID)">VIEW IN CART</span>
|
||||
<span class="text-sm font-semibold ml-2" v-else>ADD TO CART</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</item-grid-view>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- LIST VIEW -->
|
||||
<template v-else>
|
||||
<div class="items-list-view mb-base" v-for="item in items" :key="item.objectID">
|
||||
|
||||
<item-list-view :item="item">
|
||||
|
||||
<!-- SLOT: ACTION BUTTONS -->
|
||||
<template slot="action-buttons">
|
||||
<div
|
||||
class="item-view-primary-action-btn p-3 rounded-lg flex flex-grow items-center justify-center cursor-pointer mb-3"
|
||||
@click="toggleItemInWishList(item)">
|
||||
<feather-icon icon="HeartIcon" :svgClasses="[{'text-danger fill-current' : isInWishList(item.objectID)}, 'h-4 w-4']" />
|
||||
<span class="text-sm font-semibold ml-2">WISHLIST</span>
|
||||
</div>
|
||||
<div
|
||||
class="item-view-secondary-action-btn bg-primary p-3 rounded-lg flex flex-grow items-center justify-center text-white cursor-pointer"
|
||||
@click="cartButtonClicked(item)">
|
||||
<feather-icon icon="ShoppingBagIcon" svgClasses="h-4 w-4" />
|
||||
|
||||
<span class="text-sm font-semibold ml-2" v-if="isInCart(item.objectID)">VIEW IN CART</span>
|
||||
<span class="text-sm font-semibold ml-2" v-else>ADD TO CART</span>
|
||||
</div>
|
||||
</template>
|
||||
</item-list-view>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</ais-hits>
|
||||
|
||||
<!-- PAGINATION -->
|
||||
<ais-pagination>
|
||||
<div slot-scope="{
|
||||
currentRefinement,
|
||||
nbPages,
|
||||
pages,
|
||||
isFirstPage,
|
||||
isLastPage,
|
||||
refine,
|
||||
createURL
|
||||
}"
|
||||
>
|
||||
|
||||
<vs-pagination
|
||||
|
||||
:total="nbPages"
|
||||
:max="7"
|
||||
:value="currentRefinement + 1"
|
||||
@input="(val) => { refine(val - 1) }" />
|
||||
</div>
|
||||
</ais-pagination>
|
||||
|
||||
<!-- ALGOLIA LOGO -->
|
||||
<img class="flex mt-4 mx-auto h-8" src="@/assets/images/pages/eCommerce/Algolia-logo.png" alt="algolia-logo">
|
||||
</div>
|
||||
</div>
|
||||
</ais-instant-search>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
AisClearRefinements,
|
||||
AisConfigure,
|
||||
AisHierarchicalMenu,
|
||||
AisHits,
|
||||
AisInstantSearch,
|
||||
AisNumericMenu,
|
||||
AisPagination,
|
||||
AisRangeInput,
|
||||
AisRatingMenu,
|
||||
AisRefinementList,
|
||||
AisSearchBox,
|
||||
AisSortBy,
|
||||
AisStats
|
||||
} from 'vue-instantsearch'
|
||||
import algoliasearch from 'algoliasearch/lite'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ItemGridView: () => import('./components/ItemGridView.vue'),
|
||||
ItemListView: () => import('./components/ItemListView.vue'),
|
||||
AisClearRefinements,
|
||||
AisConfigure,
|
||||
AisHierarchicalMenu,
|
||||
AisHits,
|
||||
AisInstantSearch,
|
||||
AisNumericMenu,
|
||||
AisPagination,
|
||||
AisRangeInput,
|
||||
AisRatingMenu,
|
||||
AisRefinementList,
|
||||
AisSearchBox,
|
||||
AisSortBy,
|
||||
AisStats
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
searchClient: algoliasearch(
|
||||
'latency',
|
||||
'6be0576ff61c053d5f9a3225e2a90f76'
|
||||
),
|
||||
// Filter Sidebar
|
||||
isFilterSidebarActive: true,
|
||||
clickNotClose: true,
|
||||
currentItemView: 'item-grid-view',
|
||||
numericItems: [
|
||||
{ label: 'All' },
|
||||
{ label: '<= $10', end: 10 },
|
||||
{ label: '$10 - $100', start: 10, end: 100 },
|
||||
{ label: '$100 - $500', start: 100, end: 500 },
|
||||
{ label: '>= $500', start: 500 }
|
||||
],
|
||||
algoliaCategories: [
|
||||
'hierarchicalCategories.lvl0',
|
||||
'hierarchicalCategories.lvl1',
|
||||
'hierarchicalCategories.lvl2',
|
||||
'hierarchicalCategories.lvl3'
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
toValue () {
|
||||
return (value, range) => [
|
||||
value.min !== null ? value.min : range.min,
|
||||
value.max !== null ? value.max : range.max
|
||||
]
|
||||
},
|
||||
|
||||
// GRID VIEW
|
||||
isInCart () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInCart'](itemId)
|
||||
},
|
||||
isInWishList () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInWishList'](itemId)
|
||||
},
|
||||
windowWidth () { return this.$store.state.windowWidth }
|
||||
},
|
||||
watch: {
|
||||
windowWidth () {
|
||||
this.setSidebarWidth()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setSidebarWidth () {
|
||||
if (this.windowWidth < 992) {
|
||||
this.isFilterSidebarActive = this.clickNotClose = false
|
||||
} else {
|
||||
this.isFilterSidebarActive = this.clickNotClose = true
|
||||
}
|
||||
},
|
||||
|
||||
// GRID VIEW - ACTIONS
|
||||
toggleFilterSidebar () {
|
||||
if (this.clickNotClose) return
|
||||
this.isFilterSidebarActive = !this.isFilterSidebarActive
|
||||
},
|
||||
toggleItemInWishList (item) {
|
||||
this.$store.dispatch('eCommerce/toggleItemInWishList', item)
|
||||
},
|
||||
additemInCart (item) {
|
||||
this.$store.dispatch('eCommerce/additemInCart', item)
|
||||
},
|
||||
cartButtonClicked (item) {
|
||||
this.isInCart(item.objectID) ? this.$router.push('/apps/eCommerce/checkout').catch(() => {}) : this.additemInCart(item)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.setSidebarWidth()
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
#algolia-instant-search-demo {
|
||||
.algolia-header {
|
||||
.algolia-filters-label {
|
||||
width: calc(260px + 2.4rem);
|
||||
}
|
||||
}
|
||||
|
||||
#algolia-content-container {
|
||||
|
||||
.vs-sidebar {
|
||||
position: relative;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.algolia-search-input-right-aligned-icon {
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
.algolia-price-slider {
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
.item-view-primary-action-btn {
|
||||
color: #2c2c2c !important;
|
||||
background-color: #f6f6f6;
|
||||
min-width: 50%;
|
||||
}
|
||||
|
||||
.item-view-secondary-action-btn {
|
||||
min-width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-dark {
|
||||
#algolia-instant-search-demo {
|
||||
#algolia-content-container {
|
||||
.vs-sidebar {
|
||||
background-color: #10163a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.vs-sidebar-rounded {
|
||||
.vs-sidebar {
|
||||
border-radius: .5rem;
|
||||
}
|
||||
|
||||
.vs-sidebar--items {
|
||||
border-radius: .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
#algolia-content-container {
|
||||
.vs-sidebar {
|
||||
position: absolute !important;
|
||||
float: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ECommerceWishList.vue
|
||||
Description: eCommerce Wish List Page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="ecommerce-wishlist-demo">
|
||||
<div class="items-grid-view vx-row match-height" v-if="wishListitems.length" appear>
|
||||
<div class="vx-col lg:w-1/4 md:w-1/3 sm:w-1/2 w-full" v-for="item in wishListitems" :key="item.objectID">
|
||||
|
||||
<item-grid-view :item="item">
|
||||
|
||||
<!-- SLOT: ACTION BUTTONS -->
|
||||
<template slot="action-buttons">
|
||||
<div class="flex flex-wrap">
|
||||
|
||||
<!-- PRIMARY BUTTON : REMOVE -->
|
||||
<div
|
||||
class="item-view-primary-action-btn p-3 flex flex-grow items-center justify-center cursor-pointer"
|
||||
@click="removeItemFromWishList(item)">
|
||||
<feather-icon icon="XIcon" svgClasses="h-4 w-4" />
|
||||
|
||||
<span class="text-sm font-semibold ml-2">REMOVE</span>
|
||||
</div>
|
||||
|
||||
<!-- SECONDARY BUTTON: MOVE TO CART -->
|
||||
<div
|
||||
class="item-view-secondary-action-btn bg-primary p-3 flex flex-grow items-center justify-center text-white cursor-pointer"
|
||||
@click="cartButtonClicked(item)">
|
||||
<feather-icon icon="ShoppingBagIcon" svgClasses="h-4 w-4" />
|
||||
|
||||
<span class="text-sm font-semibold ml-2" v-if="isInCart(item.objectID)">VIEW IN CART</span>
|
||||
<span class="text-sm font-semibold ml-2" v-else>MOVE TO CART</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</item-grid-view>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IF NO ITEMS IN CART -->
|
||||
<vx-card title="You don't have any items in your wish list." v-else>
|
||||
<vs-button @click="$router.push('/apps/eCommerce/shop').catch(() => {})">Browse Shop</vs-button>
|
||||
</vx-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const ItemGridView = () => import('./components/ItemGridView.vue')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ItemGridView
|
||||
},
|
||||
computed: {
|
||||
wishListitems () {
|
||||
return this.$store.state.eCommerce.wishList.slice().reverse()
|
||||
},
|
||||
isInCart () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInCart'](itemId)
|
||||
},
|
||||
isInWishList () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInWishList'](itemId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeItemFromWishList (item) {
|
||||
this.$store.dispatch('eCommerce/toggleItemInWishList', item)
|
||||
},
|
||||
cartButtonClicked (item) {
|
||||
if (this.isInCart(item.objectID)) this.$router.push('/apps/eCommerce/checkout').catch(() => {})
|
||||
else {
|
||||
this.additemInCart(item)
|
||||
this.removeItemFromWishList(item)
|
||||
}
|
||||
},
|
||||
additemInCart (item) {
|
||||
this.$store.dispatch('eCommerce/additemInCart', item)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#ecommerce-wishlist-demo {
|
||||
.item-view-primary-action-btn {
|
||||
color: #2c2c2c !important;
|
||||
background-color: #f6f6f6;
|
||||
min-width: 50%;
|
||||
}
|
||||
|
||||
.item-view-secondary-action-btn {
|
||||
min-width: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,81 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ItemGridView.vue
|
||||
Description: Item Component - Grid VIew
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<!-- <div class="item-grid-view vx-row match-height">
|
||||
<div class="vx-col" :class="gridColumnWidth" v-for="item in items" :key="item.objectID"> -->
|
||||
<vx-card class="grid-view-item mb-base overflow-hidden" v-on="$listeners">
|
||||
<template slot="no-body">
|
||||
|
||||
<!-- ITEM IMAGE -->
|
||||
<div class="item-img-container bg-white h-64 flex items-center justify-center mb-4 cursor-pointer" @click="navigate_to_detail_view">
|
||||
<img :src="item.image" :alt="item.name" class="grid-view-img px-4">
|
||||
</div>
|
||||
<div class="item-details px-4">
|
||||
|
||||
<!-- RATING & PRICE -->
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="text-warning border border-solid border-warning flex py-1 px-2 rounded">
|
||||
<span class="text-sm mr-1">{{ item.rating }}</span>
|
||||
<feather-icon icon="StarIcon" svgClasses="h-4 w-4" />
|
||||
</div>
|
||||
<h6 class="font-bold">${{ item.price }}</h6>
|
||||
</div>
|
||||
|
||||
<!-- TITLE & DESCRIPTION -->
|
||||
<div class="my-4">
|
||||
<h6 class="truncate font-semibold mb-1 hover:text-primary cursor-pointer" @click="navigate_to_detail_view">{{ item.name }}</h6>
|
||||
<p class="item-description truncate text-sm">{{ item.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SLOT: ACTION BUTTONS -->
|
||||
<slot name="action-buttons" />
|
||||
</template>
|
||||
</vx-card>
|
||||
<!-- </div>
|
||||
</div> -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default{
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
navigate_to_detail_view () {
|
||||
this.$router.push({name: 'ecommerce-item-detail-view', params: {item_id: this.item.objectID }})
|
||||
.catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid-view-item {
|
||||
.grid-view-img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
transition: .35s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0px 4px 25px 0px rgba(0,0,0,.25);
|
||||
|
||||
.grid-view-img{
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,126 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: ItemListView.vue
|
||||
Description: Item Component - List VIew
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<vx-card class="list-view-item overflow-hidden" v-on="$listeners">
|
||||
|
||||
<template slot="no-body">
|
||||
<div class="vx-row item-details no-gutter">
|
||||
|
||||
<!-- IMG COL -->
|
||||
<div class="vx-col sm:w-1/4 w-full item-img-container bg-white flex items-center justify-center cursor-pointer" @click="navigate_to_detail_view">
|
||||
<img :src="item.image" :alt="item.name" class="grid-view-img p-4">
|
||||
</div>
|
||||
|
||||
<!-- ITEM NAME & DESC COL -->
|
||||
<div class="vx-col sm:w-1/2">
|
||||
<div class="p-4 pt-6">
|
||||
<slot name="item-meta">
|
||||
<h6 class="item-name font-semibold mb-1 hover:text-primary cursor-pointer" @click="navigate_to_detail_view">{{ item.name }}</h6>
|
||||
<p class="text-sm mb-4">By <span class="font-semibold cursor-pointer">{{ item.brand }}</span></p>
|
||||
<p class="item-description text-sm">{{ item.description }}</p>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PURCHASE COL -->
|
||||
<div class="vx-col sm:w-1/4 w-full flex items-center sm:border border-0 border-solid d-theme-border-grey-light border-r-0 border-t-0 border-b-0">
|
||||
|
||||
<div class="p-4 flex flex-col w-full">
|
||||
|
||||
<div class="text-warning flex self-end border border-solid border-warning py-1 px-2 rounded">
|
||||
<span class="text-sm mr-1">{{ item.rating }}</span>
|
||||
<feather-icon icon="StarIcon" svgClasses="h-4 w-4" />
|
||||
</div>
|
||||
|
||||
<div class="my-6">
|
||||
<h5 class="font-bold text-center">${{ item.price }}</h5>
|
||||
<span class="text-grey flex items-start justify-center mt-1" v-if="item.free_shipping">
|
||||
<feather-icon icon="ShoppingCartIcon" svgClasses="w-4 h-4" />
|
||||
<span class="text-sm ml-2">Free Shipping</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- SLOT: ACTION BUTTONS -->
|
||||
<slot name="action-buttons" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default{
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isInCart () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInCart'](itemId)
|
||||
},
|
||||
isInWishList () {
|
||||
return (itemId) => this.$store.getters['eCommerce/isInWishList'](itemId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleItemInWishList (item) {
|
||||
this.$store.dispatch('eCommerce/toggleItemInWishList', item)
|
||||
},
|
||||
additemInCart (item) {
|
||||
this.$store.dispatch('eCommerce/additemInCart', item)
|
||||
},
|
||||
cartButtonClicked (item) {
|
||||
this.isInCart(item.objectID) ? this.$router.push('/apps/eCommerce/checkout').catch(() => {}) : this.additemInCart(item)
|
||||
},
|
||||
navigate_to_detail_view () {
|
||||
this.$router.push({name: 'ecommerce-item-detail-view', params: {item_id: this.item.objectID }})
|
||||
.catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list-view-item {
|
||||
.item-name, .item-description {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.item-description {
|
||||
-webkit-line-clamp: 5;
|
||||
}
|
||||
|
||||
.grid-view-img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
transition: .35s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0px 4px 25px 0px rgba(0,0,0,.25);
|
||||
|
||||
.grid-view-img{
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,290 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: Email.vue
|
||||
Description: Email Application (Inbox)
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div id="email-app" class="border border-solid d-theme-border-grey-light rounded relative overflow-hidden">
|
||||
|
||||
<vs-sidebar class="items-no-padding" parent="#email-app" :click-not-close="clickNotClose" :hidden-background="clickNotClose" v-model="isEmailSidebarActive">
|
||||
<email-sidebar :emailTags="emailTags" @closeSidebar="toggleEmailSidebar" :mailFilter="mailFilter" />
|
||||
</vs-sidebar>
|
||||
|
||||
<div :class="{'sidebar-spacer': clickNotClose}" class="no-scroll-content border border-solid d-theme-border-grey-light border-r-0 border-t-0 border-b-0">
|
||||
|
||||
<!-- SEARCH BAR -->
|
||||
<div class="flex border d-theme-dark-bg items-center">
|
||||
<feather-icon class="md:inline-flex lg:hidden ml-4 mr-4 cursor-pointer" icon="MenuIcon" @click.stop="toggleEmailSidebar(true)"/>
|
||||
<vs-input icon-no-border icon="icon-search" size="large" icon-pack="feather" placeholder="Search Mail" v-model="searchQuery" class="vs-input-no-border vs-input-no-shdow-focus w-full" />
|
||||
</div>
|
||||
|
||||
<!-- EMAIL ACTION BAR -->
|
||||
<div class="email__actions flex items-center flex-wrap justify-between p-4 border border-r-0 border-l-0 border-solid d-theme-border-grey-light">
|
||||
<div class="flex items-center">
|
||||
<vs-checkbox v-model="selectAllCheckBox" icon-pack="feather" :icon="selectAllIcon" class="select-all-chexkbox ml-0">Select All</vs-checkbox>
|
||||
</div>
|
||||
<div class="flex">
|
||||
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer" v-if="mailFilter != 'sent'">
|
||||
|
||||
<feather-icon icon="FolderIcon" class="cursor-pointer" svg-classes="h-6 w-6"></feather-icon>
|
||||
|
||||
<vs-dropdown-menu>
|
||||
<vs-dropdown-item @click="moveTo('inbox')" v-if="mailFilter != 'inbox'">
|
||||
<span class="flex items-center">
|
||||
<feather-icon icon="MailIcon" svgClasses="h-4 w-4" class="mr-2" />
|
||||
<span>Inbox</span>
|
||||
</span>
|
||||
</vs-dropdown-item>
|
||||
|
||||
<vs-dropdown-item @click="moveTo('draft')" v-if="mailFilter != 'draft'">
|
||||
<span class="flex items-center">
|
||||
<feather-icon icon="Edit2Icon" svgClasses="h-4 w-4" class="mr-2" />
|
||||
<span>Draft</span>
|
||||
</span>
|
||||
</vs-dropdown-item>
|
||||
|
||||
<vs-dropdown-item @click="moveTo('spam')" v-if="mailFilter != 'spam'">
|
||||
<span class="flex items-center">
|
||||
<feather-icon icon="InfoIcon" svgClasses="h-4 w-4" class="mr-2" />
|
||||
<span>Spam</span>
|
||||
</span>
|
||||
</vs-dropdown-item>
|
||||
|
||||
<vs-dropdown-item @click="moveTo('trash')" v-if="mailFilter != 'trash'">
|
||||
<span class="flex items-center">
|
||||
<feather-icon icon="TrashIcon" svgClasses="h-4 w-4" class="mr-2" />
|
||||
<span>Trash</span>
|
||||
</span>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer">
|
||||
|
||||
<feather-icon icon="TagIcon" class="cursor-pointer ml-5" svg-classes="h-6 w-6"></feather-icon>
|
||||
|
||||
<vs-dropdown-menu >
|
||||
<vs-dropdown-item v-for="(label, index) in emailTags" :key="index" @click="updateLabels(label.value)" class="whitespace-no-wrap">
|
||||
<div class="h-3 w-3 inline-block rounded-full mr-3" :class="'bg-' + label.color"></div>
|
||||
<span>{{ label.text }}</span>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
|
||||
<feather-icon icon="MailIcon" class="ml-5 cursor-pointer" svg-classes="h-6 w-6" @click="updateMarkUnread" />
|
||||
|
||||
<feather-icon v-if="mailFilter != 'trash'" icon="TrashIcon" class="cursor-pointer ml-5" svg-classes="h-6 w-6" @click="moveTo('trash')" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- EMAILS LIST -->
|
||||
<component :is="scrollbarTag" class="email-content-scroll-area" :settings="settings" ref="mailListPS" :key="$vs.rtl">
|
||||
<transition-group name="list-enter-up" class="email__mails" tag="ul" appear>
|
||||
<li class="cursor-pointer email__mail-item" v-for="(mail, index) in mails" :key="String(mailFilter) + String(mail.id)" @click="updateOpenMail(mail.id)" :style="{transitionDelay: (index * 0.1) + 's'}">
|
||||
<mail-item :mail="mail" :isSelected="isMailSelected(mail.id)" @addToSelected="addToSelectedMails" @removeSelected="removeSelectedMail" />
|
||||
</li>
|
||||
</transition-group>
|
||||
</component>
|
||||
</div>
|
||||
|
||||
<!-- EMAIL VIEW SIDEBAR -->
|
||||
<email-view
|
||||
:emailTags = "emailTags"
|
||||
:openMailId = "openMailId"
|
||||
:isSidebarActive = "isSidebarActive"
|
||||
:mailFilter = "mailFilter"
|
||||
@markUnread = "updateSingleMarkUnread"
|
||||
@removeMail = "removeOpenMail"
|
||||
@previousMail = "previousMail"
|
||||
@nextMail = "nextMail"
|
||||
@moveTo = "moveCurrentTo"
|
||||
@closeSidebar = "closeMailViewSidebar">
|
||||
</email-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EmailSidebar from './EmailSidebar.vue'
|
||||
import MailItem from './MailItem.vue'
|
||||
import EmailView from './EmailView.vue'
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
import moduleEmail from '@/store/email/moduleEmail.js'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
openMailId : null,
|
||||
selectedMails : [],
|
||||
isSidebarActive : false,
|
||||
showThread : false,
|
||||
clickNotClose : true,
|
||||
isEmailSidebarActive : true,
|
||||
settings : {
|
||||
maxScrollbarLength : 60,
|
||||
wheelSpeed : 0.30
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isSidebarActive (value) {
|
||||
if (!value) this.showThread = false
|
||||
},
|
||||
mailFilter () {
|
||||
this.selectedMails = []
|
||||
|
||||
const scroll_el = this.$refs.mailListPS.$el || this.$refs.mailListPS
|
||||
scroll_el.scrollTop = 0
|
||||
|
||||
this.$store.commit('email/UPDATE_MAIL_FILTER', this.$route.params.filter)
|
||||
this.$store.dispatch('email/fetchEmails', { filter: this.$route.params.filter })
|
||||
this.toggleEmailSidebar()
|
||||
},
|
||||
windowWidth () {
|
||||
this.setSidebarWidth()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
mailFilter () {
|
||||
return this.$route.params.filter
|
||||
},
|
||||
emailTags () {
|
||||
return this.$store.state.email.mailTags
|
||||
},
|
||||
searchQuery: {
|
||||
get () {
|
||||
return this.$store.state.email.mailSearchQuery
|
||||
},
|
||||
set (val) {
|
||||
this.$store.dispatch('email/setEmailSearchQuery', val)
|
||||
}
|
||||
},
|
||||
selectAllCheckBox: {
|
||||
get () {
|
||||
return this.selectedMails.length
|
||||
},
|
||||
set (value) {
|
||||
value ? this.selectedMails = this.mails.map(mail => mail.id) : this.selectedMails = []
|
||||
}
|
||||
},
|
||||
mails () {
|
||||
return this.$store.getters['email/filteredMails']
|
||||
},
|
||||
selectAllIcon () {
|
||||
return this.selectedMails.length === this.mails.length ? 'icon-check' : 'icon-minus'
|
||||
},
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag },
|
||||
isMailSelected () {
|
||||
return (mailId) => this.selectedMails.indexOf(mailId) !== -1
|
||||
},
|
||||
windowWidth () {
|
||||
return this.$store.state.windowWidth
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateOpenMail (mailId) {
|
||||
this.openMailId = mailId
|
||||
this.isSidebarActive = true
|
||||
},
|
||||
addToSelectedMails (mailId) {
|
||||
if (this.selectedMails.indexOf(mailId) === -1) this.selectedMails.push(mailId)
|
||||
},
|
||||
removeSelectedMail (mailId) {
|
||||
const mailIndex = this.selectedMails.indexOf(mailId)
|
||||
if (mailIndex !== -1) this.selectedMails.splice(mailIndex, 1)
|
||||
},
|
||||
moveTo (to) {
|
||||
const payload = { emailIds: this.selectedMails, to }
|
||||
this.$store.dispatch('email/moveMailsTo', payload)
|
||||
.catch((error) => { console.error(error) })
|
||||
this.selectedMails = []
|
||||
},
|
||||
moveCurrentTo (to) {
|
||||
this.selectedMails = [this.openMailId]
|
||||
this.moveTo(to)
|
||||
},
|
||||
updateMarkUnread () {
|
||||
const payload = { emailIds: this.selectedMails, unreadFlag: true }
|
||||
this.$store.dispatch('email/setUnread', payload)
|
||||
this.selectedMails = []
|
||||
},
|
||||
removeOpenMail () {
|
||||
this.selectedMails = [this.openMailId]
|
||||
this.moveTo('trashed')
|
||||
this.isSidebarActive = false
|
||||
},
|
||||
toggleIsStarred () {
|
||||
const payload = { mailId: this.currentMail.id, value: !this.currentMail.isStarred }
|
||||
this.$store.dispatch('email/toggleIsMailStarred', payload)
|
||||
},
|
||||
nextMail () {
|
||||
const currentMailIndex = this.mails.findIndex((mail) => mail.id === this.openMailId)
|
||||
if (this.mails[currentMailIndex + 1]) this.openMailId = this.mails[currentMailIndex + 1].id
|
||||
},
|
||||
previousMail () {
|
||||
const currentMailIndex = this.mails.findIndex((mail) => mail.id === this.openMailId)
|
||||
if (this.mails[currentMailIndex - 1]) this.openMailId = this.mails[currentMailIndex - 1].id
|
||||
},
|
||||
updateSingleMarkUnread () {
|
||||
this.selectedMails = [this.openMailId]
|
||||
this.updateMarkUnread()
|
||||
this.isSidebarActive = false
|
||||
},
|
||||
updateLabels (label) {
|
||||
this.$store.dispatch('email/updateLabels', { mails: this.selectedMails, label })
|
||||
this.selectedMails = []
|
||||
},
|
||||
closeMailViewSidebar () {
|
||||
this.isSidebarActive = false
|
||||
},
|
||||
setSidebarWidth () {
|
||||
if (this.windowWidth < 992) {
|
||||
this.isEmailSidebarActive = this.clickNotClose = false
|
||||
} else {
|
||||
this.isEmailSidebarActive = this.clickNotClose = true
|
||||
}
|
||||
},
|
||||
toggleEmailSidebar (value = false) {
|
||||
if (!value) {
|
||||
this.closeMailViewSidebar()
|
||||
if (this.clickNotClose) {
|
||||
return
|
||||
}
|
||||
}
|
||||
this.isEmailSidebarActive = value
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MailItem,
|
||||
EmailSidebar,
|
||||
EmailView,
|
||||
VuePerfectScrollbar
|
||||
},
|
||||
created () {
|
||||
this.$store.registerModule('email', moduleEmail)
|
||||
this.setSidebarWidth()
|
||||
|
||||
this.$store.commit('email/UPDATE_MAIL_FILTER', this.$route.params.filter) // Update Mail Filter
|
||||
this.$store.dispatch('email/fetchEmails', { filter: this.$route.params.filter }) // Fetch Emails From API
|
||||
this.$store.dispatch('email/fetchMeta') // Fetch Unread Mails
|
||||
this.$store.dispatch('email/fetchTags') // Fetch Mail Tags
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$store.unregisterModule('email')
|
||||
},
|
||||
mounted () {
|
||||
this.$store.dispatch('email/setEmailSearchQuery', '')
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/apps/email.scss";
|
||||
</style>
|
||||
@@ -1,83 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: EmailMailCard.vue
|
||||
Description: Email Application - Single Email Card View
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template functional>
|
||||
<vx-card class="px-4" :class="data.staticClass">
|
||||
<!-- MAIL HEAD -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full border-b border-l-0 border-r-0 border-t-0 d-theme-border-grey-light border-solid flex justify-between flex items-center">
|
||||
<!-- Sender Details -->
|
||||
<div class="flex items-center">
|
||||
<div>
|
||||
<vs-avatar class="sender__avatar--single flex-shrink-0 mr-3 border-2 border-solid border-white" :src="props.mailContent.img" size="65px" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<h5 class="mb-1">{{ props.mailContent.sender_name }}</h5>
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm">{{ props.mailContent.sender }}</span>
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="inline-flex cursor-pointer">
|
||||
<feather-icon icon="ChevronDownIcon" class="w-3 h-3" />
|
||||
<vs-dropdown-menu style="z-index: 40001">
|
||||
<div class="p-2">
|
||||
<p class="text-sm mb-1">From: <span class="font-semibold"> {{ props.mailContent.sender }} </span></p>
|
||||
<p class="text-sm mb-1">To: <span class="font-semibold"> {{ props.mailContent.to | csv }} </span></p>
|
||||
<p class="text-sm mb-1">Date: <span class="font-semibold"> {{ props.mailContent.time | time }} {{ props.mailContent.time | date(true) }} </span></p>
|
||||
<p class="text-sm mb-1" v-if="props.mailContent.cc.length">cc: <span class="font-semibold"> {{ props.mailContent.cc | csv }} </span></p>
|
||||
</div>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /Sender Details -->
|
||||
|
||||
<!-- Mail Time & Date -->
|
||||
<div class="flex flex-col justify-end">
|
||||
<span class="text-right">{{ props.mailContent.time | time }}</span>
|
||||
<div class="flex justify-end mt-2">
|
||||
<span class="text-right">{{ props.mailContent.time | date(true) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /Mail Time & Date -->
|
||||
</div>
|
||||
|
||||
<!-- MAIL CONTENT -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="mail__content break-words mt-8 mb-4" v-html="props.mailContent.message"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MAIL ATTACHMENTS -->
|
||||
<div class="vx-row" v-if="props.mailContent.attachments.length">
|
||||
<div class="vx-col w-full border-b border-l-0 border-r-0 border-t-0 d-theme-border-grey-light border-solid mb-6 flex">
|
||||
<feather-icon icon="PaperclipIcon" class="mr-2" />
|
||||
<span class="block py-4">فایل های الحاقی</span>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="mail__attachment" v-for="(attachment, index) in props.mailContent.attachments" :key="index">
|
||||
<vs-chip color="primary" class="px-4 py-2 mr-3">{{ attachment }}</vs-chip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mailContent: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,183 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: EmailSidebar.vue
|
||||
Description: Email Application Sidebar(Filter) (Inbox)
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div class="email__email-sidebar h-full">
|
||||
<div class="m-6 clearfix">
|
||||
<vs-button class="bg-primary-gradient w-full" icon-pack="feather" icon="icon-edit" @click="activePrompt = true">Compose</vs-button>
|
||||
</div>
|
||||
|
||||
<!-- compose email -->
|
||||
<vs-prompt
|
||||
class="email-compose"
|
||||
title="New Message"
|
||||
accept-text= "Send"
|
||||
@cancel="clearFields"
|
||||
@accept="sendMail"
|
||||
@close="clearFields"
|
||||
:is-valid="validateForm"
|
||||
:active.sync="activePrompt">
|
||||
<component :is="scrollbarTag" class="scroll-area p-4" :settings="settings" :key="$vs.rtl">
|
||||
<form @submit.prevent>
|
||||
<vs-input v-validate="'required|email'" name="mailTo" label-placeholder="To" v-model="mailTo" class="w-full mb-6" :danger="!validateForm && mailTo != ''" val-icon-danger="clear" :success="validateForm" val-icon-success="done" :color="validateForm ? 'success' : 'danger'" />
|
||||
<vs-input name="mailSubject" label-placeholder="Subject" v-model="mailSubject" class="w-full mb-6" />
|
||||
<vs-input name="mailCC" label-placeholder="CC" v-model="mailCC" class="w-full mb-6" />
|
||||
<vs-input name="mailBCC" label-placeholder="BCC" v-model="mailBCC" class="w-full mb-6" />
|
||||
<quill-editor v-model="mailMessage" :options="editorOption" />
|
||||
<vs-upload multiple text="Attachments" :show-upload-button="false" class="compose-mail-attachment" />
|
||||
</form>
|
||||
</component>
|
||||
</vs-prompt>
|
||||
|
||||
<component :is="scrollbarTag" class="email-filter-scroll-area" :settings="settings" :key="$vs.rtl">
|
||||
<div class="px-6 pb-2 flex flex-col">
|
||||
|
||||
<!-- inbox -->
|
||||
<router-link tag="span" :to="`${baseUrl}/inbox`" class="flex justify-between items-center cursor-pointer" :class="{'text-primary': mailFilter == 'inbox'}">
|
||||
<div class="flex items-center mb-2">
|
||||
<feather-icon icon="MailIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'inbox'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">Inbox</span>
|
||||
</div>
|
||||
<template v-if="emailMeta.unreadMails">
|
||||
<vs-chip class="number" color="primary" v-if="emailMeta.unreadMails.folder.inbox.length > 0">{{ emailMeta.unreadMails.folder.inbox.length }}</vs-chip>
|
||||
</template>
|
||||
</router-link>
|
||||
|
||||
<!-- sent -->
|
||||
<router-link tag="span" :to="`${baseUrl}/sent`" class="flex items-center mt-4 mb-2 cursor-pointer" :class="{'text-primary': mailFilter == 'sent'}">
|
||||
<feather-icon icon="SendIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'sent'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">Sent</span>
|
||||
</router-link>
|
||||
|
||||
<!-- draft -->
|
||||
<router-link tag="span" :to="`${baseUrl}/draft`" class="flex justify-between items-center mt-4 cursor-pointer" :class="{'text-primary': mailFilter == 'draft'}">
|
||||
<div class="flex items-center mb-2">
|
||||
<feather-icon icon="Edit2Icon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'draft'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">Draft</span>
|
||||
</div>
|
||||
<template v-if="emailMeta.draftMails">
|
||||
<vs-chip class="number" color="warning" v-if="emailMeta.draftMails.length > 0">{{ emailMeta.draftMails.length }}</vs-chip>
|
||||
</template>
|
||||
</router-link>
|
||||
|
||||
<!-- starred -->
|
||||
<router-link tag="span" :to="`${baseUrl}/starred`" class="flex items-center mt-4 mb-2 cursor-pointer" :class="{'text-primary': mailFilter == 'starred'}">
|
||||
<feather-icon icon="StarIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'starred'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">Starred</span>
|
||||
</router-link>
|
||||
|
||||
<!-- spam -->
|
||||
<router-link tag="span" :to="`${baseUrl}/spam`" class="flex items-center justify-between items-center mt-4 cursor-pointer" :class="{'text-primary': mailFilter == 'spam'}">
|
||||
<div class="flex items-center mb-2">
|
||||
<feather-icon icon="InfoIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'spam'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">Spam</span>
|
||||
</div>
|
||||
<template v-if="emailMeta.unreadMails">
|
||||
<vs-chip class="number" color="danger" v-if="emailMeta.unreadMails.folder.spam.length > 0">{{ emailMeta.unreadMails.folder.spam.length }}</vs-chip>
|
||||
</template>
|
||||
</router-link>
|
||||
|
||||
<!-- trash -->
|
||||
<router-link tag="span" :to="`${baseUrl}/trash`" class="flex items-center mt-4 mb-2 cursor-pointer" :class="{'text-primary': mailFilter == 'trash'}">
|
||||
<feather-icon icon="TrashIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'trash'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">Trash</span>
|
||||
</router-link>
|
||||
</div>
|
||||
<vs-divider></vs-divider>
|
||||
<div class="email__labels px-6 py-4">
|
||||
<h5 class="mb-8">Labels</h5>
|
||||
<div class="email__lables-list">
|
||||
<router-link tag="span" class="email__label flex items-center mb-4 cursor-pointer" v-for="(tag, index) in emailTags" :key="index" :to="`${baseUrl}/${tag.value}`">
|
||||
<div class="ml-1 h-3 w-3 rounded-full mr-4" :class="'border-2 border-solid border-' + tag.color"></div>
|
||||
<span class="text-lg" :class="{'text-primary': mailFilter == tag.value}">{{ tag.text }}</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import { quillEditor } from 'vue-quill-editor'
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
emailTags: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
mailFilter: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activePrompt: false,
|
||||
mailTo: '',
|
||||
mailSubject: '',
|
||||
mailCC: '',
|
||||
mailBCC: '',
|
||||
mailMessage: '',
|
||||
editorOption: {
|
||||
modules: {
|
||||
toolbar: [
|
||||
['bold', 'italic', 'underline', 'strike', 'link', 'blockquote', 'code-block'],
|
||||
[{ 'header': 1 }, { 'header': 2 }],
|
||||
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
[{ 'font': [] }]
|
||||
]
|
||||
},
|
||||
placeholder: 'Message'
|
||||
},
|
||||
settings: {
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed: 0.30
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
validateForm () {
|
||||
return !this.errors.any() && this.mailTo !== ''
|
||||
},
|
||||
baseUrl () {
|
||||
const path = this.$route.path
|
||||
return path.slice(0, path.lastIndexOf('/'))
|
||||
},
|
||||
emailMeta () {
|
||||
return this.$store.state.email.meta
|
||||
},
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag }
|
||||
},
|
||||
methods: {
|
||||
clearFields () {
|
||||
this.$nextTick(() => {
|
||||
this.mailTo = ''
|
||||
this.mailSubject = ''
|
||||
this.mailCC = ''
|
||||
this.mailBCC = ''
|
||||
this.mailMessage = ''
|
||||
})
|
||||
},
|
||||
sendMail () {
|
||||
this.clearFields()
|
||||
}
|
||||
},
|
||||
components: {
|
||||
quillEditor,
|
||||
VuePerfectScrollbar
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: EmailView.vue
|
||||
Description: Email Application - Single Email View (Inbox)
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<vs-sidebar click-not-close parent="#email-app" :hidden-background="true" class="full-vs-sidebar email-view-sidebar items-no-padding" v-model="isSidebarActive" position-right>
|
||||
<div class="mail-sidebar-content px-0 sm:pb-6 h-full" v-if="currentMail">
|
||||
<div class="flex flex-wrap items-center email-header justify-between md:px-8 px-6 sm:pb-2 sm: pt-6 d-theme-dark-bg">
|
||||
<div class="flex mb-4">
|
||||
<div class="flex items-center">
|
||||
<feather-icon :icon="$vs.rtl ? 'ArrowRightIcon' : 'ArrowLeftIcon'" @click="$emit('closeSidebar')" class="cursor-pointer mr-4" svg-classes="w-6 h-6"></feather-icon>
|
||||
<h4 v-if="currentMail.subject">{{ currentMail.subject }}</h4>
|
||||
<h4 v-else>(no subject)</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-10 mb-4 mt-1">
|
||||
<div class="email__actions--single flex items-baseline">
|
||||
|
||||
<feather-icon icon="StarIcon" class="cursor-pointer" :svgClasses="[{'text-warning stroke-current stroke-current': currentMail.isStarred}, 'h-6 w-6']" @click="toggleIsStarred" />
|
||||
|
||||
<!-- MOVE TO DROPDOWN -->
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer" v-if="mailFilter != 'sent'">
|
||||
<feather-icon icon="FolderIcon" svg-classes="h-6 w-6" class="ml-4"></feather-icon>
|
||||
<vs-dropdown-menu>
|
||||
<vs-dropdown-item @click="moveTo('inbox')" v-if="currentMail.mailFolder != 'inbox'">
|
||||
<span class="flex items-center">
|
||||
<feather-icon icon="MailIcon" svgClasses="h-4 w-4" class="mr-2" />
|
||||
<span>Inbox</span>
|
||||
</span>
|
||||
</vs-dropdown-item>
|
||||
|
||||
<vs-dropdown-item @click="moveTo('draft')" v-if="currentMail.mailFolder != 'draft'">
|
||||
<span class="flex items-center">
|
||||
<feather-icon icon="Edit2Icon" svgClasses="h-4 w-4" class="mr-2" />
|
||||
<span>Draft</span>
|
||||
</span>
|
||||
</vs-dropdown-item>
|
||||
|
||||
<vs-dropdown-item @click="moveTo('spam')" v-if="currentMail.mailFolder != 'spam'">
|
||||
<span class="flex items-center">
|
||||
<feather-icon icon="InfoIcon" svgClasses="h-4 w-4" class="mr-2" />
|
||||
<span>Spam</span>
|
||||
</span>
|
||||
</vs-dropdown-item>
|
||||
|
||||
<vs-dropdown-item @click="moveTo('trash')" v-if="currentMail.mailFolder != 'trash'">
|
||||
<span class="flex items-center">
|
||||
<feather-icon icon="TrashIcon" svgClasses="h-4 w-4" class="mr-2" />
|
||||
<span>Trash</span>
|
||||
</span>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
|
||||
<!-- ADD LABEL DROPDOWN -->
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer">
|
||||
<feather-icon icon="TagIcon" svg-classes="h-6 w-6" class="cursor-pointer ml-4"></feather-icon>
|
||||
<vs-dropdown-menu style="z-index: 40001">
|
||||
<vs-dropdown-item v-for="(label, index) in emailTags" :key="index" @click.stop>
|
||||
<vs-checkbox :vs-value="label.value" v-model="currentMailLabels">{{ label.text }}</vs-checkbox>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
|
||||
<feather-icon icon="MailIcon" svg-classes="h-6 w-6" class="cursor-pointer ml-4" @click="$emit('markUnread')"></feather-icon>
|
||||
<feather-icon v-if="currentMail.mailFolder != 'trash'" icon="TrashIcon" svg-classes="h-6 w-6" class="cursor-pointer ml-4" @click="$emit('removeMail')"></feather-icon>
|
||||
<feather-icon :icon="$vs.rtl ? 'ChevronsRightIcon' : 'ChevronsLeftIcon'" svg-classes="h-6 w-6" class="cursor-pointer ml-4 hidden sm:inline-flex" @click="$emit('previousMail')" />
|
||||
<feather-icon :icon="$vs.rtl ? 'ChevronsLeftIcon' : 'ChevronsRightIcon'" svg-classes="h-6 w-6" class="cursor-pointer ml-4 hidden sm:inline-flex" @click="$emit('nextMail')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<component :is="scrollbarTag" class="scroll-area-mail-content md:px-8 md:pb-8 pt-4 px-6 pb-6" :settings="settings" :key="$vs.rtl">
|
||||
<!-- LABEL ROW -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="email__labels--single flex ml-10 items-center mt-2">
|
||||
<transition-group name="list" tag="div" class="flex">
|
||||
<div v-for="label in currentMail.labels" :key="label" class="open-mail-label flex items-center mr-4">
|
||||
<div class="h-3 w-3 rounded-full mr-1" :class="'bg-' + labelColor(label)"></div>
|
||||
<span class="text-sm">{{ label | capitalize }}</span>
|
||||
</div>
|
||||
</transition-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /LABEL ROW -->
|
||||
<br>
|
||||
|
||||
<div class="vx-row mb-4" v-if="currentMail.replies.length && !showThread">
|
||||
<div class="vx-col w-full">
|
||||
<span class="text-primary font-medium ml-10 cursor-pointer" @click="showThread = true">{{ currentMail.replies.length }} Earlier Messages</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isSidebarActive">
|
||||
|
||||
<!-- ALL MESSAGES - THREAD -->
|
||||
<div class="vx-row" v-for="threadMail in currentMail.replies.slice().reverse()" :key="threadMail.id" v-if="showThread">
|
||||
<div class="vx-col w-full">
|
||||
<email-mail-card :mailContent="threadMail" class="mb-10" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LATEST MESSAGE -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<email-mail-card :mailContent="currentMail" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-row" style="margin-top: 2.2rem">
|
||||
<div class="vx-col w-full">
|
||||
<vx-card>
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full flex justify-between">
|
||||
<span class="text-lg">Click here to <span class="text-primary font-semibold cursor-pointer">Reply</span> or <span class="text-primary font-semibold cursor-pointer">Forward</span></span>
|
||||
<feather-icon icon="PaperclipIcon"></feather-icon>
|
||||
</div>
|
||||
</div>
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</component>
|
||||
</div>
|
||||
</vs-sidebar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
import EmailMailCard from './EmailMailCard.vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
emailTags: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
openMailId: {
|
||||
required: true,
|
||||
validator: prop => typeof prop === 'number' || prop === null
|
||||
},
|
||||
isSidebarActive: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
mailFilter: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showThread: false,
|
||||
settings: {
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed: 0.50
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isSidebarActive (value) {
|
||||
if (!value) {
|
||||
this.$emit('closeSidebar')
|
||||
setTimeout(() => {
|
||||
this.showThread = false
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentMail () {
|
||||
return this.$store.getters['email/getMail'](this.openMailId)
|
||||
},
|
||||
labelColor () {
|
||||
return (label) => {
|
||||
const tags = this.$store.state.email.mailTags
|
||||
return tags.find((tag) => {
|
||||
return tag.value === label
|
||||
}).color
|
||||
}
|
||||
},
|
||||
currentMailLabels: {
|
||||
get () {
|
||||
return this.currentMail.labels
|
||||
},
|
||||
set (value) {
|
||||
if (Array.isArray(value)) {
|
||||
const payload = { mailId: this.openMailId, labels: value }
|
||||
this.$store.dispatch('email/setLabels', payload)
|
||||
}
|
||||
}
|
||||
},
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag }
|
||||
},
|
||||
methods: {
|
||||
toggleIsStarred () {
|
||||
const payload = { mailId: this.openMailId, value: !this.currentMail.isStarred }
|
||||
this.$store.dispatch('email/toggleIsMailStarred', payload)
|
||||
},
|
||||
moveTo (to) {
|
||||
this.$emit('closeSidebar')
|
||||
this.$emit('moveTo', to)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
VuePerfectScrollbar,
|
||||
EmailMailCard
|
||||
},
|
||||
updated () {
|
||||
if (!this.currentMail) return
|
||||
if (this.currentMail.unread && this.isSidebarActive) this.$store.dispatch('email/setUnread', { emailIds: [this.openMailId], unread: false })
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: MailItem.vue
|
||||
Description: Mail Item - Displays mail item
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div class="mail__mail-item sm:px-4 px-2 py-6" :class="{'mail__opened-mail': !mail.unread}">
|
||||
|
||||
<!-- MAIL ROW 1 : META -->
|
||||
<div class="flex w-full">
|
||||
<vs-avatar class="sender__avatar flex-shrink-0 mr-3 border-2 border-solid border-white" :src="mail.img" size="40px"></vs-avatar>
|
||||
|
||||
<div class="flex w-full justify-between items-start">
|
||||
<div class="mail__details">
|
||||
<h5 class="mb-1" :class="{'font-semibold': mail.unread}">{{ mail.sender_name }}</h5>
|
||||
<span v-if="mail.subject">{{ mail.subject }}</span>
|
||||
<span v-else>(no subject)</span>
|
||||
</div>
|
||||
|
||||
<div class="mail-item__meta flex items-center">
|
||||
<div class="email__labels hidden sm:flex items-center">
|
||||
<div class="h-2 w-2 rounded-full mr-2" :class="'bg-' + labelColor(label)" v-for="(label, index) in mail.labels" :key="index"></div>
|
||||
</div>
|
||||
<span>{{ mail.time | date }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /MAIL ROW 1 -->
|
||||
|
||||
<!-- MAIL ROW 2 : MSG & ACTIONS -->
|
||||
<div class="flex w-full">
|
||||
<div class="flex items-center ml-1">
|
||||
<vs-checkbox v-model="isSelectedMail" @click.stop class="vs-checkbox-small ml-0 mr-1"></vs-checkbox>
|
||||
<feather-icon icon="StarIcon" class="cursor-pointer" :svgClasses="[{'text-warning fill-current stroke-current': mail.isStarred}, 'w-5', 'h-5']" @click.stop="toggleIsStarred"></feather-icon>
|
||||
</div>
|
||||
<div class="mail__message truncate ml-3">
|
||||
<span>{{ mail.message | filter_tags }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /MAIL ROW 2 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mail: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
isSelected: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isSelectedMail: this.isSelected
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isSelected (value) {
|
||||
this.isSelectedMail = value
|
||||
},
|
||||
isSelectedMail (val) {
|
||||
val ? this.$emit('addToSelected', this.mail.id) : this.$emit('removeSelected', this.mail.id)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
labelColor () {
|
||||
return (label) => {
|
||||
const tags = this.$store.state.email.mailTags
|
||||
return tags.find((tag) => {
|
||||
return tag.value === label
|
||||
}).color
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleIsStarred () {
|
||||
const payload = { mailId: this.mail.id, value: !this.mail.isStarred }
|
||||
this.$store.dispatch('email/toggleIsMailStarred', payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card
|
||||
ref="filterCard"
|
||||
refresh-content-action
|
||||
:removeCardAction="false"
|
||||
@refresh="resetColFilters"
|
||||
title="گزارش فروش کیفی ها" class="vx-card">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="flex flex-wrap items-center mb-4">
|
||||
|
||||
|
||||
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
|
||||
<div class="flex-1">
|
||||
<a-input class="md:w-1/2" v-model="searchQuery" placeholder="جستجو">
|
||||
<a-icon slot="prefix" type="search"/>
|
||||
</a-input>
|
||||
</div>
|
||||
|
||||
|
||||
<a-dropdown-button>
|
||||
عملیات
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">
|
||||
تایید دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
حذف دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
خروجی اکسل
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown-button>
|
||||
</div>
|
||||
<VsDivider/>
|
||||
|
||||
<AModal :visible.sync="detailsPopup" @cancel="()=>detailsPopup = false" :zIndex="410000" width="80%"
|
||||
:footer="null">
|
||||
<div>
|
||||
<CustomerView/>
|
||||
</div>
|
||||
</AModal>
|
||||
|
||||
<ATable
|
||||
class="p-0 m-0"
|
||||
:pagination="false"
|
||||
:columns="cols" :data-source="data">
|
||||
<div slot="op">
|
||||
<ATooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر" @confirm="confirmDelete()">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="h-6 w-6 text-danger" class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</ATooltip>
|
||||
</div>
|
||||
</ATable>
|
||||
<vs-pagination
|
||||
class="mt-4"
|
||||
:total="totalPages"
|
||||
:max="7"
|
||||
v-model="currentPage"/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
// Store Module
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
// Cell Renderer
|
||||
import CellRendererLink from '../user/user-list/cell-renderer/CellRendererLink.vue'
|
||||
import CellRendererStatus from '../user/user-list/cell-renderer/CellRendererStatus.vue'
|
||||
import CellRendererVerified from '../user/user-list/cell-renderer/CellRendererVerified.vue'
|
||||
import CellRendererActions from '../user/user-list/cell-renderer/CellRendererActions.vue'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from "@/table/bag";
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CustomerView,
|
||||
vSelect,
|
||||
// Cell Renderer
|
||||
FeatherIcon,
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Filter Options
|
||||
filterType: 'all',
|
||||
filterSts: 'all',
|
||||
detailsPopup: false,
|
||||
typeOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'کیفی', value: 'active'},
|
||||
{label: 'عمده ای', value: 'deactivated'},
|
||||
{label: 'تک فروشی', value: 'blocked'}
|
||||
],
|
||||
statusOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'فعال', value: 'active'},
|
||||
{label: 'غیر فعال', value: 'deactivated'}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
key: '1',
|
||||
bag_name: 'محمد آذری',
|
||||
customer: 'علی قربانی',
|
||||
cat: '25-01-99 10:26',
|
||||
price: '2,500,000',
|
||||
w: '250 گرم',
|
||||
sts: 'پردازش نشده',
|
||||
when: '2 اردیبهشت 99',
|
||||
},
|
||||
],
|
||||
searchQuery: '',
|
||||
// AgGrid
|
||||
gridApi: null,
|
||||
cols: null,
|
||||
gridOptions: {},
|
||||
defaultColDef: {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
suppressMenu: true
|
||||
},
|
||||
// Cell Renderer Components
|
||||
components: {
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleFilter(obj) {
|
||||
this.setColumnFilter('role', obj.value)
|
||||
},
|
||||
statusFilter(obj) {
|
||||
this.setColumnFilter('status', obj.value)
|
||||
},
|
||||
isVerifiedFilter(obj) {
|
||||
const val = obj.value === 'all' ? 'all' : obj.value === 'yes' ? 'true' : 'false'
|
||||
this.setColumnFilter('is_verified', val)
|
||||
},
|
||||
departmentFilter(obj) {
|
||||
this.setColumnFilter('department', obj.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
usersData() {
|
||||
return this.$store.state.userManagement.users
|
||||
},
|
||||
paginationPageSize() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetPageSize()
|
||||
else return 10
|
||||
},
|
||||
totalPages() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetTotalPages()
|
||||
else return 0
|
||||
},
|
||||
currentPage: {
|
||||
get() {
|
||||
// if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1
|
||||
return 1
|
||||
},
|
||||
set(val) {
|
||||
// this.gridApi.paginationGoToPage(val - 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setColumnFilter(column, val) {
|
||||
const filter = this.gridApi.getFilterInstance(column)
|
||||
let modelObj = null
|
||||
|
||||
if (val !== 'all') {
|
||||
modelObj = {type: 'equals', filter: val}
|
||||
}
|
||||
|
||||
filter.setModel(modelObj)
|
||||
this.gridApi.onFilterChanged()
|
||||
},
|
||||
toEdit() {
|
||||
this.$router.push({name: 'app-customer-edit', params: {userId: 268}})
|
||||
},
|
||||
confirmDelete() {
|
||||
this.gridApi.onFilterChanged();
|
||||
},
|
||||
resetColFilters() {
|
||||
this.$refs.filterCard.removeRefreshAnimation()
|
||||
},
|
||||
updateSearchQuery(val) {
|
||||
this.gridApi.setQuickFilter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cols = TableCol.default;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,254 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card
|
||||
ref="filterCard"
|
||||
refresh-content-action
|
||||
:removeCardAction="false"
|
||||
@refresh="resetColFilters"
|
||||
title="گزارش فروش کیفی ها" class="vx-card">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="flex flex-wrap items-center mb-4">
|
||||
|
||||
|
||||
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
|
||||
<div class="flex-1">
|
||||
<a-input class="md:w-1/2" v-model="searchQuery" placeholder="جستجو">
|
||||
<a-icon slot="prefix" type="search"/>
|
||||
</a-input>
|
||||
</div>
|
||||
|
||||
|
||||
<a-dropdown-button>
|
||||
عملیات
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">
|
||||
تایید دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
حذف دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
خروجی اکسل
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown-button>
|
||||
</div>
|
||||
<VsDivider/>
|
||||
|
||||
<AModal :visible.sync="detailsPopup" @cancel="()=>detailsPopup = false" :zIndex="410000" width="80%"
|
||||
:footer="null">
|
||||
<div>
|
||||
<CustomerView/>
|
||||
</div>
|
||||
</AModal>
|
||||
|
||||
<ATable
|
||||
class="p-0 m-0"
|
||||
:pagination="false"
|
||||
:columns="cols" :data-source="data">
|
||||
<div slot="expandedRowRender" slot-scope="record" style="margin: 0">
|
||||
<div class="flex item-center" >
|
||||
<span class="ml-4 b">تفکیک طلایی :</span>
|
||||
<vs-chip color="primary">
|
||||
مدت : 83
|
||||
</vs-chip>
|
||||
<vs-chip color="danger">
|
||||
راس : 76 روز
|
||||
</vs-chip>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="gold" slot-scope="data">
|
||||
<FeatherIcon icon="ArrowDownIcon" class="text-danger" svgClasses="w-4 h-4"/>
|
||||
{{data}}
|
||||
</div>
|
||||
<div slot="rial" slot-scope="data">
|
||||
<FeatherIcon icon="ArrowDownIcon" class="text-danger" svgClasses="w-4 h-4"/>
|
||||
{{data}}
|
||||
</div>
|
||||
<div slot="op">
|
||||
<ATooltip>
|
||||
<span slot="title">مشاهده</span>
|
||||
<FeatherIcon icon="AlertCircleIcon" @click="detailsPopup = true" svgClasses="h-6 w-6 text-warning"
|
||||
class="cursor-pointer mx-1"/>
|
||||
</ATooltip>
|
||||
<ATooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر" @confirm="confirmDelete()">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="h-6 w-6 text-danger" class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</ATooltip>
|
||||
</div>
|
||||
</ATable>
|
||||
<vs-pagination
|
||||
class="mt-4"
|
||||
:total="totalPages"
|
||||
:max="7"
|
||||
v-model="currentPage"/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
// Store Module
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
// Cell Renderer
|
||||
import CellRendererLink from '../user/user-list/cell-renderer/CellRendererLink.vue'
|
||||
import CellRendererStatus from '../user/user-list/cell-renderer/CellRendererStatus.vue'
|
||||
import CellRendererVerified from '../user/user-list/cell-renderer/CellRendererVerified.vue'
|
||||
import CellRendererActions from '../user/user-list/cell-renderer/CellRendererActions.vue'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from "@/table/debit";
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CustomerView,
|
||||
vSelect,
|
||||
// Cell Renderer
|
||||
FeatherIcon,
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Filter Options
|
||||
filterType: 'all',
|
||||
filterSts: 'all',
|
||||
detailsPopup: false,
|
||||
typeOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'کیفی', value: 'active'},
|
||||
{label: 'عمده ای', value: 'deactivated'},
|
||||
{label: 'تک فروشی', value: 'blocked'}
|
||||
],
|
||||
statusOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'فعال', value: 'active'},
|
||||
{label: 'غیر فعال', value: 'deactivated'}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
key: '1',
|
||||
cat: "1399-01-25 10:25",
|
||||
name: "علی منتظر",
|
||||
bag_name: "محسن شاهکار",
|
||||
phone: "09128081392",
|
||||
last_order: "1399-01-20 10:25",
|
||||
gold: "25.000 بد",
|
||||
rial: "1.250.200 بد",
|
||||
},
|
||||
],
|
||||
searchQuery: '',
|
||||
// AgGrid
|
||||
gridApi: null,
|
||||
cols: null,
|
||||
gridOptions: {},
|
||||
defaultColDef: {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
suppressMenu: true
|
||||
},
|
||||
// Cell Renderer Components
|
||||
components: {
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleFilter(obj) {
|
||||
this.setColumnFilter('role', obj.value)
|
||||
},
|
||||
statusFilter(obj) {
|
||||
this.setColumnFilter('status', obj.value)
|
||||
},
|
||||
isVerifiedFilter(obj) {
|
||||
const val = obj.value === 'all' ? 'all' : obj.value === 'yes' ? 'true' : 'false'
|
||||
this.setColumnFilter('is_verified', val)
|
||||
},
|
||||
departmentFilter(obj) {
|
||||
this.setColumnFilter('department', obj.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
usersData() {
|
||||
return this.$store.state.userManagement.users
|
||||
},
|
||||
paginationPageSize() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetPageSize()
|
||||
else return 10
|
||||
},
|
||||
totalPages() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetTotalPages()
|
||||
else return 0
|
||||
},
|
||||
currentPage: {
|
||||
get() {
|
||||
// if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1
|
||||
return 1
|
||||
},
|
||||
set(val) {
|
||||
// this.gridApi.paginationGoToPage(val - 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setColumnFilter(column, val) {
|
||||
const filter = this.gridApi.getFilterInstance(column)
|
||||
let modelObj = null
|
||||
|
||||
if (val !== 'all') {
|
||||
modelObj = {type: 'equals', filter: val}
|
||||
}
|
||||
|
||||
filter.setModel(modelObj)
|
||||
this.gridApi.onFilterChanged()
|
||||
},
|
||||
toEdit() {
|
||||
this.$router.push({name: 'app-customer-edit', params: {userId: 268}})
|
||||
},
|
||||
confirmDelete() {
|
||||
this.gridApi.onFilterChanged();
|
||||
},
|
||||
resetColFilters() {
|
||||
this.$refs.filterCard.removeRefreshAnimation()
|
||||
},
|
||||
updateSearchQuery(val) {
|
||||
this.gridApi.setQuickFilter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cols = TableCol.default;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,245 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card
|
||||
ref="filterCard"
|
||||
refresh-content-action
|
||||
:removeCardAction="false"
|
||||
@refresh="resetColFilters"
|
||||
title="لیست پورسانت ها" class="vx-card">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="flex flex-wrap items-center mb-4">
|
||||
|
||||
|
||||
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
|
||||
<div class="flex-1">
|
||||
<a-input class="md:w-1/2" v-model="searchQuery" placeholder="جستجو">
|
||||
<a-icon slot="prefix" type="search"/>
|
||||
</a-input>
|
||||
</div>
|
||||
|
||||
|
||||
<a-dropdown-button>
|
||||
عملیات
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">
|
||||
تایید دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
حذف دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
خروجی اکسل
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown-button>
|
||||
</div>
|
||||
<VsDivider/>
|
||||
|
||||
<AModal :visible.sync="detailsPopup" @cancel="()=>detailsPopup = false" :zIndex="410000" width="80%"
|
||||
:footer="null">
|
||||
<div>
|
||||
<CustomerView/>
|
||||
</div>
|
||||
</AModal>
|
||||
|
||||
<ATable
|
||||
class="p-0 m-0"
|
||||
:pagination="false"
|
||||
:columns="cols" :data-source="data">
|
||||
<div slot="block" slot-scope="data">
|
||||
<FeatherIcon icon="CheckIcon"/>
|
||||
</div>
|
||||
<div slot="expandedRowRender" slot-scope="record">
|
||||
<span>علت مسدود سازی : </span>
|
||||
<p class="text-danger">{{record.block}}</p>
|
||||
</div>
|
||||
<div slot="op">
|
||||
<ATooltip>
|
||||
<span slot="title">مشاهده</span>
|
||||
<FeatherIcon icon="InfoIcon" svgClasses="h-6 w-6 text-warning"
|
||||
class="cursor-pointer mx-1"/>
|
||||
</ATooltip>
|
||||
<ATooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر" @confirm="confirmDelete()">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="h-6 w-6 text-danger" class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</ATooltip>
|
||||
</div>
|
||||
</ATable>
|
||||
<vs-pagination
|
||||
class="mt-4"
|
||||
:total="totalPages"
|
||||
:max="7"
|
||||
v-model="currentPage"/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
// Store Module
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
// Cell Renderer
|
||||
import CellRendererLink from '../user/user-list/cell-renderer/CellRendererLink.vue'
|
||||
import CellRendererStatus from '../user/user-list/cell-renderer/CellRendererStatus.vue'
|
||||
import CellRendererVerified from '../user/user-list/cell-renderer/CellRendererVerified.vue'
|
||||
import CellRendererActions from '../user/user-list/cell-renderer/CellRendererActions.vue'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from "@/table/fee";
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CustomerView,
|
||||
vSelect,
|
||||
// Cell Renderer
|
||||
FeatherIcon,
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Filter Options
|
||||
filterType: 'all',
|
||||
filterSts: 'all',
|
||||
detailsPopup: false,
|
||||
typeOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'کیفی', value: 'active'},
|
||||
{label: 'عمده ای', value: 'deactivated'},
|
||||
{label: 'تک فروشی', value: 'blocked'}
|
||||
],
|
||||
statusOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'فعال', value: 'active'},
|
||||
{label: 'غیر فعال', value: 'deactivated'}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
key: '1',
|
||||
cat: "1399-01-25 10:25",
|
||||
from: "1399-01-20 10:25",
|
||||
to: "1399-01-25 10:25",
|
||||
when: "1399-01-26 10:25",
|
||||
from_name: "علی منتظر",
|
||||
to_name: "محسن برازنده",
|
||||
sts: "انجام نشده",
|
||||
sts_f: "واریز نشده",
|
||||
block: "شماره حساب مشخص نشده است",
|
||||
bloc_why: ""
|
||||
},
|
||||
],
|
||||
searchQuery: '',
|
||||
// AgGrid
|
||||
gridApi: null,
|
||||
cols: null,
|
||||
gridOptions: {},
|
||||
defaultColDef: {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
suppressMenu: true
|
||||
},
|
||||
// Cell Renderer Components
|
||||
components: {
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleFilter(obj) {
|
||||
this.setColumnFilter('role', obj.value)
|
||||
},
|
||||
statusFilter(obj) {
|
||||
this.setColumnFilter('status', obj.value)
|
||||
},
|
||||
isVerifiedFilter(obj) {
|
||||
const val = obj.value === 'all' ? 'all' : obj.value === 'yes' ? 'true' : 'false'
|
||||
this.setColumnFilter('is_verified', val)
|
||||
},
|
||||
departmentFilter(obj) {
|
||||
this.setColumnFilter('department', obj.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
usersData() {
|
||||
return this.$store.state.userManagement.users
|
||||
},
|
||||
paginationPageSize() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetPageSize()
|
||||
else return 10
|
||||
},
|
||||
totalPages() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetTotalPages()
|
||||
else return 0
|
||||
},
|
||||
currentPage: {
|
||||
get() {
|
||||
// if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1
|
||||
return 1
|
||||
},
|
||||
set(val) {
|
||||
// this.gridApi.paginationGoToPage(val - 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setColumnFilter(column, val) {
|
||||
const filter = this.gridApi.getFilterInstance(column)
|
||||
let modelObj = null
|
||||
|
||||
if (val !== 'all') {
|
||||
modelObj = {type: 'equals', filter: val}
|
||||
}
|
||||
|
||||
filter.setModel(modelObj)
|
||||
this.gridApi.onFilterChanged()
|
||||
},
|
||||
toEdit() {
|
||||
this.$router.push({name: 'app-customer-edit', params: {userId: 268}})
|
||||
},
|
||||
confirmDelete() {
|
||||
this.gridApi.onFilterChanged();
|
||||
},
|
||||
resetColFilters() {
|
||||
this.$refs.filterCard.removeRefreshAnimation()
|
||||
},
|
||||
updateSearchQuery(val) {
|
||||
this.gridApi.setQuickFilter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cols = TableCol.default;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,274 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card
|
||||
ref="filterCard"
|
||||
refresh-content-action
|
||||
:removeCardAction="false"
|
||||
@refresh="resetColFilters"
|
||||
title="سفارش ها" class="vx-card">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="flex flex-wrap items-center mb-4">
|
||||
|
||||
|
||||
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
|
||||
<div class="flex-1">
|
||||
<a-input class="md:w-1/2" v-model="searchQuery" placeholder="جستجو">
|
||||
<a-icon slot="prefix" type="search"/>
|
||||
</a-input>
|
||||
</div>
|
||||
|
||||
|
||||
<a-dropdown-button>
|
||||
عملیات
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">
|
||||
تایید دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
حذف دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
خروجی اکسل
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown-button>
|
||||
</div>
|
||||
<VsDivider/>
|
||||
|
||||
<AModal :visible.sync="detailsPopup" @cancel="()=>detailsPopup = false" :zIndex="410000" width="80%"
|
||||
:footer="null">
|
||||
<div>
|
||||
<h2>مشاهده اطلاعات سفارش</h2>
|
||||
<ATable :pagination="false"
|
||||
:columns="colsInner" :data-source="dataInner"
|
||||
>
|
||||
<div slot="expandedRowRender" slot-scope="record">
|
||||
<p>{{record.note}}</p>
|
||||
</div>
|
||||
</ATable>
|
||||
</div>
|
||||
</AModal>
|
||||
|
||||
<ATable
|
||||
class="p-0 m-0"
|
||||
:pagination="false"
|
||||
:columns="cols" :data-source="data">
|
||||
<div slot-scope="record" slot="expandedRowRender">
|
||||
<span class="text-danger">شرح سفارش: </span>
|
||||
<p>
|
||||
{{record.note}}
|
||||
</p>
|
||||
</div>
|
||||
<div slot="id" slot-scope="data">
|
||||
<a @click="()=>detailsPopup = true" class="text-primary">{{data}}</a>
|
||||
</div>
|
||||
<div slot="op">
|
||||
<ATooltip>
|
||||
<span slot="title">مشاهده</span>
|
||||
<FeatherIcon icon="InfoIcon" @click="detailsPopup = true" svgClasses="h-6 w-6 text-warning"
|
||||
class="cursor-pointer mx-1"/>
|
||||
</ATooltip>
|
||||
<ATooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر" @confirm="confirmDelete()">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="h-6 w-6 text-danger" class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</ATooltip>
|
||||
</div>
|
||||
</ATable>
|
||||
<vs-pagination
|
||||
class="mt-4"
|
||||
:total="totalPages"
|
||||
:max="7"
|
||||
v-model="currentPage"/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
// Store Module
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
// Cell Renderer
|
||||
import CellRendererLink from '../user/user-list/cell-renderer/CellRendererLink.vue'
|
||||
import CellRendererStatus from '../user/user-list/cell-renderer/CellRendererStatus.vue'
|
||||
import CellRendererVerified from '../user/user-list/cell-renderer/CellRendererVerified.vue'
|
||||
import CellRendererActions from '../user/user-list/cell-renderer/CellRendererActions.vue'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from "@/table/order";
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CustomerView,
|
||||
vSelect,
|
||||
// Cell Renderer
|
||||
FeatherIcon,
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Filter Options
|
||||
filterType: 'all',
|
||||
filterSts: 'all',
|
||||
detailsPopup: false,
|
||||
typeOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'کیفی', value: 'active'},
|
||||
{label: 'عمده ای', value: 'deactivated'},
|
||||
{label: 'تک فروشی', value: 'blocked'}
|
||||
],
|
||||
statusOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'فعال', value: 'active'},
|
||||
{label: 'غیر فعال', value: 'deactivated'}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
key: '1',
|
||||
id: "#125000",
|
||||
w: "250",
|
||||
debt: "250.000",
|
||||
w_debt: "150 گرم",
|
||||
price: "150.100",
|
||||
p_debt: "250.000",
|
||||
p_to: "154.250.000",
|
||||
bag: "علی منتظر",
|
||||
note: "نکته مهم دیگر این است که وقتی بر پایه یک کالا گواهی سپرده صادر می شود، آن کالا قابلیت قرار گرفتن در سبد سرمایه گذاری افراد را پیدا می کند. به این ترتیب، شرکت های سبدگردانی نیز می توانند سبد متنوعی از انواع دارایی ها ",
|
||||
},
|
||||
],
|
||||
dataInner: [
|
||||
{
|
||||
|
||||
name: "انگشتر نگین 120",
|
||||
total: "2 عدد",
|
||||
creator: "طلای جمشید",
|
||||
supplier: "محمد غفرانی",
|
||||
id: "#125000",
|
||||
w: "250",
|
||||
debt: "250.000",
|
||||
w_debt: "150 گرم",
|
||||
price: "150.100",
|
||||
p_debt: "250.000",
|
||||
p_to: "154.250.000",
|
||||
bag: "علی منتظر",
|
||||
note: "نکته مهم دیگر این است که وقتی بر پایه یک کالا گواهی سپرده صادر می شود، آن کالا قابلیت قرار گرفتن در سبد سرمایه گذاری افراد را پیدا می کند. به این ترتیب، شرکت های سبدگردانی نیز می توانند سبد متنوعی از انواع دارایی ها ",
|
||||
},
|
||||
],
|
||||
searchQuery: '',
|
||||
// AgGrid
|
||||
gridApi: null,
|
||||
cols: null,
|
||||
colsInner: null,
|
||||
gridOptions: {},
|
||||
defaultColDef: {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
suppressMenu: true
|
||||
},
|
||||
// Cell Renderer Components
|
||||
components: {
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleFilter(obj) {
|
||||
this.setColumnFilter('role', obj.value)
|
||||
},
|
||||
statusFilter(obj) {
|
||||
this.setColumnFilter('status', obj.value)
|
||||
},
|
||||
isVerifiedFilter(obj) {
|
||||
const val = obj.value === 'all' ? 'all' : obj.value === 'yes' ? 'true' : 'false'
|
||||
this.setColumnFilter('is_verified', val)
|
||||
},
|
||||
departmentFilter(obj) {
|
||||
this.setColumnFilter('department', obj.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
usersData() {
|
||||
return this.$store.state.userManagement.users
|
||||
},
|
||||
paginationPageSize() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetPageSize()
|
||||
else return 10
|
||||
},
|
||||
totalPages() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetTotalPages()
|
||||
else return 0
|
||||
},
|
||||
currentPage: {
|
||||
get() {
|
||||
// if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1
|
||||
return 1
|
||||
},
|
||||
set(val) {
|
||||
// this.gridApi.paginationGoToPage(val - 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setColumnFilter(column, val) {
|
||||
const filter = this.gridApi.getFilterInstance(column)
|
||||
let modelObj = null
|
||||
|
||||
if (val !== 'all') {
|
||||
modelObj = {type: 'equals', filter: val}
|
||||
}
|
||||
|
||||
filter.setModel(modelObj)
|
||||
this.gridApi.onFilterChanged()
|
||||
},
|
||||
toEdit() {
|
||||
this.$router.push({name: 'app-customer-edit', params: {userId: 268}})
|
||||
},
|
||||
confirmDelete() {
|
||||
this.gridApi.onFilterChanged();
|
||||
},
|
||||
resetColFilters() {
|
||||
this.$refs.filterCard.removeRefreshAnimation()
|
||||
},
|
||||
updateSearchQuery(val) {
|
||||
this.gridApi.setQuickFilter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cols = TableCol.default;
|
||||
this.colsInner = new TableCol.TableInner().cols;
|
||||
console.log("this.colsInner ==> ", this.colsInner);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,111 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="صندوق ورودی پیام ها ازفرم سایت">
|
||||
<XTable :model="getColTable" ref="contact">
|
||||
<span slot="opt" slot-scope="text,record" :style="{display:'flex',justifyContent:'space-evenly'}">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>حذف</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آیا می خواهید حذف کنید؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="okDelete(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="TrashIcon" svgClasses="w-5 h-5 text-danger" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>مشاهده</span>
|
||||
</template>
|
||||
<feather-icon icon="EyeIcon" @click="view(text.record.id)" svgClasses="w-5 h-5" style="cursor: pointer"/>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</XTable>
|
||||
<a-modal :width="1000" v-model="visible" title="وضعیت" ok-text="ارسال پیام" cancel-text="ردکردن" >
|
||||
<div v-if="modalLoading">
|
||||
<ASkeleton />
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-descriptions layout="vertical">
|
||||
<a-descriptions-item label="نام">
|
||||
{{DataModal.name}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شماره موبایل">
|
||||
{{ DataModal.mobile }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="ارسال شده در">
|
||||
{{ DataModal.created_at | jdate }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="ایمیل">
|
||||
{{DataModal.email}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="متن پیام">
|
||||
{{DataModal.body}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="موضوع">
|
||||
{{DataModal.subject}}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
</a-modal>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableInbox'
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "inbox-message",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
getColTable: undefined,
|
||||
visible: false,
|
||||
modalLoading: false,
|
||||
DataModal: {}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
view(id) {
|
||||
this.modalLoading = true;
|
||||
this.visible = true;
|
||||
this.getDataModal(id);
|
||||
},
|
||||
async getDataModal(id) {
|
||||
try {
|
||||
const {data} = await axios.get(`admin/contact/${id}`)
|
||||
this.DataModal = data;
|
||||
} catch (e) {
|
||||
this.visible = false;
|
||||
} finally {
|
||||
this.modalLoading = false;
|
||||
}
|
||||
},
|
||||
async okDelete(id){
|
||||
try{
|
||||
await axios.delete(`admin/contact/${id}`)
|
||||
this.$refs.contact.fetch()
|
||||
this.$ntSet('باموفقیت حذف شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getColTable = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,17 +0,0 @@
|
||||
import XTbl,{Xtc} from '../../../components/x-table/index';
|
||||
|
||||
const tbl = new XTbl('/admin/contact/table', 'لیست صندوق ورودی');
|
||||
|
||||
tbl.add(new Xtc('name', 'نام').filterText())
|
||||
tbl.add(new Xtc('mobile', 'شماره موبایل').filterNumber())
|
||||
tbl.add(new Xtc('email', 'ایمیل').filterText())
|
||||
tbl.add(new Xtc('subject', 'موضوع').filterText())
|
||||
tbl.add(new Xtc('body', 'متن پیام').filterText())
|
||||
tbl.add(new Xtc('vaj', 'تاریخ وساعت ارسال').hidden().filterDate())
|
||||
tbl.add(new Xtc('responser_id', 'بررسی کننده').hidden().filterText())
|
||||
tbl.add(new Xtc('response_message', 'پاسخ به ناظر').hidden().filterText())
|
||||
tbl.add(new Xtc('opt', 'عملیات').noSort().renderSlot('opt'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card
|
||||
ref="filterCard"
|
||||
refresh-content-action
|
||||
:removeCardAction="false"
|
||||
@refresh="resetColFilters"
|
||||
title="رویدادهای سیستمی" class="vx-card">
|
||||
<div>
|
||||
<div class="flex flex-wrap items-center mb-4">
|
||||
|
||||
|
||||
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
|
||||
<div class="flex-1">
|
||||
<a-input class="md:w-1/2" v-model="searchQuery" placeholder="جستجو">
|
||||
<a-icon slot="prefix" type="search"/>
|
||||
</a-input>
|
||||
</div>
|
||||
|
||||
|
||||
<a-dropdown-button>
|
||||
عملیات
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">
|
||||
تایید دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
حذف دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
خروجی اکسل
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown-button>
|
||||
</div>
|
||||
<VsDivider/>
|
||||
|
||||
<AModal :visible.sync="detailsPopup" @cancel="()=>detailsPopup = false" :zIndex="410000" width="80%"
|
||||
:footer="null">
|
||||
<div>
|
||||
<CustomerView/>
|
||||
</div>
|
||||
</AModal>
|
||||
|
||||
<ATable
|
||||
class="p-0 m-0"
|
||||
:pagination="false"
|
||||
:columns="cols" :data-source="data">
|
||||
<div slot="op">
|
||||
<ATooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر" @confirm="confirmDelete()">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="h-6 w-6 text-danger" class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</ATooltip>
|
||||
</div>
|
||||
</ATable>
|
||||
<vs-pagination
|
||||
class="mt-4"
|
||||
:total="totalPages"
|
||||
:max="7"
|
||||
v-model="currentPage"/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
// Store Module
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
// Cell Renderer
|
||||
import CellRendererLink from '../user/user-list/cell-renderer/CellRendererLink.vue'
|
||||
import CellRendererStatus from '../user/user-list/cell-renderer/CellRendererStatus.vue'
|
||||
import CellRendererVerified from '../user/user-list/cell-renderer/CellRendererVerified.vue'
|
||||
import CellRendererActions from '../user/user-list/cell-renderer/CellRendererActions.vue'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from "@/table/logs";
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CustomerView,
|
||||
vSelect,
|
||||
// Cell Renderer
|
||||
FeatherIcon,
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Filter Options
|
||||
filterType: 'all',
|
||||
filterSts: 'all',
|
||||
detailsPopup: false,
|
||||
typeOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'کیفی', value: 'active'},
|
||||
{label: 'عمده ای', value: 'deactivated'},
|
||||
{label: 'تک فروشی', value: 'blocked'}
|
||||
],
|
||||
statusOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'فعال', value: 'active'},
|
||||
{label: 'غیر فعال', value: 'deactivated'}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
key: '1',
|
||||
user: 'علی قربانی',
|
||||
cat: '25-01-99 10:26',
|
||||
title: 'ثبت سفارش #124523'
|
||||
},
|
||||
],
|
||||
searchQuery: '',
|
||||
// AgGrid
|
||||
gridApi: null,
|
||||
cols: null,
|
||||
gridOptions: {},
|
||||
defaultColDef: {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
suppressMenu: true
|
||||
},
|
||||
// Cell Renderer Components
|
||||
components: {
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleFilter(obj) {
|
||||
this.setColumnFilter('role', obj.value)
|
||||
},
|
||||
statusFilter(obj) {
|
||||
this.setColumnFilter('status', obj.value)
|
||||
},
|
||||
isVerifiedFilter(obj) {
|
||||
const val = obj.value === 'all' ? 'all' : obj.value === 'yes' ? 'true' : 'false'
|
||||
this.setColumnFilter('is_verified', val)
|
||||
},
|
||||
departmentFilter(obj) {
|
||||
this.setColumnFilter('department', obj.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
usersData() {
|
||||
return this.$store.state.userManagement.users
|
||||
},
|
||||
paginationPageSize() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetPageSize()
|
||||
else return 10
|
||||
},
|
||||
totalPages() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetTotalPages()
|
||||
else return 0
|
||||
},
|
||||
currentPage: {
|
||||
get() {
|
||||
// if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1
|
||||
return 1
|
||||
},
|
||||
set(val) {
|
||||
// this.gridApi.paginationGoToPage(val - 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setColumnFilter(column, val) {
|
||||
const filter = this.gridApi.getFilterInstance(column)
|
||||
let modelObj = null
|
||||
|
||||
if (val !== 'all') {
|
||||
modelObj = {type: 'equals', filter: val}
|
||||
}
|
||||
|
||||
filter.setModel(modelObj)
|
||||
this.gridApi.onFilterChanged()
|
||||
},
|
||||
toEdit() {
|
||||
this.$router.push({name: 'app-customer-edit', params: {userId: 268}})
|
||||
},
|
||||
confirmDelete() {
|
||||
this.gridApi.onFilterChanged();
|
||||
},
|
||||
resetColFilters() {
|
||||
this.$refs.filterCard.removeRefreshAnimation()
|
||||
},
|
||||
updateSearchQuery(val) {
|
||||
this.gridApi.setQuickFilter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cols = TableCol.default;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,168 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card
|
||||
ref="filterCard"
|
||||
title="قوانین دسترسی" class="vx-card">
|
||||
<a-skeleton active />
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
// Store Module
|
||||
import moduleUserManagement from '@/store/user-management/moduleUserManagement.js'
|
||||
|
||||
// Cell Renderer
|
||||
import CellRendererLink from '../user/user-list/cell-renderer/CellRendererLink.vue'
|
||||
import CellRendererStatus from '../user/user-list/cell-renderer/CellRendererStatus.vue'
|
||||
import CellRendererVerified from '../user/user-list/cell-renderer/CellRendererVerified.vue'
|
||||
import CellRendererActions from '../user/user-list/cell-renderer/CellRendererActions.vue'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from "@/table/bag";
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CustomerView,
|
||||
vSelect,
|
||||
// Cell Renderer
|
||||
FeatherIcon,
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Filter Options
|
||||
filterType: 'all',
|
||||
filterSts: 'all',
|
||||
detailsPopup: false,
|
||||
typeOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'کیفی', value: 'active'},
|
||||
{label: 'عمده ای', value: 'deactivated'},
|
||||
{label: 'تک فروشی', value: 'blocked'}
|
||||
],
|
||||
statusOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'فعال', value: 'active'},
|
||||
{label: 'غیر فعال', value: 'deactivated'}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
key: '1',
|
||||
bag_name: 'محمد آذری',
|
||||
customer: 'علی قربانی',
|
||||
cat: '25-01-99 10:26',
|
||||
price: '2,500,000',
|
||||
w: '250 گرم',
|
||||
sts: 'پردازش نشده',
|
||||
when: '2 اردیبهشت 99',
|
||||
},
|
||||
],
|
||||
searchQuery: '',
|
||||
// AgGrid
|
||||
gridApi: null,
|
||||
cols: null,
|
||||
gridOptions: {},
|
||||
defaultColDef: {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
suppressMenu: true
|
||||
},
|
||||
// Cell Renderer Components
|
||||
components: {
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleFilter(obj) {
|
||||
this.setColumnFilter('role', obj.value)
|
||||
},
|
||||
statusFilter(obj) {
|
||||
this.setColumnFilter('status', obj.value)
|
||||
},
|
||||
isVerifiedFilter(obj) {
|
||||
const val = obj.value === 'all' ? 'all' : obj.value === 'yes' ? 'true' : 'false'
|
||||
this.setColumnFilter('is_verified', val)
|
||||
},
|
||||
departmentFilter(obj) {
|
||||
this.setColumnFilter('department', obj.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
usersData() {
|
||||
return this.$store.state.userManagement.users
|
||||
},
|
||||
paginationPageSize() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetPageSize()
|
||||
else return 10
|
||||
},
|
||||
totalPages() {
|
||||
if (this.gridApi) return this.gridApi.paginationGetTotalPages()
|
||||
else return 0
|
||||
},
|
||||
currentPage: {
|
||||
get() {
|
||||
// if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1
|
||||
return 1
|
||||
},
|
||||
set(val) {
|
||||
// this.gridApi.paginationGoToPage(val - 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setColumnFilter(column, val) {
|
||||
const filter = this.gridApi.getFilterInstance(column)
|
||||
let modelObj = null
|
||||
|
||||
if (val !== 'all') {
|
||||
modelObj = {type: 'equals', filter: val}
|
||||
}
|
||||
|
||||
filter.setModel(modelObj)
|
||||
this.gridApi.onFilterChanged()
|
||||
},
|
||||
toEdit() {
|
||||
this.$router.push({name: 'app-customer-edit', params: {userId: 268}})
|
||||
},
|
||||
confirmDelete() {
|
||||
this.gridApi.onFilterChanged();
|
||||
},
|
||||
resetColFilters() {
|
||||
this.$refs.filterCard.removeRefreshAnimation()
|
||||
},
|
||||
updateSearchQuery(val) {
|
||||
this.gridApi.setQuickFilter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cols = TableCol.default;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,71 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<vx-card title="تعداددیدگاه های ثبت شده در بازه های زمانی مختلف" style="margin-top: 2rem">
|
||||
<apexchart height="400" type="bar" :options="chartOptions" :series="series"></apexchart>
|
||||
</vx-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import VueApexCharts from 'vue-apexcharts'
|
||||
import axios from '@/axios'
|
||||
|
||||
|
||||
export default {
|
||||
name: "ChartOpinions",
|
||||
components:{
|
||||
apexchart:VueApexCharts
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
series:[],
|
||||
chartOptions:{}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
async getOpinionWeblogAdv(){
|
||||
const {data} = await axios.get('/admin/comment/query/date')
|
||||
const y = data.map(item=>item.count);
|
||||
const title = data.map((chart)=> chart.date != null ? chart.date : 'سایر تاریخ های ثبت شده دیدگاه');
|
||||
this.series= [
|
||||
{
|
||||
name:"تعداد دیدگاه",
|
||||
data: y
|
||||
}
|
||||
]
|
||||
this.chartOptions = {
|
||||
colors: ['#4f72ab'],
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: title,
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 2000,
|
||||
options: {
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: "bottom"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getOpinionWeblogAdv()
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="لیست دیدگاه ها">
|
||||
<XTable :model="getColTable" ref="comment">
|
||||
<span slot="names" slot-scope="text,record" class="flex space-x-3">
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>نظارت</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="دیدگاه موردنظر را تاییدمی کنید؟"
|
||||
ok-text="تایید"
|
||||
cancel-text="رد"
|
||||
@confirm="ok(text.record.id)"
|
||||
@cancel="cancelComment(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="EyeIcon" svgClasses="w-5 h-5 text-warning" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<template slot="title">
|
||||
<span>حذف</span>
|
||||
</template>
|
||||
<a-popconfirm
|
||||
title="آیا می خواهید حذف کنید؟"
|
||||
ok-text="بله"
|
||||
cancel-text="خیر"
|
||||
@confirm="okDelete(text.record.id)"
|
||||
>
|
||||
<feather-icon icon="TrashIcon" svgClasses="w-5 h-5 text-danger" style="cursor: pointer"/>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</XTable>
|
||||
<a-modal
|
||||
title="ایجادکامنت"
|
||||
:visible="visible"
|
||||
@cancel="close"
|
||||
>
|
||||
<a-form :form="form" @submit="submitComment">
|
||||
<a-form-item label="متن">
|
||||
<a-textarea v-decorator="['body',{ rules: [{ required: true, message: 'لطفامقدار مورد نظر را انتخاب کنید' }] },]"/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button html-type="submit">ثبت</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
<a-modal v-model="visibleSendMsg" title="ارسال پیام" ok-text="تایید" cancel-text="رد" :ok-button-props="{ props: { disabled: true } }" :cancel-button-props="{ props: { disabled: true }}">
|
||||
<a-form :form="formSendMsg" @submit="submitSendMessage">
|
||||
<a-form-item label="توضیحات">
|
||||
<a-textarea
|
||||
v-decorator="['message',{ rules: [{ required: true, message: 'لطفامقدار مورد نظر را انتخاب کنید'}]}]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button html-type="submit" type="primary">
|
||||
ارسال
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableOpinions'
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "listOpinions",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
getColTable: undefined,
|
||||
visible:false,
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
formSendMsg: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
tempRow:undefined,
|
||||
visibleSendMsg:false,
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
async ok(id){
|
||||
try{
|
||||
await axios.put(`/admin/comment/${id}`,{data:{sts:2}})
|
||||
this.$refs.comment.fetch()
|
||||
this.$ntSet('دیدگاه تایید شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
async cancelComment(id){
|
||||
try{
|
||||
await axios.put(`/admin/comment/${id}`,{data:{sts:1}})
|
||||
this.$refs.comment.fetch()
|
||||
this.$ntSet('دیدگاه رد شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
async okDelete(id){
|
||||
try{
|
||||
await axios.delete(`/admin/comment/${id}`)
|
||||
this.$refs.comment.fetch()
|
||||
this.$ntSet('دیدگاه حذف شد.')
|
||||
}catch (e) {
|
||||
this.$ntSetError()
|
||||
}finally {
|
||||
|
||||
}
|
||||
},
|
||||
response(id){
|
||||
this.visible = true
|
||||
this.tempRow = id
|
||||
},
|
||||
submitComment(e){
|
||||
const id = this.tempRow;
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try {
|
||||
await axios.post('admin/comment',{data:{body:values.body,parent_id:id}})
|
||||
this.form.resetFields()
|
||||
this.$refs.comment.fetch()
|
||||
this.$ntSet('دیدگاه با موفقیت ایجاد شد.')
|
||||
this.visible = false
|
||||
} catch (e) {
|
||||
this.$ntSetError()
|
||||
} finally {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
close(){
|
||||
this.visible = false
|
||||
},
|
||||
send(id){
|
||||
console.log(id,'id')
|
||||
this.visibleSendMsg = true;
|
||||
this.tempRowId = id
|
||||
},
|
||||
submitSendMessage(e) {
|
||||
const id = this.tempRowId;
|
||||
e.preventDefault();
|
||||
this.formSendMsg.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try {
|
||||
await axios.post('admin/comment/message', {
|
||||
message: values.message,
|
||||
id: id
|
||||
})
|
||||
this.$ntSet('ارسال پیام با موفقیت انجام شد.')
|
||||
this.visibleSendMsg = false
|
||||
} catch (e) {
|
||||
this.visibleSendMsg = false
|
||||
this.$ntSetError()
|
||||
} finally {
|
||||
this.formSendMsg.resetFields()
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
},
|
||||
created() {
|
||||
this.getColTable = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
[dir] .ant-modal-footer{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import XTbl,{Xtc} from '../../../components/x-table/index';
|
||||
|
||||
const tbl = new XTbl('/admin/comment/table', 'لیست دیدگاه ها');
|
||||
|
||||
tbl.add(new Xtc('body', 'بدنه دیدگاه').filterText())
|
||||
tbl.add(new Xtc('body', 'دیدگاه').hidden().filterText())
|
||||
tbl.add(new Xtc('meta', 'توضیحات').hidden().filterNumber())
|
||||
tbl.add(new Xtc('owner.name', 'نام تاییدکننده').filterNumber())
|
||||
tbl.add(new Xtc('owner.mobile', 'موبایل تاییدکننده').filterDate())
|
||||
tbl.add(new Xtc('subject', 'موضوع دیدگاه').filterText())
|
||||
tbl.add(new Xtc('acceptor', 'تاییدکننده').filterText())
|
||||
tbl.add(new Xtc('sts_str', 'وضعیت' ).filterSelect())
|
||||
tbl.add(new Xtc('vaj', 'تاریخ نظارت').hidden().filterDate())
|
||||
tbl.add(new Xtc('opt', 'عملیات').noSort().renderSlot('names'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserView.vue
|
||||
Description: User View page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div id="page-user-view">
|
||||
|
||||
<div id="user-data">
|
||||
<a-form :form="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" @submit="handleSubmit">
|
||||
|
||||
<ASpin type="loading" :spinning="loading">
|
||||
<vx-card title="اطلاعات پایه" class="mb-base">
|
||||
<!-- Avatar -->
|
||||
<div class="vx-row">
|
||||
<!-- Information - Col 1 -->
|
||||
<div class="vx-col flex-1" id="account-info-col-1">
|
||||
<a-form-item label="کد محصول">
|
||||
<a-input
|
||||
v-decorator="['product_code', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="نام محصول">
|
||||
<a-input
|
||||
v-decorator="['title', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="شرح محصول">
|
||||
<a-textarea
|
||||
v-decorator="['body_html', {}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="دسته بندی ">
|
||||
<QuerySelect ref="qs" url="category" v-decorator="['category_id',{
|
||||
rules: [{ required: true, message: 'وارد کردن دسته بندی الزامی است' }] },]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</vx-card>
|
||||
</ASpin>
|
||||
<!-- Images -->
|
||||
<vx-card class="mb-8">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="flex items-end px-3">
|
||||
<feather-icon svgClasses="w-6 h-6" icon="CameraIcon" class="mr-2"/>
|
||||
<span class="font-medium text-lg leading-none">تصاویر</span>
|
||||
</div>
|
||||
<vs-divider/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
<div class="w-full">
|
||||
<AUploadDragger
|
||||
name="image"
|
||||
:multiple="false"
|
||||
|
||||
:action="uploadURl"
|
||||
v-if="!thumb"
|
||||
@change="handleChangeThumb"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<a-icon type="inbox"/>
|
||||
</p>
|
||||
<p class="ant-upload-text">
|
||||
تصویر شاخص محصول
|
||||
</p>
|
||||
<p class="ant-upload-hint">
|
||||
تصاویر باید پسوند png داشته باشند و حداکثر 1 مگابایت حجم داشته باشند.
|
||||
</p>
|
||||
</AUploadDragger>
|
||||
<div v-else class="relative" style="width: 200px;">
|
||||
<VsImage :src="thumb.image" class="w-full"/>
|
||||
<div class="absolute cursor-pointer"
|
||||
@click="removeThumb"
|
||||
style="background-color: #f5222d;top: 0;z-index: 1500;margin: auto;display: flex;padding: 5px;border-radius: 5px;">
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="text-white"/>
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-4/5" v-if="false">
|
||||
<AUploadDragger
|
||||
name="image"
|
||||
:multiple="true"
|
||||
:action="uploadURl"
|
||||
@change="handleChange"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<a-icon type="inbox"/>
|
||||
</p>
|
||||
<p class="ant-upload-text">
|
||||
تصاویر این محصول را در این قسمت بارگذاری کنید.
|
||||
</p>
|
||||
<p class="ant-upload-hint">
|
||||
تصاویر باید پسوند png داشته باشند و حداکثر 1 مگابایت حجم داشته باشند.
|
||||
</p>
|
||||
</AUploadDragger>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</vx-card>
|
||||
|
||||
|
||||
<!-- /Information - Col 2 -->
|
||||
<div class="vx-col w-full flex mb-4">
|
||||
<vs-button icon-pack="feather" :disabled="loading" @click="handleSubmit" class="mr-4">
|
||||
<span v-if="!this.id">ثبت محصول</span>
|
||||
<span v-else>ویرایش</span>
|
||||
</vs-button>
|
||||
</div>
|
||||
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {baseURL} from "@/axios";
|
||||
import axios from "@/axios";
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import QuerySelect from "../../components/extra-components/query-select/QuerySelect";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
QuerySelect,
|
||||
FeatherIcon
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
uploadURl: baseURL + 'config/image',
|
||||
formLayout: 'horizontal',
|
||||
data: undefined,
|
||||
thumb: undefined,
|
||||
thumb_id: undefined,
|
||||
gallery: [],
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loading: {
|
||||
get() {
|
||||
return this.$store.state.variant.loading;
|
||||
},
|
||||
set(val) {
|
||||
this.$store.commit('product/LOADING', val)
|
||||
}
|
||||
},
|
||||
id() {
|
||||
return this.$router.history.current.params.id;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeThumb() {
|
||||
this.thumb = undefined;
|
||||
this.thumb_id = undefined;
|
||||
},
|
||||
async handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try {
|
||||
this.$vs.loading();
|
||||
const exp = Object.assign(values, {
|
||||
id: this.id,
|
||||
image_id: this.thumb_id
|
||||
});
|
||||
const {data} = await this.$store.dispatch('product/save', exp);
|
||||
this.$router.push({name: "product"});
|
||||
} catch (e) {
|
||||
console.log("e ==> ", e);
|
||||
} finally {
|
||||
this.$vs.loading.close();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
async getData() {
|
||||
if (this.id) {
|
||||
try {
|
||||
this.loading = true;
|
||||
const {data} = await axios.get(`product/${this.id}`);
|
||||
this.form.setFieldsValue({
|
||||
'product_code': data.product_code,
|
||||
'title': data.title,
|
||||
'body_html': data.body_html,
|
||||
})
|
||||
this.data = data;
|
||||
} catch (e) {
|
||||
this.$vs.notify({
|
||||
title: 'خطا در دریافت اطلاعات',
|
||||
text: `${e.message}`,
|
||||
color: 'danger'
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
handleChange(value) {
|
||||
let all = true;
|
||||
const items = _.map(value.fileList, 'response');
|
||||
for (let item of items) {
|
||||
if (!item) {
|
||||
all = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
this.gallery = items;
|
||||
console.log("this.gallery ==> ", this.gallery);
|
||||
}
|
||||
},
|
||||
handleChangeThumb(value) {
|
||||
if (value.fileList[0].response) {
|
||||
this.thumb = value.fileList[0].response;
|
||||
this.thumb_id = value.fileList[0].response.id;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getData();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#avatar-col {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
#page-user-view {
|
||||
table {
|
||||
td {
|
||||
vertical-align: top;
|
||||
min-width: 140px;
|
||||
padding-bottom: .8rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
&:not(.permissions-table) {
|
||||
td {
|
||||
@media screen and (max-width: 370px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #account-info-col-1 {
|
||||
// // flex-grow: 1;
|
||||
// width: 30rem !important;
|
||||
// @media screen and (min-width:1200px) {
|
||||
// & {
|
||||
// flex-grow: unset !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@media screen and (min-width: 1201px) and (max-width: 1211px),
|
||||
only screen and (min-width: 636px) and (max-width: 991px) {
|
||||
#account-info-col-1 {
|
||||
width: calc(100% - 12rem) !important;
|
||||
}
|
||||
|
||||
// #account-manage-buttons {
|
||||
// width: 12rem !important;
|
||||
// flex-direction: column;
|
||||
|
||||
// > button {
|
||||
// margin-right: 0 !important;
|
||||
// margin-bottom: 1rem;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,81 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserView.vue
|
||||
Description: User View page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<AddProduct />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AddProduct from "./AddProduct";
|
||||
|
||||
export default {
|
||||
components:{
|
||||
AddProduct
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#avatar-col {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
#page-user-view {
|
||||
table {
|
||||
td {
|
||||
vertical-align: top;
|
||||
min-width: 140px;
|
||||
padding-bottom: .8rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
&:not(.permissions-table) {
|
||||
td {
|
||||
@media screen and (max-width: 370px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #account-info-col-1 {
|
||||
// // flex-grow: 1;
|
||||
// width: 30rem !important;
|
||||
// @media screen and (min-width:1200px) {
|
||||
// & {
|
||||
// flex-grow: unset !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@media screen and (min-width: 1201px) and (max-width: 1211px),
|
||||
only screen and (min-width: 636px) and (max-width: 991px) {
|
||||
#account-info-col-1 {
|
||||
width: calc(100% - 12rem) !important;
|
||||
}
|
||||
|
||||
// #account-manage-buttons {
|
||||
// width: 12rem !important;
|
||||
// flex-direction: column;
|
||||
|
||||
// > button {
|
||||
// margin-right: 0 !important;
|
||||
// margin-bottom: 1rem;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,24 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserView.vue
|
||||
Description: User View page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Varaint/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Varaint from "./Varaint";
|
||||
export default {
|
||||
components: {
|
||||
Varaint
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,367 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserList.vue
|
||||
Description: User List page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
|
||||
<div id="page-user-list">
|
||||
|
||||
|
||||
<vx-card
|
||||
ref="filterCard"
|
||||
refresh-content-action
|
||||
:removeCardAction="false"
|
||||
@refresh="fetch"
|
||||
title="لیست محصولات" class="vx-card">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="flex flex-wrap items-center mb-4">
|
||||
|
||||
|
||||
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
|
||||
<div class="flex-1">
|
||||
<a-input class="md:w-1/2" v-model="searchQuery" @keyup.enter="fetch" placeholder="جستجو">
|
||||
<a-icon slot="prefix" type="search"/>
|
||||
</a-input>
|
||||
</div>
|
||||
|
||||
|
||||
<a-dropdown-button>
|
||||
عملیات
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">
|
||||
تایید دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
حذف دسته جمعی
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2">
|
||||
خروجی اکسل
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown-button>
|
||||
</div>
|
||||
<VsDivider/>
|
||||
|
||||
<AModal :visible.sync="detailsPopup" @cancel="()=>detailsPopup = false" :zIndex="410000" width="80%"
|
||||
:footer="null">
|
||||
<div>
|
||||
<h2>مشاهده اطلاعات </h2>
|
||||
<ADescriptions v-if="tempProduct">
|
||||
<ADescriptionsItem label="عنوان محصول">
|
||||
{{tempProduct.title}}
|
||||
</ADescriptionsItem>
|
||||
<ADescriptionsItem label="کد محصول">
|
||||
{{tempProduct.product_code}}
|
||||
</ADescriptionsItem>
|
||||
|
||||
<ADescriptionsItem label="فعال">
|
||||
<FeatherIcon icon="CheckIcon" svgClasses="w-5 h-5 text-primary" v-if="tempProduct.is_active"/>
|
||||
<FeatherIcon icon="XIcon" v-else svgClasses="w-5 h-5 text-danger"/>
|
||||
</ADescriptionsItem>
|
||||
|
||||
<ADescriptionsItem label="توضیح" span="3">
|
||||
{{tempProduct.body_html}}
|
||||
</ADescriptionsItem>
|
||||
</ADescriptions>
|
||||
</div>
|
||||
</AModal>
|
||||
|
||||
|
||||
<AModal :visible.sync="variantPopup" @cancel="()=>variantPopup = false" :zIndex="410001" width="80%"
|
||||
:footer="null">
|
||||
<div>
|
||||
<h2>تنوع محصولات</h2>
|
||||
<div>
|
||||
<ASkeleton active v-if="variantLoading"/>
|
||||
<a-list item-layout="horizontal" :data-source="tempVariant" v-else>
|
||||
<a-list-item slot="renderItem" slot-scope="item, index">
|
||||
<div class="">
|
||||
<ACard :title="item.title">
|
||||
<div class="flex" slot="extra">
|
||||
<div>
|
||||
<ASwitch v-model="item.is_active" @change="changeActiveVariant(item)"/>
|
||||
</div>
|
||||
<FeatherIcon @click="toEditVariant(item.id)" icon="EditIcon" class="cursor-pointer mx-4"
|
||||
svgClasses="h-5 w-5 text-primary"/>
|
||||
<div class="flex items-center">
|
||||
<APopconfirm
|
||||
|
||||
title="از حذف این تنوع مطمئنید؟"
|
||||
ok-text="بله"
|
||||
cancel-text="انصراف"
|
||||
style="z-index: 20000000">
|
||||
<a-icon slot="icon" type="question-circle-o" style="color: red"/>
|
||||
<div class="flex items-center">
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="h-5 w-5 text-danger" class="cursor-pointer"/>
|
||||
</div>
|
||||
</APopconfirm>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ADescriptions>
|
||||
<ADescriptionsItem label="rial_pay">
|
||||
{{item.rial_pay}}
|
||||
</ADescriptionsItem>
|
||||
<ADescriptionsItem label="grams">
|
||||
{{item.grams}}
|
||||
</ADescriptionsItem>
|
||||
<ADescriptionsItem label="color">
|
||||
{{item.color}}
|
||||
</ADescriptionsItem>
|
||||
<ADescriptionsItem label="price">
|
||||
{{item.price}}
|
||||
</ADescriptionsItem>
|
||||
<ADescriptionsItem label="percentage_pay">
|
||||
{{item.percentage_pay}}
|
||||
</ADescriptionsItem>
|
||||
</ADescriptions>
|
||||
</div>
|
||||
{{item.details}}
|
||||
|
||||
</ACard>
|
||||
</div>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</div>
|
||||
</div>
|
||||
</AModal>
|
||||
|
||||
|
||||
<ATable
|
||||
class="p-0 m-0"
|
||||
:pagination="false"
|
||||
:columns="cols" :data-source="data">
|
||||
<div slot="gold" slot-scope="data">
|
||||
<FeatherIcon icon="ArrowDownIcon" class="text-danger" svgClasses="w-4 h-4"/>
|
||||
{{data}}
|
||||
</div>
|
||||
<div slot="op" slot-scope="row, index">
|
||||
<ATooltip>
|
||||
<span slot="title">ویرایش</span>
|
||||
<FeatherIcon icon="EditIcon" @click="toEdit(index.id)" svgClasses="h-6 w-6 text-primary"
|
||||
class="cursor-pointer mx-1"/>
|
||||
</ATooltip>
|
||||
<ATooltip>
|
||||
<span slot="title">اطلاعات جامع</span>
|
||||
<FeatherIcon icon="AlertCircleIcon" @click="showProductModal(index)" svgClasses="h-6 w-6 text-warning"
|
||||
class="cursor-pointer mx-1"/>
|
||||
</ATooltip>
|
||||
<ATooltip>
|
||||
<span slot="title">تنوع ها</span>
|
||||
<FeatherIcon icon="ListIcon" @click="showVariantModal(index.id)" svgClasses="h-6 w-6 text-blue-400"
|
||||
class="cursor-pointer mx-1"/>
|
||||
</ATooltip>
|
||||
<ATooltip>
|
||||
<a-popconfirm placement="top" ok-text="بله" cancel-text="خیر" @confirm="confirmDelete(index.id)">
|
||||
<template slot="title">
|
||||
<p>آیا مطمئن به حذف رکورد مورد نظر هستید ؟</p>
|
||||
</template>
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="h-6 w-6 text-danger" class="cursor-pointer mx-1"/>
|
||||
</a-popconfirm>
|
||||
<span slot="title">حذف</span>
|
||||
</ATooltip>
|
||||
</div>
|
||||
</ATable>
|
||||
<vs-pagination
|
||||
class="mt-4"
|
||||
:total="getCount"
|
||||
:max="7"
|
||||
v-model="currentPage"/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {AgGridVue} from 'ag-grid-vue'
|
||||
import '@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
|
||||
// Store Module
|
||||
|
||||
// Cell Renderer
|
||||
import CellRendererLink from '../user/user-list/cell-renderer/CellRendererLink.vue'
|
||||
import CellRendererStatus from '../user/user-list/cell-renderer/CellRendererStatus.vue'
|
||||
import CellRendererVerified from '../user/user-list/cell-renderer/CellRendererVerified.vue'
|
||||
import CellRendererActions from '../user/user-list/cell-renderer/CellRendererActions.vue'
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
import * as TableCol from "@/table/product";
|
||||
import CustomerView from "@/views/apps/customer/CustomerView";
|
||||
import axios from "@/axios";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CustomerView,
|
||||
vSelect,
|
||||
// Cell Renderer
|
||||
FeatherIcon,
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Filter Options
|
||||
filterType: 'all',
|
||||
filterSts: 'all',
|
||||
tempVariant: [],
|
||||
tempProduct: undefined,
|
||||
detailsPopup: false,
|
||||
variantLoading: false,
|
||||
productLoading: false,
|
||||
variantPopup: false,
|
||||
typeOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'کیفی', value: 'active'},
|
||||
{label: 'عمده ای', value: 'deactivated'},
|
||||
{label: 'تک فروشی', value: 'blocked'}
|
||||
],
|
||||
statusOptions: [
|
||||
{label: 'همگی', value: 'all'},
|
||||
{label: 'فعال', value: 'active'},
|
||||
{label: 'غیر فعال', value: 'deactivated'}
|
||||
],
|
||||
// AgGrid
|
||||
gridApi: null,
|
||||
cols: null,
|
||||
gridOptions: {},
|
||||
defaultColDef: {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
suppressMenu: true
|
||||
},
|
||||
// Cell Renderer Components
|
||||
components: {
|
||||
CellRendererLink,
|
||||
CellRendererStatus,
|
||||
CellRendererVerified,
|
||||
CellRendererActions
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleFilter(obj) {
|
||||
this.setColumnFilter('role', obj.value)
|
||||
},
|
||||
statusFilter(obj) {
|
||||
this.setColumnFilter('status', obj.value)
|
||||
},
|
||||
isVerifiedFilter(obj) {
|
||||
const val = obj.value === 'all' ? 'all' : obj.value === 'yes' ? 'true' : 'false'
|
||||
this.setColumnFilter('is_verified', val)
|
||||
},
|
||||
departmentFilter(obj) {
|
||||
this.setColumnFilter('department', obj.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getCount() {
|
||||
return Math.ceil(this.count / 5);
|
||||
},
|
||||
data() {
|
||||
console.log("this.$store.state.product.rows ==> ", this.$store.state.product.rows);
|
||||
return this.$store.state.product.rows;
|
||||
},
|
||||
count() {
|
||||
return this.$store.state.product.count;
|
||||
},
|
||||
|
||||
currentPage: {
|
||||
get() {
|
||||
return this.$store.state.product.page;
|
||||
},
|
||||
set(val) {
|
||||
this.$store.commit('product/PAGE_SET', val);
|
||||
this.fetch();
|
||||
}
|
||||
},
|
||||
|
||||
searchQuery: {
|
||||
get() {
|
||||
return this.$store.state.product.searchQuery;
|
||||
},
|
||||
set(val) {
|
||||
this.$store.commit('product/SEARCH_QUERY_SET', val);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetch() {
|
||||
try {
|
||||
this.$refs.filterCard.visibleAnimation();
|
||||
return this.$store.dispatch('product/fetch');
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this.$refs.filterCard.removeRefreshAnimation();
|
||||
}
|
||||
},
|
||||
changeActiveVariant(item) {
|
||||
console.log("item.is_active ==> ", item.is_active);
|
||||
this.$store.dispatch('product/activeDeactive', item);
|
||||
},
|
||||
setColumnFilter(column, val) {
|
||||
const filter = this.gridApi.getFilterInstance(column)
|
||||
let modelObj = null
|
||||
|
||||
if (val !== 'all') {
|
||||
modelObj = {type: 'equals', filter: val}
|
||||
}
|
||||
|
||||
filter.setModel(modelObj)
|
||||
this.gridApi.onFilterChanged()
|
||||
},
|
||||
async showVariantModal(id) {
|
||||
this.tempVariant = [];
|
||||
this.variantLoading = true;
|
||||
this.variantPopup = true;
|
||||
const {data} = await axios.get(`product/${id}/variant`);
|
||||
this.variantLoading = false;
|
||||
this.tempVariant = data;
|
||||
},
|
||||
async showProductModal(data) {
|
||||
this.tempProduct = data;
|
||||
this.productLoading = false;
|
||||
this.detailsPopup = true;
|
||||
console.log("this.tempProduct ==> ", this.tempProduct);
|
||||
},
|
||||
toEdit(row) {
|
||||
this.$router.push({name: 'product-edit', params: {id: row}})
|
||||
},
|
||||
toEditVariant(row) {
|
||||
this.$router.push({name: 'variant-edit', params: {id: row}})
|
||||
},
|
||||
confirmDelete(id) {
|
||||
this.$store.dispatch('product/removeProduct', {id})
|
||||
},
|
||||
updateSearchQuery(val) {
|
||||
this.gridApi.setQuickFilter(val)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('product/fetch');
|
||||
},
|
||||
created() {
|
||||
this.cols = TableCol.default;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.ant-popover {
|
||||
z-index: 25000000;
|
||||
}
|
||||
</style>
|
||||
@@ -1,346 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: UserView.vue
|
||||
Description: User View page
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div id="page-user-view">
|
||||
|
||||
<div id="user-data">
|
||||
<a-form :form="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" @submit="handleSubmit">
|
||||
<ASpin :spinning="loading">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<vx-card title="انتخاب محصول" class="mb-base">
|
||||
<a-form-item label="محصول">
|
||||
<QuerySelect ref="qs" url="product" v-decorator="['product_id',{
|
||||
rules: [{ required: true, message: 'وارد کردن محصول الزامی است' }] },]"/>
|
||||
</a-form-item>
|
||||
</vx-card>
|
||||
<vx-card title="اطلاعات جامع" class="mb-base">
|
||||
<div class="flex">
|
||||
<div class="w-full md:w-1/2">
|
||||
<a-form-item label="عنوان">
|
||||
|
||||
<a-input
|
||||
v-decorator="['title',{ rules: [{ required: true, message: '' }] },]"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="بارکد">
|
||||
<a-input
|
||||
v-decorator="['barcode',{ rules: [{ required: true, message: '' }] },]"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="برند">
|
||||
<a-input
|
||||
v-decorator="['brand',{},]"/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div class="w-full md:w-1/2">
|
||||
<a-form-item label="وزن">
|
||||
|
||||
<a-input
|
||||
v-decorator="['grams',{ rules: [{ required: true, message: '' }] },]"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="رنگ">
|
||||
<ASelect
|
||||
v-decorator="['color',{ rules: [{ required: true, message: '' }] },]">
|
||||
<a-select-option v-for="(item,index) in colors" :value="index">
|
||||
{{item}}
|
||||
</a-select-option>
|
||||
</ASelect>
|
||||
</a-form-item>
|
||||
<a-form-item label="فعال">
|
||||
<ASwitch
|
||||
v-decorator="['is_active',{},]">
|
||||
</ASwitch>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
</ASpin>
|
||||
<vx-card title="قیمت" class="mb-8">
|
||||
<a-form-item label="مبلغ پرداختی">
|
||||
<AInputNumber
|
||||
v-decorator="['rial_pay',{ rules: [{ required: true, message: '' }] },]">
|
||||
</AInputNumber>
|
||||
</a-form-item>
|
||||
<a-form-item label="percentage_pay">
|
||||
<AInputNumber
|
||||
v-decorator="['percentage_pay',{ rules: [{ required: true, message: '' }] },]">
|
||||
</AInputNumber>
|
||||
</a-form-item>
|
||||
</vx-card>
|
||||
|
||||
<vx-card title="جزییات بیشتر" class="mb-8">
|
||||
<a-form-item label="توضیح مختصر">
|
||||
<ATextarea
|
||||
v-decorator="['details',{ },]">
|
||||
</ATextarea>
|
||||
</a-form-item>
|
||||
<a-form-item label="توضیحات کامل">
|
||||
<ATextarea
|
||||
v-decorator="['description',{ },]">
|
||||
</ATextarea>
|
||||
</a-form-item>
|
||||
</vx-card>
|
||||
|
||||
<!-- Permissions -->
|
||||
<vx-card class="mb-8">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="flex items-end px-3">
|
||||
<feather-icon svgClasses="w-6 h-6" icon="CameraIcon" class="mr-2"/>
|
||||
<span class="font-medium text-lg leading-none">تصاویر</span>
|
||||
</div>
|
||||
<vs-divider/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
<div class="w-full md:w-1/5 md:mr-8">
|
||||
<AUploadDragger
|
||||
name="image"
|
||||
:multiple="false"
|
||||
accept="image/*"
|
||||
:action="uploadURl"
|
||||
v-if="!thumb"
|
||||
@change="handleChangeThumb"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<a-icon type="inbox"/>
|
||||
</p>
|
||||
<p class="ant-upload-text">
|
||||
تصویر شاخص تنوع
|
||||
</p>
|
||||
<p class="ant-upload-hint">
|
||||
تصاویر باید پسوند png داشته باشند و حداکثر 1 مگابایت حجم داشته باشند.
|
||||
</p>
|
||||
</AUploadDragger>
|
||||
<div v-else class="relative">
|
||||
<VsImage :src="thumb.image" class="w-full"/>
|
||||
<div class="absolute cursor-pointer"
|
||||
@click="removeThumb"
|
||||
style="background-color: #f5222d;z-index: 1500;margin: auto;display: flex;padding: 5px;border-radius: 5px;">
|
||||
<FeatherIcon icon="TrashIcon" svgClasses="text-white"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full mt-6">
|
||||
<AUploadDragger
|
||||
name="image"
|
||||
:multiple="true"
|
||||
accept="image/*"
|
||||
:action="uploadURl"
|
||||
@change="handleChange"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<a-icon type="inbox"/>
|
||||
</p>
|
||||
<p class="ant-upload-text">
|
||||
تصاویر تنوع این محصول را در این قسمت بارگذاری کنید.
|
||||
</p>
|
||||
<p class="ant-upload-hint">
|
||||
تصاویر باید پسوند png داشته باشند و حداکثر 1 مگابایت حجم داشته باشند.
|
||||
</p>
|
||||
</AUploadDragger>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</vx-card>
|
||||
|
||||
<!-- /Information - Col 2 -->
|
||||
<div class="vx-col w-full flex mb-4">
|
||||
<vs-button icon-pack="feather" @click="handleSubmit" class="mr-4">
|
||||
<span v-if="!id"> ثبت تنوع</span>
|
||||
<span v-else>ویرایش تنوع</span>
|
||||
</vs-button>
|
||||
</div>
|
||||
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import QuerySelect from "@/views/components/extra-components/query-select/QuerySelect";
|
||||
import {baseURL} from "@/axios";
|
||||
import axios from "@/axios";
|
||||
import FeatherIcon from '@/components/FeatherIcon.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
QuerySelect,
|
||||
FeatherIcon
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
data: {},
|
||||
uploadURl: baseURL + 'config/image',
|
||||
textSearch: false,
|
||||
fetching: false,
|
||||
products: [],
|
||||
thumb: undefined,
|
||||
thumb_id: undefined,
|
||||
gallery: [],
|
||||
models: [
|
||||
'کونیک',
|
||||
'ساده'
|
||||
],
|
||||
colors: [
|
||||
'سفید',
|
||||
'زرد',
|
||||
'شکلاتی',
|
||||
'رزگلد',
|
||||
],
|
||||
formLayout: 'horizontal',
|
||||
form: this.$form.createForm(this, {name: 'coordinated'}),
|
||||
user_not_found: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
id() {
|
||||
return this.$router.history.current.params.id;
|
||||
},
|
||||
loading: {
|
||||
get() {
|
||||
return this.$store.state.variant.loading;
|
||||
},
|
||||
set(val) {
|
||||
this.$store.commit('variant/LOADING', val);
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeThumb(){
|
||||
this.thumb = undefined;
|
||||
this.thumb_id = undefined;
|
||||
},
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
let exp = values;
|
||||
exp.id = this.id;
|
||||
exp.image_id = _.map(this.gallery || [], 'id');
|
||||
exp.thumb_id = this.thumb_id;
|
||||
|
||||
try {
|
||||
this.$vs.loading();
|
||||
await this.$store.dispatch('variant/save', exp);
|
||||
this.$router.push({name: "product-list"});
|
||||
this.$ntSet();
|
||||
} catch (e) {
|
||||
this.$ntSetError();
|
||||
} finally {
|
||||
this.$vs.loading.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
async getData() {
|
||||
if (this.id) {
|
||||
try {
|
||||
this.loading = true;
|
||||
const {data} = await axios.get(`product/variant/${this.id}`);
|
||||
this.form.setFieldsValue(data)
|
||||
this.data = data;
|
||||
} catch (e) {
|
||||
console.log("e ==> ", e);
|
||||
this.$ntGetError()
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
handleChange(value) {
|
||||
let all = true;
|
||||
const items = _.map(value.fileList, 'response');
|
||||
for (let item of items) {
|
||||
if (!item) {
|
||||
all = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
this.gallery = items;
|
||||
}
|
||||
},
|
||||
handleChangeThumb(value) {
|
||||
if (value.fileList[0].response) {
|
||||
this.thumb = value.fileList[0].response;
|
||||
this.thumb_id = value.fileList[0].response.id;
|
||||
console.log("this.thumb_id ==> ", this.thumb_id);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
created() {
|
||||
this.getData();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#avatar-col {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
#page-user-view {
|
||||
table {
|
||||
td {
|
||||
vertical-align: top;
|
||||
min-width: 140px;
|
||||
padding-bottom: .8rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
&:not(.permissions-table) {
|
||||
td {
|
||||
@media screen and (max-width: 370px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #account-info-col-1 {
|
||||
// // flex-grow: 1;
|
||||
// width: 30rem !important;
|
||||
// @media screen and (min-width:1200px) {
|
||||
// & {
|
||||
// flex-grow: unset !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@media screen and (min-width: 1201px) and (max-width: 1211px),
|
||||
only screen and (min-width: 636px) and (max-width: 991px) {
|
||||
#account-info-col-1 {
|
||||
width: calc(100% - 12rem) !important;
|
||||
}
|
||||
|
||||
// #account-manage-buttons {
|
||||
// width: 12rem !important;
|
||||
// flex-direction: column;
|
||||
|
||||
// > button {
|
||||
// margin-right: 0 !important;
|
||||
// margin-bottom: 1rem;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,37 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="شماره های معرفی شده به سیستم">
|
||||
<XTable :model="getColTable">
|
||||
<div slot="score" slot-scope="{text, record}" @click="d(text,record)">
|
||||
<ATag v-for="(item,index) in text">
|
||||
{{item.value_c}}
|
||||
</ATag>
|
||||
</div>
|
||||
</XTable>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableSystem'
|
||||
|
||||
export default {
|
||||
name: "Introduction-system",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
getColTable: undefined,
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
d(text,record){
|
||||
console.log(text,record)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getColTable = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,11 +0,0 @@
|
||||
import XTbl,{Xtc} from '../../../components/x-table/index';
|
||||
|
||||
const tbl = new XTbl('/admin/present/table', 'لیست معرفی به سیستم');
|
||||
|
||||
tbl.add(new Xtc('presenter.mobile', 'معرفی کننده').filterNumber())
|
||||
tbl.add(new Xtc('mobile', 'معرفی شده و واردشده به سیستم').filterNumber())
|
||||
tbl.add(new Xtc('created_at', 'تاریخ ثبت ورودازلینک معرفی').filterDate())
|
||||
tbl.add(new Xtc('score', 'امتیازات کسرشده').filterNumber().renderSlot('score'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,254 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: Email.vue
|
||||
Description: Email Application (Inbox)
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div id="email-app" class="border border-solid d-theme-border-grey-light rounded relative overflow-hidden">
|
||||
|
||||
<vs-sidebar class="items-no-padding" parent="#email-app" :click-not-close="clickNotClose" :hidden-background="clickNotClose" v-model="isEmailSidebarActive">
|
||||
<email-sidebar :emailTags="emailTags" @closeSidebar="toggleEmailSidebar" :mailFilter="mailFilter" />
|
||||
</vs-sidebar>
|
||||
|
||||
<div :class="{'sidebar-spacer': clickNotClose}" class="no-scroll-content border border-solid d-theme-border-grey-light border-r-0 border-t-0 border-b-0">
|
||||
|
||||
<!-- SEARCH BAR -->
|
||||
<div class="flex border d-theme-dark-bg items-center">
|
||||
<feather-icon class="md:inline-flex lg:hidden ml-4 mr-4 cursor-pointer" icon="MenuIcon" @click.stop="toggleEmailSidebar(true)"/>
|
||||
<vs-input icon-no-border icon="icon-search" size="large" icon-pack="feather" placeholder="جستجو" v-model="searchQuery" class="vs-input-no-border vs-input-no-shdow-focus w-full" />
|
||||
</div>
|
||||
|
||||
<!-- EMAIL ACTION BAR -->
|
||||
<div class="email__actions flex items-center flex-wrap justify-between p-4 border border-r-0 border-l-0 border-solid d-theme-border-grey-light">
|
||||
<div class="flex items-center">
|
||||
<vs-checkbox v-model="selectAllCheckBox" icon-pack="feather" :icon="selectAllIcon" class="select-all-chexkbox ml-0">انتخاب همگی</vs-checkbox>
|
||||
</div>
|
||||
<div class="flex">
|
||||
|
||||
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer mt-3">
|
||||
|
||||
<feather-icon icon="TagIcon" class="cursor-pointer ml-5" svg-classes="h-6 w-6"></feather-icon>
|
||||
|
||||
<vs-dropdown-menu >
|
||||
<vs-dropdown-item v-for="(label, index) in emailTags" :key="index" @click="updateLabels(label.value)" class="whitespace-no-wrap">
|
||||
<div class="h-3 w-3 inline-block rounded-full mr-3" :class="'bg-' + label.color"></div>
|
||||
<span>{{ label.text }}</span>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
|
||||
<feather-icon v-if="mailFilter != 'trash'" icon="TrashIcon" class="cursor-pointer text-danger ml-5" svg-classes="h-6 w-6" @click="moveTo('trash')" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- EMAILS LIST -->
|
||||
<component :is="scrollbarTag" class="email-content-scroll-area" :settings="settings" ref="mailListPS" :key="$vs.rtl">
|
||||
<transition-group name="list-enter-up" class="email__mails" tag="ul" appear>
|
||||
<li class="cursor-pointer email__mail-item" v-for="(mail, index) in mails" :key="String(mailFilter) + String(mail.id)" @click="updateOpenMail(mail.id)" :style="{transitionDelay: (index * 0.1) + 's'}">
|
||||
<mail-item :mail="mail" :isSelected="isMailSelected(mail.id)" @addToSelected="addToSelectedMails" @removeSelected="removeSelectedMail" />
|
||||
</li>
|
||||
</transition-group>
|
||||
</component>
|
||||
</div>
|
||||
|
||||
<!-- EMAIL VIEW SIDEBAR -->
|
||||
<email-view
|
||||
:emailTags = "emailTags"
|
||||
:openMailId = "openMailId"
|
||||
:isSidebarActive = "isSidebarActive"
|
||||
:mailFilter = "mailFilter"
|
||||
@markUnread = "updateSingleMarkUnread"
|
||||
@removeMail = "removeOpenMail"
|
||||
@previousMail = "previousMail"
|
||||
@nextMail = "nextMail"
|
||||
@moveTo = "moveCurrentTo"
|
||||
@closeSidebar = "closeMailViewSidebar">
|
||||
</email-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EmailSidebar from './TicketSidebar.vue'
|
||||
import MailItem from './TicketItem.vue'
|
||||
import EmailView from './TicketView.vue'
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
import moduleEmail from '@/store/email/moduleEmail.js'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
openMailId : null,
|
||||
selectedMails : [],
|
||||
isSidebarActive : false,
|
||||
showThread : false,
|
||||
clickNotClose : true,
|
||||
isEmailSidebarActive : true,
|
||||
settings : {
|
||||
maxScrollbarLength : 60,
|
||||
wheelSpeed : 0.30
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isSidebarActive (value) {
|
||||
if (!value) this.showThread = false
|
||||
},
|
||||
mailFilter () {
|
||||
this.selectedMails = []
|
||||
|
||||
const scroll_el = this.$refs.mailListPS.$el || this.$refs.mailListPS
|
||||
scroll_el.scrollTop = 0
|
||||
|
||||
this.$store.commit('email/UPDATE_MAIL_FILTER', this.$route.params.filter)
|
||||
this.$store.dispatch('email/fetchEmails', { filter: this.$route.params.filter })
|
||||
this.toggleEmailSidebar()
|
||||
},
|
||||
windowWidth () {
|
||||
this.setSidebarWidth()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
mailFilter () {
|
||||
return this.$route.params.filter
|
||||
},
|
||||
emailTags () {
|
||||
return this.$store.state.email.mailTags
|
||||
},
|
||||
searchQuery: {
|
||||
get () {
|
||||
return this.$store.state.email.mailSearchQuery
|
||||
},
|
||||
set (val) {
|
||||
this.$store.dispatch('email/setEmailSearchQuery', val)
|
||||
}
|
||||
},
|
||||
selectAllCheckBox: {
|
||||
get () {
|
||||
return this.selectedMails.length
|
||||
},
|
||||
set (value) {
|
||||
value ? this.selectedMails = this.mails.map(mail => mail.id) : this.selectedMails = []
|
||||
}
|
||||
},
|
||||
mails () {
|
||||
return this.$store.getters['email/filteredMails']
|
||||
},
|
||||
selectAllIcon () {
|
||||
return this.selectedMails.length === this.mails.length ? 'icon-check' : 'icon-minus'
|
||||
},
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag },
|
||||
isMailSelected () {
|
||||
return (mailId) => this.selectedMails.indexOf(mailId) !== -1
|
||||
},
|
||||
windowWidth () {
|
||||
return this.$store.state.windowWidth
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateOpenMail (mailId) {
|
||||
this.openMailId = mailId
|
||||
this.isSidebarActive = true
|
||||
},
|
||||
addToSelectedMails (mailId) {
|
||||
if (this.selectedMails.indexOf(mailId) === -1) this.selectedMails.push(mailId)
|
||||
},
|
||||
removeSelectedMail (mailId) {
|
||||
const mailIndex = this.selectedMails.indexOf(mailId)
|
||||
if (mailIndex !== -1) this.selectedMails.splice(mailIndex, 1)
|
||||
},
|
||||
moveTo (to) {
|
||||
const payload = { emailIds: this.selectedMails, to }
|
||||
this.$store.dispatch('email/moveMailsTo', payload)
|
||||
.catch((error) => { console.error(error) })
|
||||
this.selectedMails = []
|
||||
},
|
||||
moveCurrentTo (to) {
|
||||
this.selectedMails = [this.openMailId]
|
||||
this.moveTo(to)
|
||||
},
|
||||
updateMarkUnread () {
|
||||
const payload = { emailIds: this.selectedMails, unreadFlag: true }
|
||||
this.$store.dispatch('email/setUnread', payload)
|
||||
this.selectedMails = []
|
||||
},
|
||||
removeOpenMail () {
|
||||
this.selectedMails = [this.openMailId]
|
||||
this.moveTo('trashed')
|
||||
this.isSidebarActive = false
|
||||
},
|
||||
toggleIsStarred () {
|
||||
const payload = { mailId: this.currentMail.id, value: !this.currentMail.isStarred }
|
||||
this.$store.dispatch('email/toggleIsMailStarred', payload)
|
||||
},
|
||||
nextMail () {
|
||||
const currentMailIndex = this.mails.findIndex((mail) => mail.id === this.openMailId)
|
||||
if (this.mails[currentMailIndex + 1]) this.openMailId = this.mails[currentMailIndex + 1].id
|
||||
},
|
||||
previousMail () {
|
||||
const currentMailIndex = this.mails.findIndex((mail) => mail.id === this.openMailId)
|
||||
if (this.mails[currentMailIndex - 1]) this.openMailId = this.mails[currentMailIndex - 1].id
|
||||
},
|
||||
updateSingleMarkUnread () {
|
||||
this.selectedMails = [this.openMailId]
|
||||
this.updateMarkUnread()
|
||||
this.isSidebarActive = false
|
||||
},
|
||||
updateLabels (label) {
|
||||
this.$store.dispatch('email/updateLabels', { mails: this.selectedMails, label })
|
||||
this.selectedMails = []
|
||||
},
|
||||
closeMailViewSidebar () {
|
||||
this.isSidebarActive = false
|
||||
},
|
||||
setSidebarWidth () {
|
||||
if (this.windowWidth < 992) {
|
||||
this.isEmailSidebarActive = this.clickNotClose = false
|
||||
} else {
|
||||
this.isEmailSidebarActive = this.clickNotClose = true
|
||||
}
|
||||
},
|
||||
toggleEmailSidebar (value = false) {
|
||||
if (!value) {
|
||||
this.closeMailViewSidebar()
|
||||
if (this.clickNotClose) {
|
||||
return
|
||||
}
|
||||
}
|
||||
this.isEmailSidebarActive = value
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MailItem,
|
||||
EmailSidebar,
|
||||
EmailView,
|
||||
VuePerfectScrollbar
|
||||
},
|
||||
created () {
|
||||
this.$store.registerModule('email', moduleEmail)
|
||||
this.setSidebarWidth()
|
||||
|
||||
this.$store.commit('email/UPDATE_MAIL_FILTER', this.$route.params.filter) // Update Mail Filter
|
||||
this.$store.dispatch('email/fetchEmails', { filter: this.$route.params.filter }) // Fetch Emails From API
|
||||
this.$store.dispatch('email/fetchMeta') // Fetch Unread Mails
|
||||
this.$store.dispatch('email/fetchTags') // Fetch Mail Tags
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$store.unregisterModule('email')
|
||||
},
|
||||
mounted () {
|
||||
this.$store.dispatch('email/setEmailSearchQuery', '')
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/apps/email.scss";
|
||||
</style>
|
||||
@@ -1,92 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: MailItem.vue
|
||||
Description: Mail Item - Displays mail item
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div class="mail__mail-item sm:px-4 px-2 py-6" :class="{'mail__opened-mail': !mail.unread}">
|
||||
|
||||
<!-- MAIL ROW 1 : META -->
|
||||
<div class="flex w-full">
|
||||
<vs-avatar class="sender__avatar flex-shrink-0 mr-3 border-2 border-solid border-white" :src="mail.img" size="40px"></vs-avatar>
|
||||
|
||||
<div class="flex w-full justify-between items-start">
|
||||
<div class="mail__details">
|
||||
<h5 class="mb-1" :class="{'font-semibold': mail.unread}">{{ mail.sender_name }}</h5>
|
||||
<span v-if="mail.subject">{{ mail.subject }}</span>
|
||||
<span v-else>(no subject)</span>
|
||||
</div>
|
||||
|
||||
<div class="mail-item__meta flex items-center">
|
||||
<div class="email__labels hidden sm:flex items-center">
|
||||
<div class="h-2 w-2 rounded-full mr-2" :class="'bg-' + labelColor(label)" v-for="(label, index) in mail.labels" :key="index"></div>
|
||||
</div>
|
||||
<span>20 فروردین</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /MAIL ROW 1 -->
|
||||
|
||||
<!-- MAIL ROW 2 : MSG & ACTIONS -->
|
||||
<div class="flex w-full">
|
||||
<div class="flex items-center ml-1">
|
||||
<vs-checkbox v-model="isSelectedMail" @click.stop class="vs-checkbox-small ml-0 mr-1"></vs-checkbox>
|
||||
<feather-icon icon="StarIcon" class="cursor-pointer" :svgClasses="[{'text-warning fill-current stroke-current': mail.isStarred}, 'w-5', 'h-5']" @click.stop="toggleIsStarred"></feather-icon>
|
||||
</div>
|
||||
<div class="mail__message truncate ml-3">
|
||||
<span>{{ mail.message | filter_tags }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /MAIL ROW 2 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mail: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
isSelected: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isSelectedMail: this.isSelected
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isSelected (value) {
|
||||
this.isSelectedMail = value
|
||||
},
|
||||
isSelectedMail (val) {
|
||||
val ? this.$emit('addToSelected', this.mail.id) : this.$emit('removeSelected', this.mail.id)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
labelColor () {
|
||||
return (label) => {
|
||||
const tags = this.$store.state.email.mailTags
|
||||
return tags.find((tag) => {
|
||||
return tag.value === label
|
||||
}).color
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleIsStarred () {
|
||||
const payload = { mailId: this.mail.id, value: !this.mail.isStarred }
|
||||
this.$store.dispatch('email/toggleIsMailStarred', payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: EmailMailCard.vue
|
||||
Description: Email Application - Single Email Card View
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template functional>
|
||||
<vx-card class="px-4" :class="data.staticClass">
|
||||
<!-- MAIL HEAD -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full border-b border-l-0 border-r-0 border-t-0 d-theme-border-grey-light border-solid flex justify-between flex items-center">
|
||||
<!-- Sender Details -->
|
||||
<div class="flex items-center">
|
||||
<div>
|
||||
<vs-avatar class="sender__avatar--single flex-shrink-0 mr-3 border-2 border-solid border-white" :src="props.mailContent.img" size="65px" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<h5 class="mb-1">{{ props.mailContent.sender_name }}</h5>
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm">09128081392</span>
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="inline-flex cursor-pointer">
|
||||
<feather-icon icon="ChevronDownIcon" class="w-3 h-3" />
|
||||
<vs-dropdown-menu style="z-index: 40001">
|
||||
<div class="p-2">
|
||||
<p class="text-sm mb-1">از : <span class="font-semibold"> {{ props.mailContent.sender_name }} </span></p>
|
||||
<p class="text-sm mb-1">به : <span class="font-semibold"> محسن الیادرانی</span></p>
|
||||
<p class="text-sm mb-1">تاریخ : <span class="font-semibold">29 فروردین 1399 10:40 </span></p>
|
||||
<p class="text-sm mb-1" v-if="props.mailContent.cc.length">cc: <span class="font-semibold"> {{ props.mailContent.cc | csv }} </span></p>
|
||||
</div>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /Sender Details -->
|
||||
|
||||
<!-- Mail Time & Date -->
|
||||
<div class="flex flex-col justify-end">
|
||||
<span class="text-right">{{ props.mailContent.time | time }}</span>
|
||||
<div class="flex justify-end mt-2">
|
||||
<span class="text-right">29 فروردین</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /Mail Time & Date -->
|
||||
</div>
|
||||
|
||||
<!-- MAIL CONTENT -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="mail__content break-words mt-8 mb-4" v-html="props.mailContent.message"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MAIL ATTACHMENTS -->
|
||||
<div class="vx-row" v-if="props.mailContent.attachments.length">
|
||||
<div class="vx-col w-full border-b border-l-0 border-r-0 border-t-0 d-theme-border-grey-light border-solid mb-6 flex">
|
||||
<feather-icon icon="PaperclipIcon" class="mr-2" />
|
||||
<span class="block py-4">فایل ها</span>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="mail__attachment" v-for="(attachment, index) in props.mailContent.attachments" :key="index">
|
||||
<vs-chip color="primary" class="px-4 py-2 mr-3">{{ attachment }}</vs-chip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mailContent: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,173 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: EmailSidebar.vue
|
||||
Description: Email Application Sidebar(Filter) (Inbox)
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div class="email__email-sidebar h-full">
|
||||
<div class="m-6 clearfix">
|
||||
<vs-button class="bg-primary-gradient w-full" icon-pack="feather" icon="icon-edit" @click="activePrompt = true">ارسال تیکت جدید</vs-button>
|
||||
</div>
|
||||
|
||||
<!-- compose email -->
|
||||
<vs-prompt
|
||||
class="email-compose"
|
||||
title="New Message"
|
||||
accept-text= "Send"
|
||||
@cancel="clearFields"
|
||||
@accept="sendMail"
|
||||
@close="clearFields"
|
||||
:is-valid="validateForm"
|
||||
:active.sync="activePrompt">
|
||||
<component :is="scrollbarTag" class="scroll-area p-4" :settings="settings" :key="$vs.rtl">
|
||||
<form @submit.prevent>
|
||||
<vs-input v-validate="'required|email'" name="mailTo" label-placeholder="To" v-model="mailTo" class="w-full mb-6" :danger="!validateForm && mailTo != ''" val-icon-danger="clear" :success="validateForm" val-icon-success="done" :color="validateForm ? 'success' : 'danger'" />
|
||||
<vs-input name="mailSubject" label-placeholder="Subject" v-model="mailSubject" class="w-full mb-6" />
|
||||
<vs-input name="mailCC" label-placeholder="CC" v-model="mailCC" class="w-full mb-6" />
|
||||
<vs-input name="mailBCC" label-placeholder="BCC" v-model="mailBCC" class="w-full mb-6" />
|
||||
<quill-editor v-model="mailMessage" :options="editorOption" />
|
||||
<vs-upload multiple text="Attachments" :show-upload-button="false" class="compose-mail-attachment" />
|
||||
</form>
|
||||
</component>
|
||||
</vs-prompt>
|
||||
|
||||
<component :is="scrollbarTag" class="email-filter-scroll-area" :settings="settings" :key="$vs.rtl">
|
||||
<div class="px-6 pb-2 flex flex-col">
|
||||
|
||||
<!-- inbox -->
|
||||
<router-link tag="span" :to="`${baseUrl}/inbox`" class="flex justify-between items-center cursor-pointer" :class="{'text-primary': mailFilter == 'inbox'}">
|
||||
<div class="flex items-center mb-2">
|
||||
<feather-icon icon="MailIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'inbox'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">صندوق ورودی</span>
|
||||
</div>
|
||||
<template v-if="emailMeta.unreadMails">
|
||||
<vs-chip class="number" color="primary" v-if="emailMeta.unreadMails.folder.inbox.length > 0">{{ emailMeta.unreadMails.folder.inbox.length }}</vs-chip>
|
||||
</template>
|
||||
</router-link>
|
||||
|
||||
<!-- sent -->
|
||||
<router-link tag="span" :to="`${baseUrl}/sent`" class="flex items-center mt-4 mb-2 cursor-pointer" :class="{'text-primary': mailFilter == 'sent'}">
|
||||
<feather-icon icon="SendIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'sent'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">ارسال شده ها</span>
|
||||
</router-link>
|
||||
|
||||
<!-- draft -->
|
||||
<router-link tag="span" :to="`${baseUrl}/draft`" class="flex justify-between items-center mt-4 cursor-pointer" :class="{'text-primary': mailFilter == 'draft'}">
|
||||
<div class="flex items-center mb-2">
|
||||
<feather-icon icon="Edit2Icon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'draft'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">پیش نویس ها</span>
|
||||
</div>
|
||||
<template v-if="emailMeta.draftMails">
|
||||
<vs-chip class="number" color="warning" v-if="emailMeta.draftMails.length > 0">{{ emailMeta.draftMails.length }}</vs-chip>
|
||||
</template>
|
||||
</router-link>
|
||||
|
||||
<!-- starred -->
|
||||
<router-link tag="span" :to="`${baseUrl}/starred`" class="flex items-center mt-4 mb-2 cursor-pointer" :class="{'text-primary': mailFilter == 'starred'}">
|
||||
<feather-icon icon="StarIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'starred'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">مهم</span>
|
||||
</router-link>
|
||||
|
||||
|
||||
<!-- trash -->
|
||||
<router-link tag="span" :to="`${baseUrl}/trash`" class="flex items-center mt-4 mb-2 cursor-pointer" :class="{'text-primary': mailFilter == 'trash'}">
|
||||
<feather-icon icon="TrashIcon" :svgClasses="[{'text-primary stroke-current': mailFilter == 'trash'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">آرشیو شده</span>
|
||||
</router-link>
|
||||
</div>
|
||||
<vs-divider></vs-divider>
|
||||
<div class="email__labels px-6 py-4">
|
||||
<h5 class="mb-8">برچسب ها</h5>
|
||||
<div class="email__lables-list">
|
||||
<router-link tag="span" class="email__label flex items-center mb-4 cursor-pointer" v-for="(tag, index) in emailTags" :key="index" :to="`${baseUrl}/${tag.value}`">
|
||||
<div class="ml-1 h-3 w-3 rounded-full mr-4" :class="'border-2 border-solid border-' + tag.color"></div>
|
||||
<span class="text-lg" :class="{'text-primary': mailFilter == tag.value}">{{ tag.text }}</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import { quillEditor } from 'vue-quill-editor'
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
emailTags: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
mailFilter: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activePrompt: false,
|
||||
mailTo: '',
|
||||
mailSubject: '',
|
||||
mailCC: '',
|
||||
mailBCC: '',
|
||||
mailMessage: '',
|
||||
editorOption: {
|
||||
modules: {
|
||||
toolbar: [
|
||||
['bold', 'italic', 'underline', 'strike', 'link', 'blockquote', 'code-block'],
|
||||
[{ 'header': 1 }, { 'header': 2 }],
|
||||
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
[{ 'font': [] }]
|
||||
]
|
||||
},
|
||||
placeholder: 'Message'
|
||||
},
|
||||
settings: {
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed: 0.30
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
validateForm () {
|
||||
return !this.errors.any() && this.mailTo !== ''
|
||||
},
|
||||
baseUrl () {
|
||||
const path = this.$route.path
|
||||
return path.slice(0, path.lastIndexOf('/'))
|
||||
},
|
||||
emailMeta () {
|
||||
return this.$store.state.email.meta
|
||||
},
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag }
|
||||
},
|
||||
methods: {
|
||||
clearFields () {
|
||||
this.$nextTick(() => {
|
||||
this.mailTo = ''
|
||||
this.mailSubject = ''
|
||||
this.mailCC = ''
|
||||
this.mailBCC = ''
|
||||
this.mailMessage = ''
|
||||
})
|
||||
},
|
||||
sendMail () {
|
||||
this.clearFields()
|
||||
}
|
||||
},
|
||||
components: {
|
||||
quillEditor,
|
||||
VuePerfectScrollbar
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: EmailView.vue
|
||||
Description: Email Application - Single Email View (Inbox)
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<vs-sidebar click-not-close parent="#email-app" :hidden-background="true" class="full-vs-sidebar email-view-sidebar items-no-padding" v-model="isSidebarActive" position-right>
|
||||
<div class="mail-sidebar-content px-0 sm:pb-6 h-full" v-if="currentMail">
|
||||
<div class="flex flex-wrap items-center email-header justify-between md:px-8 px-6 sm:pb-2 sm: pt-6 d-theme-dark-bg">
|
||||
<div class="flex mb-4">
|
||||
<div class="flex items-center">
|
||||
<feather-icon :icon="$vs.rtl ? 'ArrowRightIcon' : 'ArrowLeftIcon'" @click="$emit('closeSidebar')" class="cursor-pointer mr-4" svg-classes="w-6 h-6"></feather-icon>
|
||||
<h4 v-if="currentMail.subject">{{ currentMail.subject }}</h4>
|
||||
<h4 v-else>(no subject)</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-10 mb-4 mt-1">
|
||||
<div class="email__actions--single flex items-baseline">
|
||||
|
||||
<feather-icon icon="StarIcon" class="cursor-pointer" :svgClasses="[{'text-warning stroke-current stroke-current': currentMail.isStarred}, 'h-6 w-6']" @click="toggleIsStarred" />
|
||||
|
||||
|
||||
<!-- ADD LABEL DROPDOWN -->
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer">
|
||||
<feather-icon icon="TagIcon" svg-classes="h-6 w-6" class="cursor-pointer ml-4"></feather-icon>
|
||||
<vs-dropdown-menu style="z-index: 40001">
|
||||
<vs-dropdown-item v-for="(label, index) in emailTags" :key="index" @click.stop>
|
||||
<vs-checkbox :vs-value="label.value" v-model="currentMailLabels">{{ label.text }}</vs-checkbox>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
|
||||
<feather-icon :icon="$vs.rtl ? 'ChevronsRightIcon' : 'ChevronsLeftIcon'" svg-classes="h-6 w-6" class="cursor-pointer ml-4 hidden sm:inline-flex" @click="$emit('previousMail')" />
|
||||
<feather-icon :icon="$vs.rtl ? 'ChevronsLeftIcon' : 'ChevronsRightIcon'" svg-classes="h-6 w-6" class="cursor-pointer ml-4 hidden sm:inline-flex" @click="$emit('nextMail')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<component :is="scrollbarTag" class="scroll-area-mail-content md:px-8 md:pb-8 pt-4 px-6 pb-6" :settings="settings" :key="$vs.rtl">
|
||||
<!-- LABEL ROW -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<div class="email__labels--single flex ml-10 items-center mt-2">
|
||||
<transition-group name="list" tag="div" class="flex">
|
||||
<div v-for="label in currentMail.labels" :key="label" class="open-mail-label flex items-center mr-4">
|
||||
<div class="h-3 w-3 rounded-full mr-1" :class="'bg-' + labelColor(label)"></div>
|
||||
<span class="text-sm">سفارش</span>
|
||||
</div>
|
||||
</transition-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /LABEL ROW -->
|
||||
<br>
|
||||
|
||||
<div class="vx-row mb-4" v-if="currentMail.replies.length && !showThread">
|
||||
<div class="vx-col w-full">
|
||||
<span class="text-primary font-medium ml-10 cursor-pointer" @click="showThread = true">{{ currentMail.replies.length }} تیکت های قبل تر</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isSidebarActive">
|
||||
|
||||
<!-- ALL MESSAGES - THREAD -->
|
||||
<div class="vx-row" v-for="threadMail in currentMail.replies.slice().reverse()" :key="threadMail.id" v-if="showThread">
|
||||
<div class="vx-col w-full">
|
||||
<email-mail-card :mailContent="threadMail" class="mb-10" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LATEST MESSAGE -->
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<email-mail-card :mailContent="currentMail" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-row" style="margin-top: 2.2rem">
|
||||
<div class="vx-col w-full">
|
||||
<vx-card>
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full flex justify-between">
|
||||
<span class="text-lg"><span class="text-primary font-semibold cursor-pointer">پاسخ </span> یا <span class="text-primary font-semibold cursor-pointer">ارسال</span> جواب به این تیکت</span>
|
||||
<feather-icon icon="PaperclipIcon"></feather-icon>
|
||||
</div>
|
||||
</div>
|
||||
</vx-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</component>
|
||||
</div>
|
||||
</vs-sidebar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
import EmailMailCard from './TicketMailCard.vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
emailTags: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
openMailId: {
|
||||
required: true,
|
||||
validator: prop => typeof prop === 'number' || prop === null
|
||||
},
|
||||
isSidebarActive: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
mailFilter: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showThread: false,
|
||||
settings: {
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed: 0.50
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isSidebarActive (value) {
|
||||
if (!value) {
|
||||
this.$emit('closeSidebar')
|
||||
setTimeout(() => {
|
||||
this.showThread = false
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentMail () {
|
||||
return this.$store.getters['email/getMail'](this.openMailId)
|
||||
},
|
||||
labelColor () {
|
||||
return (label) => {
|
||||
const tags = this.$store.state.email.mailTags
|
||||
return tags.find((tag) => {
|
||||
return tag.value === label
|
||||
}).color
|
||||
}
|
||||
},
|
||||
currentMailLabels: {
|
||||
get () {
|
||||
return this.currentMail.labels
|
||||
},
|
||||
set (value) {
|
||||
if (Array.isArray(value)) {
|
||||
const payload = { mailId: this.openMailId, labels: value }
|
||||
this.$store.dispatch('email/setLabels', payload)
|
||||
}
|
||||
}
|
||||
},
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag }
|
||||
},
|
||||
methods: {
|
||||
toggleIsStarred () {
|
||||
const payload = { mailId: this.openMailId, value: !this.currentMail.isStarred }
|
||||
this.$store.dispatch('email/toggleIsMailStarred', payload)
|
||||
},
|
||||
moveTo (to) {
|
||||
this.$emit('closeSidebar')
|
||||
this.$emit('moveTo', to)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
VuePerfectScrollbar,
|
||||
EmailMailCard
|
||||
},
|
||||
updated () {
|
||||
if (!this.currentMail) return
|
||||
if (this.currentMail.unread && this.isSidebarActive) this.$store.dispatch('email/setUnread', { emailIds: [this.openMailId], unread: false })
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: Todo.vue
|
||||
Description: Todo Application to keep you ahead of time
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div id="todo-app" class="border border-solid d-theme-border-grey-light rounded relative overflow-hidden">
|
||||
<vs-sidebar class="items-no-padding" parent="#todo-app" :click-not-close="clickNotClose" :hidden-background="clickNotClose" v-model="isSidebarActive">
|
||||
|
||||
<todo-add-new />
|
||||
|
||||
<component :is="scrollbarTag" class="todo-scroll-area" :settings="settings" :key="$vs.rtl">
|
||||
<todo-filters @closeSidebar="toggleTodoSidebar"></todo-filters>
|
||||
</component>
|
||||
|
||||
</vs-sidebar>
|
||||
<div :class="{'sidebar-spacer': clickNotClose}" class="no-scroll-content border border-r-0 border-b-0 border-t-0 border-solid d-theme-border-grey-light no-scroll-content">
|
||||
|
||||
<div class="flex d-theme-dark-bg items-center border border-l-0 border-r-0 border-t-0 border-solid d-theme-border-grey-light">
|
||||
|
||||
<!-- TOGGLE SIDEBAR BUTTON -->
|
||||
<feather-icon class="md:inline-flex lg:hidden ml-4 mr-4 cursor-pointer" icon="MenuIcon" @click.stop="toggleTodoSidebar(true)" />
|
||||
|
||||
<!-- SEARCH BAR -->
|
||||
<vs-input icon-no-border size="large" icon-pack="feather" icon="icon-search" placeholder="Search..." v-model="searchQuery" class="vs-input-no-border vs-input-no-shdow-focus w-full" />
|
||||
</div>
|
||||
|
||||
<!-- TODO LIST -->
|
||||
<component :is="scrollbarTag" class="todo-content-scroll-area" :settings="settings" ref="taskListPS" :key="$vs.rtl">
|
||||
|
||||
<transition-group class="todo-list" name="list-enter-up" tag="ul" appear>
|
||||
<li
|
||||
class="cursor-pointer todo_todo-item"
|
||||
v-for="(task, index) in taskList"
|
||||
:key="String(currFilter) + String(task.id)"
|
||||
:style="[{transitionDelay: (index * 0.1) + 's'}]">
|
||||
|
||||
<todo-task :taskId="task.id" @showDisplayPrompt="showDisplayPrompt($event)" :key="String(task.title) + String(task.desc)" />
|
||||
<!--
|
||||
Note: Remove "todo-task" component's key just concat lastUpdated field in li key list.
|
||||
e.g. <li class="..." v-for="..." :key="String(currFilter) + String(task.id) + String(task.lastUpdated)" .. >
|
||||
-->
|
||||
</li>
|
||||
</transition-group>
|
||||
</component>
|
||||
<!-- /TODO LIST -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- EDIT TODO DIALOG -->
|
||||
<todo-edit :displayPrompt="displayPrompt" :taskId="taskIdToEdit" @hideDisplayPrompt="hidePrompt" v-if="displayPrompt"></todo-edit>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moduleTodo from '@/store/todo/moduleTodo.js'
|
||||
import TodoAddNew from './TodoAddNew.vue'
|
||||
import TodoTask from './TodoTask.vue'
|
||||
import TodoFilters from './TodoFilters.vue'
|
||||
import TodoEdit from './TodoEdit.vue'
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
currFilter : '',
|
||||
clickNotClose : true,
|
||||
displayPrompt : false,
|
||||
taskIdToEdit : 0,
|
||||
isSidebarActive : true,
|
||||
settings : {
|
||||
maxScrollbarLength : 60,
|
||||
wheelSpeed : 0.30
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
todoFilter () {
|
||||
const scroll_el = this.$refs.taskListPS.$el || this.$refs.taskListPS
|
||||
scroll_el.scrollTop = 0
|
||||
|
||||
this.toggleTodoSidebar()
|
||||
|
||||
// Fetch Tasks
|
||||
const filter = this.$route.params.filter
|
||||
this.$store.dispatch('todo/fetchTasks', { filter })
|
||||
this.$store.commit('todo/UPDATE_TODO_FILTER', filter)
|
||||
},
|
||||
windowWidth () {
|
||||
this.setSidebarWidth()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
todo () { return this.$store.state.todo.todoArray },
|
||||
todoFilter () { return this.$route.params.filter },
|
||||
taskList () { return this.$store.getters['todo/queriedTasks'] },
|
||||
searchQuery: {
|
||||
get () { return this.$store.state.todo.todoSearchQuery },
|
||||
set (val) { this.$store.dispatch('todo/setTodoSearchQuery', val) }
|
||||
},
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag },
|
||||
windowWidth () { return this.$store.state.windowWidth }
|
||||
},
|
||||
methods: {
|
||||
showDisplayPrompt (itemId) {
|
||||
this.taskIdToEdit = itemId
|
||||
this.displayPrompt = true
|
||||
},
|
||||
hidePrompt () {
|
||||
this.displayPrompt = false
|
||||
},
|
||||
setSidebarWidth () {
|
||||
if (this.windowWidth < 992) {
|
||||
this.isSidebarActive = this.clickNotClose = false
|
||||
} else {
|
||||
this.isSidebarActive = this.clickNotClose = true
|
||||
}
|
||||
},
|
||||
toggleTodoSidebar (value = false) {
|
||||
if (!value && this.clickNotClose) return
|
||||
this.isSidebarActive = value
|
||||
}
|
||||
},
|
||||
components: {
|
||||
TodoAddNew,
|
||||
TodoTask,
|
||||
TodoFilters,
|
||||
TodoEdit,
|
||||
VuePerfectScrollbar
|
||||
},
|
||||
created () {
|
||||
this.$store.registerModule('todo', moduleTodo)
|
||||
this.setSidebarWidth()
|
||||
|
||||
const filter = this.$route.params.filter
|
||||
|
||||
// Fetch Tasks
|
||||
this.$store.dispatch('todo/fetchTasks', { filter })
|
||||
this.$store.commit('todo/UPDATE_TODO_FILTER', filter)
|
||||
|
||||
// Fetch Tags
|
||||
this.$store.dispatch('todo/fetchTags')
|
||||
},
|
||||
beforeUpdate () {
|
||||
this.currFilter = this.$route.params.filter
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$store.unregisterModule('todo')
|
||||
},
|
||||
mounted () {
|
||||
this.$store.dispatch('todo/setTodoSearchQuery', '')
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/apps/todo.scss";
|
||||
</style>
|
||||
@@ -1,104 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: TodoAddNew.vue
|
||||
Description: Add new-x-table todo component
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div class="px-6 pb-2 pt-6">
|
||||
<vs-button @click="activePrompt = true" class="w-full">Add Task</vs-button>
|
||||
<vs-prompt
|
||||
title="Add Task"
|
||||
accept-text= "Add Task"
|
||||
button-cancel = "border"
|
||||
@cancel="clearFields"
|
||||
@accept="addTodo"
|
||||
@close="clearFields"
|
||||
:is-valid="validateForm"
|
||||
:active.sync="activePrompt">
|
||||
<div>
|
||||
<form>
|
||||
<div class="vx-row">
|
||||
|
||||
<div class="vx-col ml-auto flex">
|
||||
<feather-icon icon="InfoIcon" class="cursor-pointer" :svgClasses="[{'text-success stroke-current': taskLocal.isImportant}, 'w-5', 'h-5 mr-4']" @click.prevent="taskLocal.isImportant = !taskLocal.isImportant"></feather-icon>
|
||||
|
||||
<feather-icon icon="StarIcon" class="cursor-pointer" :svgClasses="[{'text-warning stroke-current': taskLocal.isStarred}, 'w-5', 'h-5 mr-4']" @click.prevent="taskLocal.isStarred = !taskLocal.isStarred"></feather-icon>
|
||||
|
||||
<vs-dropdown class="cursor-pointer flex" vs-custom-content>
|
||||
|
||||
<feather-icon icon="TagIcon" svgClasses="h-5 w-5" @click.prevent></feather-icon>
|
||||
<!-- <vs-button radius color="success" type="flat" iconPack="feather" icon="icon-tag" @click.prevent></vs-button> -->
|
||||
|
||||
<vs-dropdown-menu style="z-index: 200001">
|
||||
<vs-dropdown-item @click.stop v-for="(tag, index) in taskTags" :key="index">
|
||||
<vs-checkbox :vs-value="tag.value" v-model="taskLocal.tags">{{ tag.text }}</vs-checkbox>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<vs-input v-validate="'required'" name="title" class="w-full mb-4 mt-5" placeholder="Title" v-model="taskLocal.title" :color="validateForm ? 'success' : 'danger'" />
|
||||
<vs-textarea rows="5" label="Add description" v-model="taskLocal.desc" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</vs-prompt>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
activePrompt: false,
|
||||
|
||||
taskLocal: {
|
||||
title: '',
|
||||
desc: '',
|
||||
isCompleted: false,
|
||||
isImportant: false,
|
||||
isStarred: false,
|
||||
tags: []
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
taskTags () {
|
||||
return this.$store.state.todo.taskTags
|
||||
},
|
||||
validateForm () {
|
||||
return !this.errors.any() && this.taskLocal.title !== ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clearFields () {
|
||||
Object.assign(this.taskLocal, {
|
||||
title: '',
|
||||
desc: '',
|
||||
isCompleted: false,
|
||||
isImportant: false,
|
||||
isStarred: false,
|
||||
tags: []
|
||||
})
|
||||
},
|
||||
addTodo () {
|
||||
this.$validator.validateAll().then(result => {
|
||||
if (result) {
|
||||
this.$store.dispatch('todo/addTask', Object.assign({}, this.taskLocal))
|
||||
this.clearFields()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,117 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: TodoEdit.vue
|
||||
Description: Edit todo component
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<vs-prompt
|
||||
title="Edit Task"
|
||||
accept-text= "Submit"
|
||||
cancel-text = "Remove"
|
||||
button-cancel = "border"
|
||||
@cancel="removeTodo"
|
||||
@accept="submitTodo"
|
||||
@close="init"
|
||||
:is-valid="validateForm"
|
||||
:active.sync="activePrompt">
|
||||
<div>
|
||||
<form>
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-1/6 self-center">
|
||||
<vs-checkbox v-model="taskLocal.isCompleted" class="w-8"></vs-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="vx-col ml-auto flex">
|
||||
<feather-icon
|
||||
icon="InfoIcon"
|
||||
class="cursor-pointer"
|
||||
:svgClasses="[{'text-success stroke-current': taskLocal.isImportant}, 'w-5', 'h-5 mr-4']"
|
||||
@click.prevent="taskLocal.isImportant = !taskLocal.isImportant" />
|
||||
|
||||
<feather-icon
|
||||
icon="StarIcon"
|
||||
class="cursor-pointer"
|
||||
:svgClasses="[{'text-warning stroke-current': taskLocal.isStarred}, 'w-5', 'h-5 mr-4']"
|
||||
@click.prevent="taskLocal.isStarred = !taskLocal.isStarred" />
|
||||
|
||||
<vs-dropdown class="cursor-pointer flex" vs-custom-content>
|
||||
|
||||
<feather-icon icon="TagIcon" svgClasses="h-5 w-5" />
|
||||
|
||||
<vs-dropdown-menu style="z-index: 200001">
|
||||
<vs-dropdown-item @click.stop v-for="(tag, index) in taskTags" :key="index">
|
||||
<vs-checkbox :vs-value="tag.value" v-model="taskLocal.tags">{{ tag.text }}</vs-checkbox>
|
||||
</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full">
|
||||
<vs-input v-validate="'required'" name="title" class="w-full mb-4 mt-5" placeholder="Title" v-model="taskLocal.title" />
|
||||
<vs-textarea rows="5" label="Add description" v-model="taskLocal.desc" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</vs-prompt>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
displayPrompt: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
taskId: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
taskLocal: Object.assign({}, this.$store.getters['todo/getTask'](this.taskId))
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activePrompt: {
|
||||
get () {
|
||||
return this.displayPrompt
|
||||
},
|
||||
set (value) {
|
||||
this.$emit('hideDisplayPrompt', value)
|
||||
}
|
||||
},
|
||||
taskTags () {
|
||||
return this.$store.state.todo.taskTags
|
||||
},
|
||||
validateForm () {
|
||||
return !this.errors.any() && this.taskLocal.title !== ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeTodo () {
|
||||
this.$store.dispatch('todo/updateTask', Object.assign({}, this.taskLocal, {isTrashed: true}))
|
||||
.then(() => {
|
||||
// Fetch Tasks
|
||||
this.$store.dispatch('todo/fetchTasks', { filter: this.$route.params.filter })
|
||||
})
|
||||
.catch((error) => { console.error(error) })
|
||||
},
|
||||
init () {
|
||||
this.taskLocal = Object.assign({}, this.$store.getters['todo/getTask'](this.taskId))
|
||||
},
|
||||
submitTodo () {
|
||||
this.$store.dispatch('todo/updateTask', this.taskLocal)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,78 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: TodoAddNew.vue
|
||||
Description: Add new-x-table todo component
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div class="todo__filters-container">
|
||||
|
||||
<!-- all -->
|
||||
<div class="px-6 py-4">
|
||||
<router-link tag="span" class="flex cursor-pointer" :class="{'text-primary': todoFilter == 'all'}" :to="`${baseUrl}/all`">
|
||||
<feather-icon icon="LayersIcon" :svgClasses="[{'text-primary stroke-current': todoFilter == 'all'}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">All</span>
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<vs-divider></vs-divider>
|
||||
|
||||
<!-- starred -->
|
||||
<div class="px-6 py-4">
|
||||
<h5>Filters</h5>
|
||||
|
||||
<template v-for="filter in todoFilters">
|
||||
<router-link tag="span" class="flex mt-6 cursor-pointer" :class="{'text-primary': todoFilter == filter.filter}" :to="`${baseUrl}/${filter.filter}`" :key="filter.filter">
|
||||
<feather-icon :icon="filter.icon" :svgClasses="[{'text-primary stroke-current': todoFilter == filter.filter}, 'h-6 w-6']"></feather-icon>
|
||||
<span class="text-lg ml-3">{{ filter.filterName }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
|
||||
<vs-divider></vs-divider>
|
||||
|
||||
<div class="px-6 py-4">
|
||||
<h5>Labels</h5>
|
||||
<div class="todo__lables-list">
|
||||
<router-link tag="span" class="todo__label flex items-center mt-6 cursor-pointer" v-for="(tag, index) in taskTags" :key="index" :to="`${baseUrl}/${tag.value}`">
|
||||
<div class="ml-1 h-3 w-3 rounded-full mr-4" :class="'border-2 border-solid border-' + tag.color" />
|
||||
<span class="text-lg" :class="{'text-primary': todoFilter == tag.value}">{{ tag.text }}</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default{
|
||||
data () {
|
||||
return {
|
||||
todoFilters: [
|
||||
{ filterName: 'Starred', filter: 'starred', icon: 'StarIcon' },
|
||||
{ filterName: 'Important', filter: 'important', icon: 'InfoIcon' },
|
||||
{ filterName: 'Completed', filter: 'completed', icon: 'CheckIcon' },
|
||||
{ filterName: 'Trashed', filter: 'trashed', icon: 'TrashIcon' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
taskTags () {
|
||||
return this.$store.state.todo.taskTags
|
||||
},
|
||||
todoFilter () {
|
||||
return this.$route.params.filter
|
||||
},
|
||||
baseUrl () {
|
||||
const path = this.$route.path
|
||||
return path.slice(0, path.lastIndexOf('/'))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,123 +0,0 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: TodoItem.vue
|
||||
Description: Single todo item component
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div @click="displayPrompt" class="px-4 py-4 list-item-component">
|
||||
<div class="vx-row">
|
||||
<div class="vx-col w-full sm:w-5/6 flex sm:items-center sm:flex-row flex-col">
|
||||
<div class="flex items-center">
|
||||
<vs-checkbox v-model="isCompleted" class="w-8 m-0 vs-checkbox-small" @click.stop />
|
||||
<h6 class="todo-title" :class="{'line-through': taskLocal.isCompleted}">{{ taskLocal.title }}</h6>
|
||||
</div>
|
||||
<div class="todo-tags sm:ml-2 sm:my-0 my-2 flex">
|
||||
<vs-chip v-for="(tag, index) in taskLocal.tags" :key="index">
|
||||
<div class="h-2 w-2 rounded-full mr-1" :class="'bg-' + todoLabelColor(tag)"></div>
|
||||
<span>{{ tag | capitalize }}</span>
|
||||
</vs-chip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vx-col w-full sm:w-1/6 ml-auto flex sm:justify-end">
|
||||
<feather-icon
|
||||
icon="InfoIcon"
|
||||
class="cursor-pointer"
|
||||
:svgClasses="[{'text-success stroke-current': taskLocal.isImportant}, 'w-5', 'h-5 mr-4']"
|
||||
@click.stop="toggleIsImportant" />
|
||||
|
||||
<feather-icon
|
||||
icon="StarIcon"
|
||||
class="cursor-pointer"
|
||||
:svgClasses="[{'text-warning stroke-current': taskLocal.isStarred}, 'w-5', 'h-5 mr-4']"
|
||||
@click.stop="toggleIsStarred" />
|
||||
<feather-icon
|
||||
v-if="!taskLocal.isTrashed"
|
||||
icon="TrashIcon"
|
||||
class="cursor-pointer"
|
||||
svgClasses="w-5 h-5"
|
||||
@click.stop="moveToTrash" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="vx-row" v-if="taskLocal.desc">
|
||||
<div class="vx-col w-full">
|
||||
<p class="mt-2 truncate" :class="{'line-through': taskLocal.isCompleted}">{{ taskLocal.desc }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default{
|
||||
props: {
|
||||
taskId: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
taskLocal: this.$store.getters['todo/getTask'](this.taskId)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isCompleted: {
|
||||
get () {
|
||||
return this.taskLocal.isCompleted
|
||||
},
|
||||
set (value) {
|
||||
this.$store.dispatch('todo/updateTask', Object.assign({}, this.taskLocal, {isCompleted: value}))
|
||||
.then((response) => {
|
||||
this.taskLocal.isCompleted = response.data.isCompleted
|
||||
})
|
||||
.catch((error) => { console.error(error) })
|
||||
}
|
||||
},
|
||||
todoLabelColor () {
|
||||
return (label) => {
|
||||
const tags = this.$store.state.todo.taskTags
|
||||
return tags.find((tag) => {
|
||||
return tag.value === label
|
||||
}).color
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleIsImportant () {
|
||||
this.$store.dispatch('todo/updateTask', Object.assign({}, this.taskLocal, {isImportant: !this.taskLocal.isImportant}))
|
||||
.then((response) => {
|
||||
this.taskLocal.isImportant = response.data.isImportant
|
||||
})
|
||||
.catch((error) => { console.error(error) })
|
||||
},
|
||||
toggleIsStarred () {
|
||||
this.$store.dispatch('todo/updateTask', Object.assign({}, this.taskLocal, {isStarred: !this.taskLocal.isStarred}))
|
||||
.then((response) => {
|
||||
this.taskLocal.isStarred = response.data.isStarred
|
||||
})
|
||||
.catch((error) => { console.error(error) })
|
||||
},
|
||||
moveToTrash () {
|
||||
|
||||
this.$store.dispatch('todo/updateTask', Object.assign({}, this.taskLocal, {isTrashed: true}))
|
||||
.then((response) => {
|
||||
// console.log(response.data);
|
||||
this.taskLocal.isTrashed = response.data.isTrashed
|
||||
this.$el.style.display = 'none' // Hides element from DOM
|
||||
})
|
||||
.catch((error) => { console.error(error) })
|
||||
|
||||
// Un-comment below line if you want to fetch task after task is deleted
|
||||
// this.$store.dispatch("todo/fetchTasks", {filter: this.$route.params.filter})
|
||||
},
|
||||
displayPrompt () {
|
||||
this.$emit('showDisplayPrompt', this.taskId)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
<template>
|
||||
<Add/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Add from './add.vue'
|
||||
export default {
|
||||
name: "Edit",
|
||||
components:{
|
||||
Add
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="لیست فعالیت کاربران و ناظران" class="mb-base">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="نام کاربر">
|
||||
{{ dataProfile.rows[0].user.name }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="شماره تماس">
|
||||
{{ dataProfile.rows[0].user.mobile }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="میانگین تعدادنظارت روزانه">
|
||||
{{ dataProfile.avg.toFixed(2) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="پیک نظارتی">
|
||||
{{ dataProfile.max }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="ضریب فعالیت">
|
||||
{{ dataProfile.activity.toFixed(2) }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<XTable :model="model"></XTable>
|
||||
<a-descriptions style="margin: 10px 0">
|
||||
<a-descriptions-item label="جمع کل">
|
||||
{{dataProfile.query.total}}عدد
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableSpecialUser'
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "SpecialActivity",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
model: null,
|
||||
dataProfile:undefined
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
getInformationData(id){
|
||||
axios.post('/admin/activity/table/show/'+id).then((res)=>{
|
||||
this.dataProfile = res.data
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getInformationData(2)
|
||||
this.model = TableCol.default(3);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
import XTbl,{Xtc} from '../../../components/x-table/index';
|
||||
const tbl = new XTbl('/admin/user/table', 'لیست کاربران');
|
||||
|
||||
tbl.add(new Xtc('mobile', 'موبایل').filterNumber())
|
||||
tbl.add(new Xtc('name', 'نام').filterText())
|
||||
tbl.add(new Xtc('city', 'شهر').hidden().filterText())
|
||||
tbl.add(new Xtc('ncode', 'کدملی').filterNumber())
|
||||
tbl.add(new Xtc('birth_day', 'تاریخ تولد').hidden().filterDate())
|
||||
tbl.add(new Xtc('email', 'ایمیل').filterText())
|
||||
tbl.add(new Xtc('avatar', 'عکس پروفایل').hidden().filterSwitch())
|
||||
tbl.add(new Xtc('caj', 'تاریخ فرم ارسال').hidden().filterDate())
|
||||
tbl.add(new Xtc('user_type_str','نوع کاربری').hidden().filterText())
|
||||
tbl.add(new Xtc('active', 'فعالسازی').filterSwitch().renderSlot('active'))
|
||||
tbl.add(new Xtc('sts_str', 'وضعیت').filterSelect().renderSlot('sts_str'))
|
||||
tbl.add(new Xtc('', 'عملیات').noSort().renderSlot('names'))
|
||||
|
||||
export default tbl;
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<template>
|
||||
<vx-card title="لیست فعالیت کاربران و ناظران" class="mb-base">
|
||||
<!-- <a-descriptions>-->
|
||||
<!-- <a-descriptions-item label="میانگین کل کاربران">-->
|
||||
<!-- {{ total.avg.toFixed(2) }}-->
|
||||
<!-- </a-descriptions-item>-->
|
||||
<!-- </a-descriptions>-->
|
||||
<XTable :model="model"></XTable>
|
||||
<!-- <a-descriptions style="margin: 10px 0">-->
|
||||
<!-- <a-descriptions-item label="جمع کل">-->
|
||||
<!-- {{total.query.total}}-->
|
||||
<!-- </a-descriptions-item>-->
|
||||
<!-- </a-descriptions>-->
|
||||
</vx-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import XTable from '../../../components/x-table/XTable'
|
||||
import * as TableCol from './tableUserActivity'
|
||||
import axios from '@/axios'
|
||||
|
||||
export default {
|
||||
name: "UserActivity",
|
||||
components: {
|
||||
XTable
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
model: null,
|
||||
size: 8,
|
||||
total:undefined
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
getTotal(){
|
||||
axios.get('/admin/activity').then((res)=>{
|
||||
this.total = res.data
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getTotal()
|
||||
this.model = TableCol.default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user