transfer project in github

This commit is contained in:
hamid.zarghami1@gmail.com
2024-05-12 15:29:27 +03:30
commit e644edbd65
348 changed files with 164991 additions and 0 deletions
+101
View File
@@ -0,0 +1,101 @@
<template>
<div class="about--page page--container">
<section class="s1">
<div class="container">
<div class="txt">
<h1>درباره کافه رستوران برگ</h1>
<p>{{storeInfo.caption}}</p>
</div>
</div>
</section>
<section class="s2">
<!-- <div id="slick">-->
<!-- <div>-->
<!-- <img src="~/assets/img/aboutPage/about-i1.jpg" data-thumb-image="1" alt="">-->
<!-- </div>-->
<!-- <div>-->
<!-- <img src="~/assets/img/aboutPage/about-i2.jpg" data-thumb-image="2" alt="">-->
<!-- </div>-->
<!-- <div>-->
<!-- <img src="~/assets/img/aboutPage/about-i3.jpg" data-thumb-image="3" alt="">-->
<!-- </div>-->
<!-- <div>-->
<!-- <img src="~/assets/img/aboutPage/about-i4.jpg" data-thumb-image="4" alt="">-->
<!-- </div>-->
<!-- <div>-->
<!-- <img src="~/assets/img/aboutPage/about-i4.jpg" data-thumb-image="5" alt="">-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="imageModal">-->
<!-- <div class="relativePos">-->
<!-- <div class="bg"></div>-->
<!-- <div class="imgBox">-->
<!-- <div class="relativePos">-->
<!-- <IconsCloseBtn class="close&#45;&#45;btn"/>-->
<!-- &lt;!&ndash; images will be here &ndash;&gt;-->
<!-- <img src="~/assets/img/aboutPage/about-i1.jpg" data-2x-image="1" alt="">-->
<!-- <img src="~/assets/img/aboutPage/about-i2.jpg" data-2x-image="2" alt="">-->
<!-- <img src="~/assets/img/aboutPage/about-i3.jpg" data-2x-image="3" alt="">-->
<!-- <img src="~/assets/img/aboutPage/about-i4.jpg" data-2x-image="4" alt="">-->
<!-- <img src="~/assets/img/aboutPage/about-i4.jpg" data-2x-image="5" alt="">-->
<!-- &lt;!&ndash; images will be here &ndash;&gt;-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
</section>
</div>
</template>
<script>
if (process.client) require('slick-carousel')
export default {
data(){
return{
storeInfo :null
}
},
mounted() {
////////////////////////////////////////////////////////////////////////
$('#slick').slick({
slidesToShow: 4,
rtl: true,
draggable: false
})
$('#slick img').click(function () {
$('.about--page .imageModal img').removeClass('zoom')
$('.about--page .imageModal').addClass('modal--active')
$(`.about--page *[data-2x-image="${$(this).attr('data-thumb-image')}"]`).addClass('zoom')
})
$('.about--page .imageModal .bg,.about--page .imageModal .close--btn').click(function () {
$('.about--page .imageModal').removeClass('modal--active')
$('.about--page .imageModal img').removeClass('zoom')
})
////////////////////////////////////////////////////////////////////////
},
async asyncData({$axios, error}) {
try {
const storeInfo = await $axios.get('/api/public/storeInfo')
return {
storeInfo: storeInfo.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+609
View File
@@ -0,0 +1,609 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-customers'}">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="6">
<CCard>
<CCardBody>
<CForm>
<template v-if="$route.params.profile !== 'new'">
<h4>مشخصات مشتری</h4>
<el-divider/>
</template>
<CRow>
<CCol sm="12">
<CInput
label="نام"
disabled
:value="customer.first_name"
/>
</CCol>
<CCol sm="12">
<CInput
label="نام خانوادگی"
disabled
:value="customer.last_name"
/>
</CCol>
<CCol sm="12">
<CInput
label="کد مشتری"
disabled
:value="customer.business_code"
/>
<p class="form-err" v-if="validation.username">{{ validation.username.msg }}</p>
</CCol>
<CCol sm="12">
<CInput
label="تلفن همراه"
disabled
:value="customer.mobile_number"
/>
</CCol>
<CCol sm="12">
<CInput
label="ایمیل"
disabled
:value="customer.email"
/>
</CCol>
<CCol sm="12">
<CInput
label="کد ملی"
disabled
:value="customer.national_code"
/>
</CCol>
<CCol sm="12">
<CInput
label="شغل"
disabled
:value="customer.job"
/>
</CCol>
<CCol sm="12">
<CInput
label="تاریخ تولد"
disabled
:value="jDateOfCustomer(customer.birth_date)"
/>
</CCol>
<CCol sm="12">
<CInput
label="تاریخ ازدواج"
disabled
:value="jDateOfCustomer(customer.marriage_date)"
/>
</CCol>
<CCol sm="12">
<CInput
label="امتیاز"
disabled
:value="customer.score"
/>
</CCol>
<CCol sm="12">
<CInput
label="موجودی کیف پول"
disabled
:value="customer.bagAmount + ' ریال'"
/>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h4>کد های تخفیف مشتری</h4>
<el-divider></el-divider>
<el-table
:data="customer.discount_codes"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="discount_code"
label="کد"
width="">
</el-table-column>
<el-table-column
label="درصد تخفیف"
width="">
<template slot-scope="scope">
{{ scope.row.discount_amount + '%' }}
</template>
</el-table-column>
<el-table-column
label="استفاده شده"
width="">
<template slot-scope="scope">
<span v-if="scope.row.used_by.includes(customer._id)">بله</span>
<span v-else>خیر</span>
</template>
</el-table-column>
<el-table-column
prop="province"
label="تاریخ انقضا"
width="">
<template slot-scope="scope">
{{ jDateDiscount(scope.row.discount_expire_date) }}
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
<CCol sm="12">
<CCard>
<CCardBody>
<h4>آدرس های مشتری</h4>
<el-divider></el-divider>
<el-table
:data="customer.addresses"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="title"
label="عنوان"
width="100">
</el-table-column>
<el-table-column
prop="province"
label="استان"
width="100">
</el-table-column>
<el-table-column
prop="city"
label="شهر"
width="100">
</el-table-column>
<el-table-column
prop="address"
label="آدرس"
width="600">
</el-table-column>
<el-table-column
label="ویرایش"
width="200"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" @click="deleteAddress(scope.row._id)" :key="scope.row._id + Math.random()">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton
variant="outline"
title="بروزرسانی"
color="success"
:key="scope.row._id"
@click="openDialog(scope.row)">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
<CCol sm="12">
<CCard>
<CCardBody>
<h4>لیست تراکنش ها</h4>
<el-divider></el-divider>
<el-table
:data="payments.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="نوع تراکنش"
width="">
<template slot-scope="scope">
<el-tag
type="success"
effect="dark">
<span>{{
scope.row.action === 'increaseBag' ? 'افزایش کیف پول' : scope.row.action === 'decreaseBag' ? 'کاهش کیف پول' : 'پرداخت اینترنتی'
}}
</span>
</el-tag>
</template>
</el-table-column>
<el-table-column
label="وضعیت پرداخت"
width="">
<template slot-scope="scope">
<el-tag
:type="scope.row.status === 'paid' ? 'success' : 'danger' "
effect="dark">
<span>{{ scope.row.status === 'paid' ? 'پرداخت موفق' : 'پرداخت ناموفق'}}</span>
</el-tag>
</template>
</el-table-column>
<el-table-column
label="مبلغ"
width="">
<template slot-scope="scope">
{{ scope.row.cost.toLocaleString() + ' ریال' }}
</template>
</el-table-column>
<el-table-column
label="تاریخ و ساعت"
width="">
<template slot-scope="scope">
{{ jDate(scope.row.created_at) }}
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="payments.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="payments.limit"
@current-change="handleCurrentChange" :current-page.sync="payments.page" :total="payments.totalDocs">
</el-pagination>
</CRow>
</CCard>
</CCol>
<CCol sm="12">
<CCard>
<CCardBody>
<h4>لاگ امتیازها</h4>
<el-divider></el-divider>
<el-table
:data="customer.scoreLogs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="وضعیت"
width="">
<template slot-scope="scope">
<el-tag
:type="scope.row.action === 'decrease'? 'danger' : 'success'"
effect="dark">
<span>{{scope.row.action === 'decrease' ? 'کاهش امتیاز' : 'افزایش امتیاز' }}</span>
</el-tag>
</template>
</el-table-column>
<el-table-column
label="برای"
width="">
<template slot-scope="scope">
<span>{{ forWhat(scope.row.forWhat)}}</span>
</template>
</el-table-column>
<el-table-column
label="امتیاز"
prop="score"
width="">
</el-table-column>
<el-table-column
label="تاریخ و ساعت"
width="">
<template slot-scope="scope">
{{ jDate(scope.row.created_at) }}
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
</CRow>
<el-dialog
title="آدرس"
:visible.sync="dialogVisible"
width="50%">
<CInput
label="عنوان"
:class="validation.title ? 'err' : null"
:description="validation.title ? validation.title.msg : null"
v-model="address.title"/>
<CInput
label="استان"
:class="validation.province ? 'err' : null"
:disabled="true"
:description="validation.province ? validation.province.msg : null"
v-model="address.province"/>
<CInput
label="شهر"
:class="validation.city ? 'err' : null"
:disabled="true"
:description="validation.city ? validation.city.msg : null"
v-model="address.city"/>
<CInput
label="آدرس"
:class="validation.address ? 'err' : null"
:description="validation.address ? validation.address.msg : null"
v-model="address.address"/>
<span slot="footer" class="dialog-footer">
<el-button type="success" @click="updateAddress">بروزرسانی</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import moment from "moment-jalaali"
export default {
data() {
return {
title: 'مشاهده پروفایل مشتری',
customer: null,
payments : null,
dialogVisible: false,
validation: {},
address: {}
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch:{
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
forWhat(status) {
switch (status) {
case 'birthDate':
return 'تولد'
case 'marriageDate':
return 'سالگرد ازدواج'
case 'buy':
return 'خرید'
case 'register':
return 'ثبت نام'
case 'invite':
return 'دعوت دوستان'
case 'emailVerify':
return 'تایید ایمیل'
default :
return 'نامشخص'
}
},
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-customers-profile",
query: {
page: page
}
});
// }
},
openDialog(address) {
this.address = address
this.dialogVisible = true
},
updateAddress() {
this.validation = {}
this.$axios.put(`/api/admin/address/${this.address._id}`, this.address)
.then(res => {
this.dialogVisible = false;
this.$message({
type: 'success',
message: 'آدرس با موفقیت ثبت شد'
})
this.$nuxt.refresh()
})
.catch(err => {
console.log(err.response.data)
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 403) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 500) {
return this.$message({
type: "error",
message: "مشکلی در ارسال درخواست پیش آمده",
});
}
if (err.response.status === 422) {
this.$message({
type: 'warning',
message: 'پارامترها را بررسی کنید'
})
this.validation = err.response.data.validation;
} else console.log(err.response.data);
})
},
deleteAddress(id) {
this.$confirm("آدرس حذف شود؟", "اخطار", {
confirmButtonText: "بله",
cancelButtonText: "لغو",
type: "warning",
})
.then(async () => {
this.validation = {}
this.$axios.delete(`/api/admin/address/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'آدرس با موفقیت حذف شد'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 403) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 404) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 500) {
return this.$message({
type: "error",
message: "مشکلی در ارسال درخواست پیش آمده",
});
}
if (err.response.status === 422) {
this.$message({
type: 'warning',
message: 'پارامترها را بررسی کنید'
})
this.validation = err.response.data.validation;
} else console.log(err.response.data);
})
})
.catch(() => {
this.$message({
type: "warning",
message: "عملیات لغو شد",
});
});
},
imagePreview(e) {
this.customer.profile_pic = URL.createObjectURL(e.target.files[0])
},
jDate(date) {
return moment(date).format('jYYYY/jMM/jDD HH:MM')
},
jDateOfCustomer(date) {
if (date){
return moment(date).format('jYYYY/jMM/jDD')
}
},
jDateDiscount(date) {
return moment(date , 'X').format('jYYYY/jMM/jDD')
},
update() {
this.validation = {}
const data = new FormData()
data.append("first_name", this.customer.first_name)
data.append("last_name", this.customer.last_name)
data.append("mobile_number", this.customer.mobile_number)
data.append("email", this.customer.email)
data.append("username", this.customer.username)
data.append("permissions", JSON.stringify(this.customer.permissions))
data.append("password", this.customer.password)
data.append("password_confirmation", this.customer.password_confirmation)
if (this.$refs.profile_pic.files[0]) data.append("profile_pic", this.$refs.profile_pic.files[0])
this.$axios.put(`/api/admin/admin/${this.customer._id}`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'اطلاعات بروزرسانی شد.'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, query , error}) {
try {
const customer = await $axios.get(`/api/admin/user/${params.profile}`)
const payments = await $axios.get(`/api/admin/payments/${params.profile}?page=${query.page || 1}`)
return {
customer: customer.data,
payments: payments.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
+191
View File
@@ -0,0 +1,191 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<a :href="`/api/public/users/exportExel/${$auth.user._id}`" target="_blank" class="mr-auto">
<CButton size="sm" color="success">خروجی اکسل</CButton>
</a>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="customers.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="first_name"
label="نام"
width="">
</el-table-column>
<el-table-column
prop="last_name"
label="نام خانوادگی"
width="">
</el-table-column>
<el-table-column
prop="mobile_number"
label="شماره موبایل"
width="">
</el-table-column>
<el-table-column
prop="business_code"
label="کد مشتری"
width="">
</el-table-column>
<el-table-column
prop="score"
label="score"
width="">
</el-table-column>
<el-table-column
label="مشاهده"
width="70"
align="center">
<template slot-scope="scope">
<CButton color="success" variant="outline" :key="scope.row._id"
:to="{name: 'admin-branch-customers-profile',params: {profile: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="customers.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="customers.limit"
@current-change="handleCurrentChange" :current-page.sync="customers.page" :total="customers.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست مشتریان',
list_title: 'لیست',
customers: null
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch:{
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-branch-customers",
query: {
page: page
}
});
// }
},
deleteUser(id) {
this.$confirm('کاربر حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/admin/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'کاربر با موفقیت حذف شد'
})
this.customers.docs = this.customers.docs.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
async createExel(){
try {
const createExel = await this.$axios.$get(`/api/admin/users/exportExel`);
console.log(createExel)
}catch (e) {
if (e?.response?.status === 401) {
this.$message({
type: 'warning',
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
this.$message({
type: 'warning',
message: 'مشکلی در گرفتن اطلاعات بوجود آمده است'
})
}
}
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios,query, error, params}) {
try {
const customers = await $axios.get(`/api/admin/users/${params.branch}?page=${query.page || 1}`)
return {
customers: customers.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+315
View File
@@ -0,0 +1,315 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<!-- <CButton size="sm" color="success" :to="{name: 'admin-discounts-discount',params:{profile: 'new'}}" class="mr-auto">افزودن</CButton>-->
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<h2>افزودن کد تخفیف</h2>
<el-divider></el-divider>
<el-button-group>
<el-button :type="newDiscountIsPublic ? 'info' : 'primary'" @click="newDiscountIsPublic = false" icon="el-icon-arrow-left">کد تخفیف اختصاصی</el-button>
<el-button :type="newDiscountIsPublic ? 'primary' : 'info'" @click="newDiscountIsPublic = true" icon="el-icon-arrow-left">کد تخفیف عمومی</el-button>
</el-button-group>
<br>
<el-select
v-if="!newDiscountIsPublic"
v-model="discount_user_id"
filterable
style="width: 300px;margin-top: 20px;margin-bottom: 10px;">
<el-option
v-for="item in users"
:key="item._id"
:value="item._id"
:label="item.business_code + ' ' + '(' + item.first_name + ' ' + item.last_name + ')'"/>
</el-select>
<p class="text-danger" v-if="validation.discount_user_id">{{ validation.discount_user_id.msg }}</p>
<div v-if="newDiscountIsPublic" style="margin-top: 20px;margin-bottom: 10px;">
<el-switch
style="direction: ltr;margin-bottom: 20px;"
v-model="publicDiscountIsAuto"
active-text="ایجاد کد تخفیف توسط سیستم"
inactive-text="وارد کردن کد دستی">
</el-switch>
<el-input v-model="customDiscountCode" v-if="!publicDiscountIsAuto" placeholder="کدتخفیف دستی را وارد کنید" style="width: 300px;display: block;"></el-input>
<p class="text-danger" v-if="validation.customDiscountCode">{{ validation.customDiscountCode.msg }}</p>
</div>
<el-input v-model="discount_amount" placeholder="درصد تخفیف را وارد کنید" style="display: block;width: 300px;margin-bottom: 10px;"></el-input>
<p class="text-danger" v-if="validation.discount_amount">{{ validation.discount_amount.msg }}</p>
<date-picker
v-model="discount_expire_date"
placeholder="تاریخ انقضای کد را مشخص کنید"
format="X"
displayFormat="jYYYY/jMM/jDD"
style="display: block;width: 300px!important;margin-bottom: 10px;"/>
<p class="text-danger" v-if="validation.discount_expire_date">{{ validation.discount_expire_date.msg }}</p>
<el-select
v-model="menuTypeId"
filterable
placeholder="منو را انتخاب کنید"
style="width: 300px;margin-bottom: 20px;">
<el-option
v-for="item in menuTypes"
:key="item._id"
:value="item._id"
:label="item.name"/>
</el-select>
<p class="text-danger" v-if="validation.menuTypeId">{{ validation.menuTypeId.msg }}</p>
<br>
<el-button type="success" @click="addDiscount">ایجاد کد تخفیف</el-button>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="discounts.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="discount_code"
label="کد تخفیف"
width="">
</el-table-column>
<el-table-column
label="درصد تخفیف"
width="">
<template slot-scope="scope">
<span class="text-success">{{ scope.row.discount_amount + '%' }}</span>
</template>
</el-table-column>
<el-table-column
label="تاریخ انقضا"
width="">
<template slot-scope="scope">
{{ jDate(scope.row.discount_expire_date) }}
</template>
</el-table-column>
<el-table-column
label="در دسترس برای"
width="">
<template slot-scope="scope">
<span v-if="scope.row.isPublic" class="text-success">برای همه</span>
<span v-else>{{ scope.row.discount_user_id.first_name + ' ' + scope.row.discount_user_id.last_name }}</span>
</template>
</el-table-column>
<el-table-column
label="حذف"
width="75"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="deleteUser(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="discounts.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="discounts.limit"
@current-change="handleCurrentChange" :current-page.sync="discounts.page" :total="discounts.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
import moment from 'moment-jalaali'
export default {
data() {
return {
title: 'لیست کدهای تخفیف',
list_title: 'لیست',
// base data
discounts: null,
users: null,
menuTypes: null,
// discount details
discount_user_id: '',
discount_expire_date: '',
menuTypeId: '',
discount_amount: '',
customDiscountCode: '',
newDiscountIsPublic: true,
publicDiscountIsAuto: true,
loading: false,
// validation
validation: {}
}
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
},
newDiscountIsPublic(newVal, oldVal) {
this.validation = {}
},
publicDiscountIsAuto(newVal, oldVal) {
this.validation = {}
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
methods: {
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-branch-discounts",
query: {
page: page
}
});
// }
},
addDiscount() {
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.validation = {}
const data = {
discount_user_id: this.discount_user_id,
discount_expire_date: this.discount_expire_date,
discount_amount: this.discount_amount,
menuTypeId: this.menuTypeId,
customDiscountCode: this.customDiscountCode,
newDiscountIsPublic: this.newDiscountIsPublic,
publicDiscountIsAuto: this.publicDiscountIsAuto,
branchId: this.$route.params.branch
}
this.$axios.post('/api/admin/discountCode', data)
.then(res => {
loading.close()
this.$alert('', 'موفق', {
type: 'success',
message: `کد تخفیف: ${res.data.discount_code}`
})
this.discount_user_id = ''
this.discount_expire_date = ''
this.discount_amount = ''
this.menuTypeId = ''
this.customDiscountCode = ''
this.$nuxt.refresh()
})
.catch(err => {
loading.close()
if (err.response.status === 422) return this.validation = err.response.data.validation
else if (err.response.status === 500) error({
status: 500,
message: err.response.data.message,
});
else console.log(err)
})
},
deleteUser(id) {
this.$confirm('کد تخفیف حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/discountCode/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'کد تخفیف با موفقیت حذف شد'
})
this.discounts.docs = this.discounts.docs.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
jDate(date) {
return moment(date, 'X').format('jYYYY/jMM/jDD')
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, query, error, params}) {
try {
const users = await $axios.get(`/api/admin/users/getAll/${params.branch}`)
const menuTypes = await $axios.get(`/api/public/menuTypes/getAll/${params.branch}`)
const discounts = await $axios.get(`/api/admin/discountCodes/${params.branch}?page=${query.page || 1}`)
return {
users: users.data,
discounts: discounts.data,
menuTypes: menuTypes.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
<style lang="scss">
.el-button:focus {
outline-color: #39f !important;
}
</style>
@@ -0,0 +1,203 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-branch-food-categories'}">برگشت به صفحه
قبل</CButton>
<CButton v-if="$route.params.category === 'new'" size="sm" color="success" class="mr-1" @click="post">افزودن</CButton>
<CButton v-else size="sm" color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="6">
<CCard>
<CCardBody>
<CForm>
<CRow>
<CCol sm="12">
<CInput
:class="validation.name ? 'err' : null"
label="نام"
:description="validation.name ? validation.name.msg : null"
v-model="foodCategory.name"
/>
</CCol>
</CRow>
<CRow>
<CCol s="12">
<span>نوع منو</span>
</CCol>
<CCol sm="12" class="err">
<el-select v-model="foodCategory.type" filterable style="width: 100%;margin-top: 5px;">
<el-option v-for="item in menuTypes" :key="item._id" :value="item._id" :label="item.name"/>
</el-select>
<p v-if="validation.type" class="text-danger" style="margin-top: 5px;">{{ validation.type.msg }}</p>
</CCol>
</CRow>
<CRow>
<CCol s="12" class="mt-3">
<span>ترتیب نمایش در منو</span>
</CCol>
<CCol sm="12" class="err">
<el-select v-model="foodCategory.index" filterable style="width: 100%;margin-top: 5px;">
<el-option
v-for="item in 1000"
v-if="!foodCategories.filter(item2=>Number(item2.index) === item && item2.type._id === foodCategory.type).length"
:key="item + 202"
:value="item"
:label="item"/>
</el-select>
<p v-if="validation.index" class="text-danger" style="margin-top: 5px;">{{ validation.index.msg }}</p>
</CCol>
</CRow>
</CForm>
<el-divider></el-divider>
<h3>کاور</h3>
<img :src="foodCategory.cover" style="width: 100%;max-width: 300px;" alt="">
<input type="file" ref="cover" @change="preview">
<p class="text-danger" v-if="validation.cover">{{ validation.cover.msg }}</p>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import axiosUploadProcess from "@/mixins/axiosUploadProcess"
export default {
data() {
return {
foodCategories: null,
foodCategory: null,
menuTypes: null,
validation: {}
}
},
mixins: [axiosUploadProcess],
computed: {
title() {
return this.$route.params.category === 'new' ? 'افزودن دسته بندی' : 'مشاهده دسته بندی'
}
},
methods: {
preview(event) {
this.foodCategory.cover = URL.createObjectURL(event.target.files[0])
},
post() {
this.validation = {}
const data = new FormData()
data.append('name', this.foodCategory.name)
data.append('type', this.foodCategory.type)
data.append('index', this.foodCategory.index)
data.append('cover', this.$refs.cover.files[0])
data.append('branchId', this.$route?.params?.branch)
this.$axios.post(`/api/admin/foodCategory`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'دسته بندی با موفقیت ایجاد شد.'
})
this.$refs.cover.value = null
this.$router.push({name: 'admin-branch-food-categories'})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
},
update() {
this.validation = {}
const data = new FormData()
data.append('name', this.foodCategory.name)
data.append('type', this.foodCategory.type)
data.append('index', this.foodCategory.index)
data.append('branchId', this.$route?.params?.branch)
if (this.$refs.cover.files[0]) data.append('cover', this.$refs.cover.files[0])
this.$axios.put(`/api/admin/foodCategory/${this.foodCategory._id}`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'اطلاعات بروزرسانی شد.'
})
this.$refs.cover.value = null
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
const foodCategories = await $axios.get(`/api/public/foodCategories/getAll/${params?.branch}`)
const menuTypes = await $axios.get(`/api/admin/allMenuType/getAll/${params?.branch}`)
if (params.category !== 'new') {
const foodCategory = await $axios.get(`/api/public/foodCategory/${params.category}`)
return {
foodCategories: foodCategories.data,
menuTypes: menuTypes.data,
foodCategory: foodCategory.data
}
} else {
return {
foodCategories: foodCategories.data,
menuTypes: menuTypes.data,
foodCategory: {
name: '',
type: '',
cover: '',
index: 0
}
}
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
@@ -0,0 +1,187 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{name: 'admin-branch-food-categories-category',params:{category: 'new'}}"
class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="foodCategories.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="کاور"
width="200">
<template slot-scope="scope">
<img :src="scope.row.cover" style="width: 100%;" alt="">
</template>
</el-table-column>
<el-table-column
prop="name"
label="نام"
width="">
</el-table-column>
<el-table-column
prop="type.name"
label="نوع منو"
:filters="filter"
:filter-method="filterType"
width="">
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="remove(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id" :to="{name:
'admin-branch-food-categories-category',params: {category: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="foodCategories.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="foodCategories.limit"
@current-change="handleCurrentChange" :current-page.sync="foodCategories.page" :total="foodCategories.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست دسته بندی غذاها',
list_title: 'لیست',
foodCategories: null,
menuTypes: null
}
},
computed: {
pageQuery() {
return this.$route.query.page;
},
filter(){
const fill = []
for (const item of this.menuTypes) {
fill.push({
text : item.name,
value : item._id
})
}
return fill
}
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-branch-food-categories",
query: {
page: page
}
});
// }
},
filterType(value, row){
return row.type._id === value;
},
remove(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/foodCategory/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'دسته بندی با موفقیت حذف شد'
})
this.foodCategories.docs = this.foodCategories.docs.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 403) {
return this.$message({
type: 'error',
message: err.response.data.message
})
} else console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios,query, error, params}) {
try {
const foodCategories = await $axios.get(`/api/admin/foodCategory/getAll/${params.branch}?page=${query.page ||
1}`)
const menuTypes = await $axios.get(`/api/admin/allMenuType/getAll/${params.branch}`)
return {
foodCategories: foodCategories.data,
menuTypes: menuTypes.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+573
View File
@@ -0,0 +1,573 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-branch-foods'}">برگشت به صفحه قبل</CButton>
<CButton v-if="$route.params.food === 'new'" size="sm" color="success" class="mr-1" @click="post">افزودن</CButton>
<CButton v-else size="sm" color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="6">
<CCard>
<CCardBody>
<CForm>
<CRow>
<CCol sm="12">
<el-checkbox v-model="food.special" label="قرار گرفتن در منوی ویژه سرآشپز"/>
</CCol>
<CCol sm="12">
<el-checkbox v-model="food.havePoint" label="افزودن امتیاز به مشتری برای خرید این محصول"/>
</CCol>
<CCol sm="12">
<el-checkbox v-model="food.sale" label="این محصول به صورت عادی فروخته شود"/>
</CCol>
<CCol sm="12">
<el-checkbox v-model="food.club" label="این محصول با امتیاز به فروش برسد"/>
</CCol>
<el-divider></el-divider>
<CCol sm="12">
<CInput
v-if="food.club"
:class="validation.point ? 'err' : null"
label="مقدار امتیاز برای خرید"
:description="validation.point ? validation.point.msg : null"
v-model="food.point"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.name ? 'err' : null"
label="نام"
:description="validation.name ? validation.name.msg : null"
v-model="food.name"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.short_description ? 'err' : null"
label="توضیحات کوتاه"
placeholder="پرس ویژه (اختیاری)"
:description="validation.short_description ? validation.short_description.msg : null"
v-model="food.short_description"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.description ? 'err' : null"
label="توضیحات"
placeholder="مواد تشکیل دهنده (اختیاری)"
:description="validation.description ? validation.description.msg : null"
v-model="food.description"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.estimated_time ? 'err' : null"
label="زمان آماده سازی (دقیقه)"
placeholder="اختیاری"
:description="validation.estimated_time ? validation.estimated_time.msg : null"
v-model="food.estimated_time"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.stock ? 'err' : null"
label="موجودی"
:description="validation.stock ? validation.stock.msg : null"
v-model="food.stock"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.price ? 'err' : null"
label="قیمت (ريال)"
:description="validation.price ? validation.price.msg : null"
v-model="food.price"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.static_discount ? 'err' : null"
label="تخفیف روز (درصد)"
placeholder="اختیاری"
:description="validation.static_discount ? validation.static_discount.msg : null"
v-model="food.static_discount"
/>
</CCol>
</CRow>
<CRow>
<CCol s="12">
<span>دسته بندی</span>
</CCol>
<CCol sm="12" class="err">
<el-select v-model="food.category" filterable style="width: 100%;margin-top: 5px;">
<el-option v-for="item in foodCategories" :key="item._id" :value="item._id" :label="item.name"/>
</el-select>
<p v-if="validation.category" class="text-danger" style="margin-top: 5px;">{{ validation.category.msg }}</p>
</CCol>
</CRow>
<CRow>
<CCol s="12" class="mt-3">
<span>ترتیب نمایش در منو</span>
</CCol>
<CCol sm="12" class="err">
<el-select v-model="food.index" filterable style="width: 100%;margin-top: 5px;">
<el-option
v-for="item in foods.length + 10"
v-if="!foods.find(item2=>Number(item2.index) === item && item2.category === food.category)"
:key="item + 202"
:value="item"
:label="item"/>
</el-select>
<p v-if="validation.index" class="text-danger" style="margin-top: 5px;">{{ validation.index.msg }}</p>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h3>تصویر: (اختیاری)</h3>
<el-divider></el-divider>
<img :src="food.image" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="image" @change="imagePreview">
</CCardBody>
</CCard>
</CCol>
<CCol v-if="$route.params.food !== 'new'">
<CCard>
<CCardBody>
<div class="row mb-5">
<div class="col-sm-2">
<div class="callout">
<small class="text-muted">تعداد کل رای ها</small><br>
<strong class="h4">{{ food.ratings.length }}</strong>
</div>
</div><!--/.col-->
<div class="col-sm-2">
<div class="callout rate">
<small class="text-muted">میانگین امتیاز ها</small><br>
<strong class="h4">
{{ food.rate }}
</strong>
<i class="fas fa-star"></i>
</div>
</div><!--/.col-->
</div><!--/.row-->
<h3>نظرات مشتریان</h3>
<el-divider></el-divider>
<el-table
:data="food.ratings.filter(item=>item.comment && item.comment.length)"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop=""
label="نام"
width="">
<template slot-scope="scope" v-if="scope.row.user_id">
{{ scope.row.user_id.first_name + ' ' + scope.row.user_id.last_name }}
</template>
</el-table-column>
<el-table-column
label="تاریخ"
width="">
<template slot-scope="scope">
{{ jDate(scope.row.cretated_at) }}
</template>
</el-table-column>
<el-table-column
label="امتیاز"
width="">
<template slot-scope="scope">
<span>{{ scope.row.rate }}</span>
<i class="fas fa-star"></i>
</template>
</el-table-column>
<el-table-column
label="نظر"
width="">
<template slot-scope="scope">
<span>
<el-popover v-if="scope.row.comment" placement="top-end" trigger="hover" :content="scope.row.comment">
<i v-if="scope.row.comment.length > 25" class="el-icon-info" slot="reference"></i>
</el-popover>
{{ scope.row.comment || 'بدون پاسخ' }}
</span>
</template>
</el-table-column>
<el-table-column
label="پاسخ"
width="">
<template slot-scope="scope">
<span>
<el-popover v-if="scope.row.replay" placement="top-end" trigger="hover" :content="scope.row.replay">
<i v-if="scope.row.replay.length > 25" class="el-icon-info" slot="reference"></i>
</el-popover>
{{ scope.row.replay || 'بدون پاسخ' }}
</span>
</template>
</el-table-column>
<el-table-column
label="ویرایش"
width=""
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" @click="deleteComment(scope.row._id)" :key="scope.row._id + Math.random()">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="primary" variant="outline" @click="openDialog(scope.row._id, scope.row.replay)" :key="scope.row._id + Math.random()">
<i class="far fa-comment-alt"></i>
</CButton>
<CButton
variant="outline"
:title="scope.row.confirmed ? 'غیرفعال کردن' : 'فعال کردن'"
:color="scope.row.confirmed ? 'danger' : 'success'"
:key="scope.row._id"
@click="changeCommentStatus(scope.row._id,!scope.row.confirmed)"
>
<i class="fas" :class="scope.row.confirmed ? 'fa-do-not-enter' : 'fa-check'"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
</CRow>
<el-dialog
title="پاسخ"
:visible.sync="dialogVisible"
width="50%">
<CTextarea
:class="validation.replay ? 'err' : null"
placeholder="پیام خود را وارد کنید"
:description="validation.replay ? validation.replay.msg : null"
v-model="replay"/>
<span slot="footer" class="dialog-footer">
<el-button type="success" @click="addReply">ارسال</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import axiosUploadProcess from "@/mixins/axiosUploadProcess"
import moment from "moment-jalaali"
export default {
data() {
return {
foods: null,
foodCategories: null,
menuTypes: null,
food: null,
validation: {},
dialogVisible : false,
replay : '',
commentId : ''
}
},
mixins: [axiosUploadProcess],
computed: {
title() {
return this.$route.params.food === 'new' ? 'افزودن غذا' : 'مشاهده غذا'
}
},
methods: {
openDialog(id , text){
this.commentId = id
this.replay = text
this.dialogVisible = true
},
jDate(date) {
return moment(date).format('jYYYY/jMM/jDD')
},
imagePreview(e) {
this.food.image = URL.createObjectURL(e.target.files[0])
},
changeCommentStatus(id, status) {
this.$axios.post(`/api/admin/commentStatus/${id}`, {confirmed: status})
.then(res => {
this.$message({
type: 'success',
message: 'وضعیت کامنت یا موفقیت تغییر کرد'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err) console.log(err)
this.$message({
type: 'error',
message: 'مشکلی پیش آمده، لطفا دوباره تلاش کنید'
})
})
},
addReply(){
this.validation = {}
this.$axios.post(`/api/admin/replayComment/${this.commentId}`, {replay: this.replay})
.then(res => {
this.dialogVisible = false;
this.$message({
type: 'success',
message: 'پاسخ با موفقیت ثبت شد'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 403) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 500) {
return this.$message({
type: "error",
message: "مشکلی در ارسال درخواست پیش آمده",
});
}
if (err.response.status === 422){
this.$message({
type: 'warning',
message: 'پارامترها را بررسی کنید'
})
this.validation = err.response.data.validation;
} else console.log(err.response.data);
})
},
deleteComment(id){
this.$confirm("کامنت حذف شود؟", "اخطار", {
confirmButtonText: "بله",
cancelButtonText: "لغو",
type: "warning",
})
.then(async () => {
this.validation = {}
this.$axios.delete(`/api/admin/deleteComment/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'کامنت با موفقیت حذف شد'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 403) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 500) {
return this.$message({
type: "error",
message: "مشکلی در ارسال درخواست پیش آمده",
});
}
if (err.response.status === 422){
this.$message({
type: 'warning',
message: 'پارامترها را بررسی کنید'
})
this.validation = err.response.data.validation;
} else console.log(err.response.data);
})
})
.catch(() => {
this.$message({
type: "warning",
message: "عملیات لغو شد",
});
});
},
post() {
this.validation = {}
const data = new FormData()
data.append('name', this.food.name)
data.append('price', this.food.price)
data.append('description', this.food.description)
data.append('short_description', this.food.short_description)
this.food.estimated_time && data.append('estimated_time', this.food.estimated_time)
data.append('stock', this.food.stock)
data.append('category', this.food.category)
data.append('static_discount', this.food.static_discount)
data.append('special', this.food.special)
data.append('index', this.food.index)
data.append('havePoint', this.food.havePoint)
data.append('club', this.food.club)
data.append('point', this.food.point)
data.append('sale', this.food.sale)
data.append('branchId', this.$route?.params?.branch)
if (this.$refs.image.files[0]) data.append('image', this.$refs.image.files[0])
this.$axios.post(`/api/admin/food`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'غذا با موفقیت ایجاد شد.'
})
this.$router.push({name: 'admin-branch-foods'})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
},
update() {
this.validation = {}
const data = new FormData()
data.append('name', this.food.name)
data.append('price', this.food.price)
data.append('description', this.food.description || '')
data.append('short_description', this.food.short_description || '')
this.food.estimated_time && data.append('estimated_time', this.food.estimated_time)
data.append('stock', this.food.stock)
data.append('category', this.food.category)
data.append('static_discount', this.food.static_discount)
data.append('special', this.food.special)
data.append('index', this.food.index)
data.append('havePoint', this.food.havePoint)
data.append('club', this.food.club)
data.append('point', this.food.point)
data.append('sale', this.food.sale)
data.append('branchId', this.$route?.params?.branch)
if (this.$refs.image.files[0]) data.append('image', this.$refs.image.files[0])
this.$axios.put(`/api/admin/food/${this.food._id}`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'اطلاعات بروزرسانی شد.'
})
this.$nuxt.refresh()
this.$refs.image.value = null
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error }) {
try {
const foods = await $axios.get(`/api/public/foods/getAll/${params?.branch}`)
const menuTypes = await $axios.get(`/api/public/menuTypes/getAll/${params?.branch}`)
const foodCategories = await $axios.get(`/api/public/foodCategories/getAll/${params?.branch}`)
if (params.food !== 'new') {
const food = await $axios.get(`/api/admin/food/${params.food}`)
return {
foods: foods.data,
menuTypes: menuTypes.data,
foodCategories: foodCategories.data,
food: food.data
}
} else {
return {
foods: foods.data,
menuTypes: menuTypes.data,
foodCategories: foodCategories.data,
food: {
name: '',
image: '',
price: 0,
stock: 0,
description: '',
short_description: '',
estimated_time: '',
category: '',
static_discount: 0,
index: 0,
special : false,
havePoint : false,
club : false,
sale: true,
point : 0
}
}
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
<style lang="scss">
.callout {
border: 0.5px solid rgba(#000, 0.3);
border-right: 6px solid blue;
border-radius: 5px;
padding: 3px 5px;
&.rate {
border-right: 5px solid goldenrod;
i {
color: goldenrod;
font-size: 19px;
}
}
}
</style>
+336
View File
@@ -0,0 +1,336 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{name: 'admin-branch-foods-food',params:{food: 'new'}}" class="mr-auto">
افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-filter"></i>
<span style="color:#000">فیلتر</span>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol md="6">
<CRow style="flex-direction : column;">
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>نام</span>
</CCol>
<CCol col="md-9">
<el-input style="width : 100%" placeholder="" v-model="search.name"></el-input>
</CCol>
</CRow>
</CCol>
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>دسته بندی</span>
</CCol>
<CCol col="md-9">
<el-select filterable clearable style="width : 100%" v-model="search.category"
placeholder="">
<el-option
v-for="item in foodCategories"
:key="item._id"
:value="item._id"
:label="item.name"/>
</el-select>
</CCol>
</CRow>
</CCol>
</CRow>
</CCol>
<CCol md="6">
<CRow style="flex-direction : column;">
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>فروش به صورت عادی</span>
</CCol>
<CCol col="md-9">
<el-select v-model="search.sale" clearable style="width : 100%">
<el-option :key="1" label="بله" :value="true"></el-option>
<el-option :key="2" label="خیر" :value="false"></el-option>
</el-select>
</CCol>
</CRow>
</CCol>
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>فروش در باشگاه مشتریان</span>
</CCol>
<CCol col="md-9">
<el-select v-model="search.club" clearable style="width : 100%">
<el-option :key="1" label="بله" :value="true"></el-option>
<el-option :key="2" label="خیر" :value="false"></el-option>
</el-select>
</CCol>
</CRow>
</CCol>
</CRow>
</CCol>
</CRow>
<CRow>
<el-button :loading="loading" @click="handleSearch" size="small"
style="width: auto;margin: 25px auto auto auto;" type="primary"
icon="el-icon-search">
جست و جو
</el-button>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="foods.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="عکس"
width="">
<template slot-scope="scope">
<img v-if="scope.row.image" :src="scope.row.image" alt="" style="width: 100px;">
<i v-else class="fal fa-image-polaroid" style="font-size: 115px;"></i>
</template>
</el-table-column>
<el-table-column
prop="name"
label="نام"
width="">
</el-table-column>
<el-table-column
label="قیمت"
width="">
<template slot-scope="scope">
<span v-if="scope.row.price">{{ scope.row.price.toLocaleString() + ' ريال ' }}</span>
<span v-else class="text-danger">بدون قیمت</span>
</template>
</el-table-column>
<el-table-column
label="قیمت با تخفیف"
width="">
<template slot-scope="scope">
<span v-if="scope.row.static_discount">{{ (scope.row.price - (scope.row.price / 100) * scope.row.static_discount).toLocaleString() + ' ريال ' }}</span>
<span v-else class="text-danger">{{ scope.row.price.toLocaleString() + ' ريال ' }}</span>
</template>
</el-table-column>
<el-table-column
label="تعداد موجود"
width="">
<template slot-scope="scope">
<span v-if="scope.row.stock" class="text-success">{{ scope.row.stock }}</span>
<span v-else class="text-danger">اتمام موجودی</span>
</template>
</el-table-column>
<el-table-column
label="درصد تخفیف"
width="">
<template slot-scope="scope">
<span v-if="scope.row.static_discount" class="text-success">{{ scope.row.static_discount + '%' }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column
label="امتیاز مشتریان"
width="">
<template slot-scope="scope">
<span>{{ scope.row.rate }}</span>
<i class="fas fa-star" style="color: goldenrod;"></i>
</template>
</el-table-column>
<el-table-column
label="دسته بندی"
width="">
<template slot-scope="scope">
{{ getFoodCategoryName(scope.row.category) }}
</template>
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="remove(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id" :to="{name: 'admin-branch-foods-food',params:
{food: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="foods.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="foods.limit"
@current-change="handleCurrentChange" :current-page.sync="foods.page" :total="foods.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
const _ = require('lodash');
export default {
data() {
return {
title: 'لیست غذاها',
list_title: 'لیست',
foodCategories: null,
foods: null,
loading : false,
search: {},
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
handleCurrentChange(page) {
if (!_.isEmpty(this.search)) {
this.handleSearch(page);
} else {
this.$router.push({
name: "admin-branch-foods",
query: {
page: page
}
});
}
},
getFoodCategoryName(id) {
return this.foodCategories.filter(item => item._id === id)[0].name
},
remove(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/food/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'غذا با موفقیت حذف شد'
})
this.foods.docs = this.foods.docs.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 403) {
return this.$message({
type: 'error',
message: err.response.data.message
})
} else console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
handleSearch(page) {
this.loading = true;
const data = {
club: this.search.club,
sale: this.search.sale,
name: this.search.name,
category: this.search.category,
branchId: this.$route?.params?.branch
}
this.$axios.post(`/api/admin/food/search?page=${page}`, data, this.axiosConfig)
.then((result) => {
this.foods = result.data;
this.loading = false;
})
.catch(err => {
this.loading = false;
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, query, error, params}) {
try {
const foodCategories = await $axios.get(`/api/public/foodCategories/getAll/${params.branch}`)
const foods = await $axios.get(`/api/admin/food/getAll/${params.branch}?page=${query.page || 1}`)
return {
foodCategories: foodCategories.data,
foods: foods.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+265
View File
@@ -0,0 +1,265 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<!-- <CButton size="sm" color="success" :to="{name: 'admin-foods-food',params:{food: 'new'}}" class="mr-auto">افزودن</CButton>-->
</CustomSubHeader>
<CCard v-if="hasPermission('super-admin')">
<CCardBody>
<CRow>
<CCol col="12" sm="6">
<CCallout color="info">
<small class="text-muted">تعداد مشتری ها</small><br>
<strong class="h4">{{ customers.length }}</strong>
</CCallout>
</CCol>
<CCol col="12" sm="6">
<CCallout color="danger">
<small class="text-muted">تعداد سفارشات</small><br>
<strong class="h4">{{ orders.length }}</strong>
</CCallout>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCol v-if="hasPermission('super-admin')">
<CRow>
<CCol sm="6">
<CCard>
<CCardHeader>
<strong>
<span>تعداد مشتریان بر اساس شغل</span>
</strong>
</CCardHeader>
<CCardBody>
<canvas id="myChart" width="400" height="400"></canvas>
</CCardBody>
</CCard>
</CCol>
</CRow>
</CCol>
<CCard v-if="hasPermission('super-admin')">
<CCardHeader>
<strong>
<span>لیست تخفیف های ویژه امروز مورخ: </span>
<span>{{ jDate(Date.now()) }}</span>
</strong>
</CCardHeader>
<CCardBody>
<el-table
:data="offFoods"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="عکس"
width="">
<template slot-scope="scope">
<img v-if="scope.row.image" :src="scope.row.image" alt="" style="width: 100px;">
<i v-else class="fal fa-image-polaroid" style="font-size: 115px;"></i>
</template>
</el-table-column>
<el-table-column
prop="name"
label="نام"
width="">
</el-table-column>
<el-table-column
label="قیمت"
width="">
<template slot-scope="scope">
<span class="text-success" v-if="scope.row.price">{{ scope.row.price.toLocaleString() + ' ريال ' }}</span>
<span class="text-danger" v-else>بدون قیمت</span>
</template>
</el-table-column>
<el-table-column
label="قیمت با تخفیف"
width="">
<template slot-scope="scope">
<span v-if="scope.row.static_discount">{{ (scope.row.price - (scope.row.price / 100) * scope.row.static_discount).toLocaleString() + ' ريال ' }}</span>
<span v-else class="text-danger">{{ scope.row.price.toLocaleString() + ' ريال ' }}</span>
</template>
</el-table-column>
<el-table-column
label="تعداد موجود"
width="">
<template slot-scope="scope">
<span class="text-success" v-if="scope.row.stock">{{ scope.row.stock }}</span>
<span class="text-danger" v-else>اتمام موجودی</span>
</template>
</el-table-column>
<el-table-column
label="درصد تخفیف"
width="">
<template slot-scope="scope">
<span class="text-success" v-if="scope.row.static_discount">{{ scope.row.static_discount + '%' }}</span>
</template>
</el-table-column>
<el-table-column
label="دسته بندی"
width="">
<template slot-scope="scope">
{{ getFoodCategoryName(scope.row.category) }}
</template>
</el-table-column>
<el-table-column
label="مشاهده"
width="75"
align="center">
<template slot-scope="scope">
<CButton color="success" variant="outline" :key="scope.row._id" :to="{name: 'admin-foods-food',params: {food: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
import moment from "moment-jalaali"
import login from "@/pages/admin/login";
export default {
data() {
return {
title: 'داشبورد',
list_title: 'لیست',
foodCategories: null,
foods: null,
idToken: '',
permissionGranted: false,
customers : null,
orders : null
}
},
computed: {
offFoods() {
return this.foods.filter(item => item.static_discount)
},
branchId(){
return this.$store?.state?.admin?.branchId
}
},
methods: {
jDate(date) {
return moment(date).format("jYYYY/jMM/jDD")
},
getFoodCategoryName(id) {
return this.foodCategories.filter(item => item._id === id)[0].name
},
hasPermission(permission) {
if (this.$auth.loggedIn) return this.$auth.user.permissions.includes(permission)
else return false
},
},
head() {
return {
title: this.title
}
},
async mounted() {
await Notification.requestPermission()
const typePermission = await Notification.permission
this.permissionGranted = typePermission === 'granted'
const getAdmin = this.$auth.$state.user
if (typePermission === 'granted') {
if (getAdmin) {
this.idToken = await this.$fire.messaging.getToken()
await this.$axios.post('/api/admin/addFcmToken', {
fcmToken: this.idToken
})
}
}
if (this.hasPermission('super-admin')){
const counts = {};
this.customers.forEach(function (x) { counts[x.job] = (counts[x.job] || 0) + 1; });
let keys = Object.keys(counts).map(item => item === 'undefined' ? 'نامشخص' : item);
let values = Object.values(counts).map(item => item === 'undefined' ? 'نامشخص' : item);
const CHART_COLORS = {
red: 'rgb(255, 99, 132)',
orange: 'rgb(255, 159, 64)',
yellow: 'rgb(255, 205, 86)',
green: 'rgb(75, 192, 192)',
blue: 'rgb(54, 162, 235)',
purple: 'rgb(153, 102, 255)',
grey: 'rgb(201, 203, 207)'
};
const ctx = document.getElementById('myChart');
const myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: keys,
datasets: [{
// label: '# of Votes',
data: values,
backgroundColor: Object.values(CHART_COLORS),
borderWidth: 1
}]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true
}
}
}
});
}
},
layout: 'admin',
async asyncData({$axios, error , redirect , route}) {
try {
const branchId = route?.params?.branch
const requests = [
$axios.get(`/api/public/foodCategories/getAll/${branchId}`),
$axios.get(`/api/public/foods/getAll/${branchId}`,{progress: false}),
$axios.get(`/api/admin/users/forReport/${branchId}`,{progress: false}),
$axios.get(`/api/admin/order/forReport/${branchId}`,{progress: false})
];
const fetch = await Promise.all(requests);
const [foodCategories, foods, customers, orders] = fetch;
return {
foodCategories: foodCategories.data,
foods: foods.data,
customers: customers.data,
orders: orders.data
}
} catch (e) {
if (e?.response?.status === 401) {
redirect('/admin/login')
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+163
View File
@@ -0,0 +1,163 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-branch-jobs'}">برگشت به صفحه قبل</CButton>
<CButton v-if="$route.params.type === 'new'" size="sm" color="success" class="mr-1" @click="post">افزودن</CButton>
<CButton v-else size="sm" color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="6">
<CCard>
<CCardBody>
<CForm>
<!-- <template v-if="$route.params.profile !== 'new'">-->
<!-- <h4>مشخصات منو</h4>-->
<!-- <el-divider/>-->
<!-- </template>-->
<CRow>
<CCol sm="12">
<CInput
:class="validation.name ? 'err' : null"
label="نام"
:description="validation.name ? validation.name.msg : null"
v-model="job.name"
/>
</CCol>
</CRow>
<CRow>
<CCol s="12" class="mt-3">
<span>ترتیب نمایش در منو</span>
</CCol>
<CCol sm="12" class="err">
<el-select v-model="job.index" filterable style="width: 100%;margin-top: 5px;">
<el-option
v-for="item in 1000"
v-if="!jobs.filter(item2=>Number(item2.index) === item).length"
:key="item + 202"
:value="item"
:label="item"/>
</el-select>
<p v-if="validation.index" class="text-danger" style="margin-top: 5px;">{{ validation.index.msg }}</p>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
data() {
return {
jobs: null,
job: null,
validation: {}
}
},
computed: {
title() {
return this.$route.params.type === 'new' ? 'افزودن شغل' : 'مشاهده شغل'
}
},
methods: {
post() {
this.validation = {}
const data = this.job
this.$axios.post(`/api/admin/job`, data)
.then(response => {
this.$message({
type: 'success',
message: 'شغل با موفقیت ایجاد شد.'
})
this.$router.push({name: 'admin-branch-jobs'})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
},
update() {
this.validation = {}
const data = this.job
this.$axios.put(`/api/admin/job/${this.job._id}`, data)
.then(response => {
this.$message({
type: 'success',
message: 'اطلاعات بروزرسانی شد.'
})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
const jobs = await $axios.get(`/api/public/job`)
if (params.type !== 'new') {
const job = await $axios.get(`/api/admin/job/${params.type}`)
return {
jobs: jobs.data,
job: job.data
}
} else {
return {
jobs: jobs.data,
job: {
name: '',
index: 0
}
}
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
+155
View File
@@ -0,0 +1,155 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{name: 'admin-branch-jobs-type',params:{type: 'new'}}"
class="mr-auto">افزودن
</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="jobs.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="name"
label="نام"
width="">
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="remove(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id" :to="{name: 'admin-branch-jobs-type',params:
{type: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="jobs.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="jobs.limit"
@current-change="handleCurrentChange" :current-page.sync="jobs.page" :total="jobs.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست انواع منوها',
list_title: 'لیست',
jobs: null
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-branch-menu-types",
query: {
page: page
}
});
// }
},
remove(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/job/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'منو با موفقیت حذف شد'
})
this.jobs.docs = this.jobs.docs.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 403) {
return this.$message({
type: 'error',
message: err.response.data.message
})
} else console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios,query , error}) {
try {
const jobs = await $axios.get(`/api/admin/job?page=${query.page || 1}`)
return {
jobs: jobs.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+174
View File
@@ -0,0 +1,174 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-branch-menu-types'}">برگشت به صفحه
قبل</CButton>
<CButton v-if="$route.params.type === 'new'" size="sm" color="success" class="mr-1" @click="post">افزودن</CButton>
<CButton v-else size="sm" color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="6">
<CCard>
<CCardBody>
<CForm>
<!-- <template v-if="$route.params.profile !== 'new'">-->
<!-- <h4>مشخصات منو</h4>-->
<!-- <el-divider/>-->
<!-- </template>-->
<CRow>
<CCol sm="12">
<CInput
:class="validation.name ? 'err' : null"
label="نام"
:description="validation.name ? validation.name.msg : null"
v-model="menuType.name"
/>
</CCol>
<CCol sm="12">
<el-checkbox v-model="menuType.showOnWebSite">در وبسایت نمایش داده شود</el-checkbox>
</CCol>
<CCol sm="12">
<el-checkbox v-model="menuType.isCafeMenu">منوی کافه است</el-checkbox>
</CCol>
</CRow>
<CRow>
<CCol s="12" class="mt-3">
<span>ترتیب نمایش در منو</span>
</CCol>
<CCol sm="12" class="err">
<el-select v-model="menuType.index" filterable style="width: 100%;margin-top: 5px;">
<el-option
v-for="item in 1000"
v-if="!menuTypes.filter(item2=>Number(item2.index) === item).length"
:key="item + 202"
:value="item"
:label="item"/>
</el-select>
<p v-if="validation.index" class="text-danger" style="margin-top: 5px;">{{ validation.index.msg }}</p>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
data() {
return {
menuTypes: null,
menuType: null,
validation: {}
}
},
computed: {
title() {
return this.$route.params.type === 'new' ? 'افزودن منو' : 'مشاهده منو'
}
},
methods: {
post() {
this.validation = {}
const data = this.menuType
data.branchId = this.$route?.params?.branch
this.$axios.post(`/api/admin/menuType`, data)
.then(response => {
this.$message({
type: 'success',
message: 'منو با موفقیت ایجاد شد.'
})
this.$router.push({name: 'admin-branch-menu-types'})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
},
update() {
this.validation = {}
const data = this.menuType
data.branchId = this.$route?.params?.branch
this.$axios.put(`/api/admin/menuType/${this.menuType._id}`, data)
.then(response => {
this.$message({
type: 'success',
message: 'اطلاعات بروزرسانی شد.'
})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
const menuTypes = await $axios.get(`/api/public/menuTypes/getAll/${params?.branch}`)
if (params.type !== 'new') {
const menuType = await $axios.get(`/api/public/menuType/${params.type}`)
return {
menuTypes: menuTypes.data,
menuType: menuType.data
}
} else {
return {
menuTypes: menuTypes.data,
menuType: {
name: '',
showOnWebSite: true,
isCafeMenu: false,
index: 0
}
}
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
+154
View File
@@ -0,0 +1,154 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{name: 'admin-branch-menu-types-type',params:{type: 'new'}}"
class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="menuTypes.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="name"
label="نام"
width="">
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="remove(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id"
:to="{name: 'admin-branch-menu-types-type',params: {type: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="menuTypes.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="menuTypes.limit"
@current-change="handleCurrentChange" :current-page.sync="menuTypes.page" :total="menuTypes.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست انواع منوها',
list_title: 'لیست',
menuTypes: null
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-branch-menu-types",
query: {
page: page
}
});
// }
},
remove(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/menuType/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'منو با موفقیت حذف شد'
})
this.menuTypes.docs = this.menuTypes.docs.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 403) {
return this.$message({
type: 'error',
message: err.response.data.message
})
} else console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios,query , error, params}) {
try {
const menuTypes = await $axios.get(`/api/admin/menuType/getAll/${params?.branch}?page=${query.page || 1}`)
return {
menuTypes: menuTypes.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+182
View File
@@ -0,0 +1,182 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<!-- <CButton size="sm" color="success" class="mr-auto" @click="addInfo">بروزرسانی</CButton>-->
</CustomSubHeader>
<CCard>
<CCardBody>
<CCol lg="6" sm="12">
<el-switch
style="display: flex; direction: ltr!important; justify-content: right"
v-model="notif.multi"
active-color="#13ce66"
inactive-color="#ff4949"
active-text="ارسال عمومی"
inactive-text="ارسال اختصاصی">
</el-switch>
<!-- <el-checkbox v-model="notif.multi" label="ارسال عمومی"/>-->
</CCol>
<CCol class="mt-4" v-if="!notif.multi" lg="6" sm="12">
<el-select
v-model="notif.user_id"
filterable
style="width: 300px;margin-top: 20px;margin-bottom: 10px;">
<el-option
v-for="item in users"
:key="item._id"
:value="item._id"
:label="item.business_code + ' ' + '(' + item.first_name + ' ' + item.last_name + ')'"/>
</el-select>
</CCol>
<CCol class="mt-4" sm="12" lg="6">
<CInput
:class="validation.title ? 'err' : null"
label="عنوان"
:description="validation.title ? validation.title.msg : null"
v-model="notif.title"
/>
</CCol>
<CCol class="mt-4" sm="12" lg="6">
<CTextarea
:class="validation.body ? 'err' : null"
label="متن پیام"
:description="validation.body ? validation.body.msg : null"
v-model="notif.body"
/>
</CCol>
<CCol class="mt-4" sm="12" lg="6">
<el-button type="success" @click="sendNotification">ارسال</el-button>
</CCol>
</CCardBody>
</CCard>
</div>
</template>
<script>
import moment from 'moment-jalaali'
export default {
data() {
return {
title: 'ارسال نوتیفیکیشن',
list_title: 'لیست',
// base data
notif: {
multi: true,
user_id: '',
title: '',
body: '',
},
users: null,
// validation
validation: {}
}
},
methods: {
sendNotification() {
this.validation = {}
this.$axios.post('/api/admin/notification', this.notif)
.then(res => {
this.$message({
type: 'success',
message: 'نوتیفیکیشن با موفقیت ارسال شد'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 403) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 500) {
return this.$message({
type: "error",
message: "مشکلی در ارسال درخواست پیش آمده",
});
}
if (err.response.status === 422) {
this.$message({
type: 'warning',
message: 'پارامترها را بررسی کنید'
})
this.validation = err.response.data.validation;
} else console.log(err.response.data);
});
},
jDate(date) {
return moment(date, 'X').format('jYYYY/jMM/jDD')
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, error , params}) {
try {
const users = await $axios.get(`/api/admin/users/getAll/${params?.branch}`)
return {
users: users.data,
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
<style lang="scss">
.el-button:focus {
outline-color: #39f !important;
}
#map {
width: 100vh;
height: 50vh;
}
.holder-logo {
left: 0;
}
.mapboxgl-ctrl-attrib-button {
display: none;
}
</style>
+775
View File
@@ -0,0 +1,775 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-branch-orders'}">برگشت به صفحه قبل</CButton>
<CButton size="sm" color="danger" class="mr-1" @click="remove">حذف</CButton>
</CustomSubHeader>
<CRow>
<CCol>
<CCard>
<CCardHeader>
<span><b><i class="fal fa-info-circle"></i></b></span>
<span><b>اطلاعات</b></span>
</CCardHeader>
<CCardBody>
<CForm>
<CRow>
<el-card class="box-card">
<CCol class="m-2" sm="12">
<span>شماره سفارش:</span>
<span>{{ order.number }}</span>
</CCol>
<CCol class="m-2" sm="12">
<span>تاریخ ایجاد:</span>
<span>{{ jDate(order.createdOn) }}</span>
</CCol>
<CCol class="m-2" sm="12">
<span>توضیحات سفارش:</span>
<span>{{ order.description }}</span>
</CCol>
<CCol class="m-2" sm="12">
<span>مشتری:</span>
<nuxt-link :to="{name : 'admin-branch-customers-profile' , params : {profile : order.user_id._id}}">
{{ order.user_id.first_name + ' ' + order.user_id.last_name }}
</nuxt-link>
</CCol>
<CCol class="m-2" sm="12">
<span>وضعیت سفارش:</span>
<span>
<b>
<el-tag
size="medium"
:type="showOrderStatus(order.status).type "
effect="dark">
<span>{{ showOrderStatus(order.status).message }}</span>
</el-tag>
</b>
</span>
<el-button type="info" size="medium" class="mr-1" @click="openChangeStatus(order.status)">تغییر وضعیت</el-button>
</CCol>
</el-card>
</CRow>
<CRow>
<el-card class="box-card mt-4">
<CCol v-if="order.orderType === 'online'" class="m-2" sm="12">
<span>مجموع:</span>
<span>{{ order.sum.toLocaleString() + ' ریال' }}</span>
</CCol>
<CCol v-if="order.orderType === 'online'" class="m-2" sm="12">
<span>هزینه ارسال:</span>
<span>{{ order.routePrice.toLocaleString() + ' ریال' }}</span>
</CCol>
<CCol v-if="order.orderType === 'online'" class="m-2" sm="12">
<span>مالیات:</span>
<span>{{ order.tax.toLocaleString() + ' ریال' }}</span>
</CCol>
<CCol v-if="order.orderType === 'online'" class="m-2" sm="12">
<span>تخفیف:</span>
<span>{{ order.percent.toLocaleString() + ' ریال' }}</span>
</CCol>
<CCol class="m-2" sm="12" v-if="order.discount_code">
<span>کد تخفیف:</span>
<span>{{ order.discount_code }}</span>
</CCol>
<CCol class="m-2" sm="12" v-if="order.discount_code">
<span>درصد تخفیف:</span>
<span>{{ order.discount_amount }}</span>
</CCol>
<CCol class="m-2" sm="12">
<span>جمع کل:</span>
<span v-if="order.orderType === 'online'">{{ order.total.toLocaleString() + ' ریال' }}</span>
<span v-else>{{ order.total + ' امتیاز' }}</span>
</CCol>
</el-card>
</CRow>
<CRow>
<el-card class="box-card mt-4">
<CCol class="m-2" v-if="order.payment.length">
<CCardHeader>
<!-- <span><b><i class="fal fal fa-utensils"></i></b></span>-->
<span><b>لیست تراکنشات</b></span>
</CCardHeader>
<CCardBody>
<el-table
:data="order.payment"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="شناسه تراکنش"
width="350"
prop="transactionId"/>
<el-table-column
label="شماره پیگیری"
width=""
prop="refId"/>
<el-table-column
label="نوع تراکنش"
width="">
<template slot-scope="scope">
<el-tag
type="success"
effect="dark">
<span>{{
scope.row.action === 'increaseBag' ? 'افزایش کیف پول' : scope.row.action === 'decreaseBag' ? 'کاهش کیف پول' : 'پرداخت اینترنتی'
}}
</span>
</el-tag>
</template>
</el-table-column>
<el-table-column
label="وضعیت پرداخت"
width="">
<template slot-scope="scope">
<el-tag
:type="scope.row.status === 'paid' ? 'success' : 'danger' "
effect="dark">
<span>{{ scope.row.status === 'paid' ? 'پرداخت موفق' : 'پرداخت ناموفق' }}</span>
</el-tag>
</template>
</el-table-column>
<el-table-column
label="مبلغ"
width="">
<template slot-scope="scope">
{{ scope.row.cost.toLocaleString() + ' ریال' }}
</template>
</el-table-column>
<el-table-column
label="تاریخ و ساعت"
width="">
<template slot-scope="scope">
{{ jDate(scope.row.created_at) }}
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCol>
<CCol class="m-2" v-if="scoreLogs.length">
<CCardHeader>
<!-- <span><b><i class="fal fal fa-utensils"></i></b></span>-->
<span><b>لیست امتیازات استفاده شده</b></span>
</CCardHeader>
<CCardBody>
<el-table
:data="scoreLogs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="نوع"
width="">
کاهش
</el-table-column>
<el-table-column
label="وضعیت پرداخت"
width="">
<template slot-scope="scope">
<el-tag
type="success"
effect="dark">
<span>پرداخت موفق</span>
</el-tag>
</template>
</el-table-column>
<el-table-column
label="امتیاز"
width=""
prop="score"/>
<!-- <el-table-column-->
<!-- label="مبلغ به ازای امتیاز"-->
<!-- width="">-->
<!-- <template slot-scope="scope">-->
<!-- {{ (scope.row.score*pointPrice).toLocaleString() + ' ریال' }}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column
label="تاریخ و ساعت"
width="">
<template slot-scope="scope">
{{ jDate(scope.row.created_at) }}
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCol>
<!-- <CCol class="m-2" sm="12" v-if="order.bag">-->
<!-- <span>مقدار پرداخت شده از کیف پول:</span>-->
<!-- <span>{{ order.discount_amount }}</span>-->
<!-- </CCol>-->
<!-- <CCol class="m-2" sm="12" v-if="order.payment">-->
<!-- <span>شماره پیگیری:</span>-->
<!-- <span v-if="order.payment.length">{{ order.payment[0].refId }}</span>-->
<!-- </CCol>-->
<CCol class="m-2" sm="12">
<span>وضعیت پرداخت:</span>
<span>
<b>
<el-tag
size="medium"
:type="showPaymentStatus(order.paymentStatus).type"
effect="dark">
<span>{{ showPaymentStatus(order.paymentStatus).message }}</span>
</el-tag>
</b>
</span>
<!-- <el-button type="info" size="medium" class="mr-1" @click="openChangePayStatus(order.paymentStatus)">تغییر وضعیت</el-button>-->
</CCol>
</el-card>
</CRow>
</CForm>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<span><b><i class="fal fa-map-marker-alt"></i></b></span>
<span><b>آدرس</b></span>
</CCardHeader>
<CCardBody>
<CForm>
<CRow v-if="order.address">
<el-card class="box-card">
<CCol class="m-2" sm="12">
<span>عنوان:</span>
<span>{{ order.address.title }}</span>
</CCol>
<CCol class="m-2" sm="12">
<span>استان:</span>
<span>{{ order.address.province }}</span>
</CCol>
<CCol class="m-2" sm="12">
<span>شهر:</span>
<span>{{ order.address.city }}</span>
</CCol>
<CCol class="m-2" sm="12">
<span>آدرس:</span>
<span>{{ order.address.address }}</span>
</CCol>
</el-card>
<el-card class="box-card mt-4 text-center">
<template>
<no-ssr>
<mapir class="d-inline-flex" id="map" :min-zoom="12" :max-zoom="18" :zoom="15" logo-position="top-left" :center="order.address.location.coordinates || center" :apiKey="apiKey">
<mapNavigationControl position="top-right"/>
<mapMarker
:coordinates.sync="order.address.location.coordinates || center"
color="red"
:draggable="false"
/>
</mapir>
</no-ssr>
</template>
</el-card>
</CRow>
</CForm>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<span><b><i class="fal fal fa-utensils"></i></b></span>
<span><b>سفارشات</b></span>
</CCardHeader>
<CCardBody>
<el-table
:data="order.order_items"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="عکس"
width="">
<template slot-scope="scope">
<img v-if="scope.row.product_id" :src="scope.row.product_id.image" alt="" style="width: 100px;">
<i v-else class="fal fa-image-polaroid" style="font-size: 115px;"></i>
</template>
</el-table-column>
<el-table-column
label="نام"
width="">
<template slot-scope="scope">
<span v-if="scope.row.product_id">{{ scope.row.product_id.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="order.orderType === 'club' ? 'امتیاز' : 'قیمت'"
width="">
<template slot-scope="scope">
<span v-if="order.orderType === 'club'">
<span v-if="scope.row.point">{{ scope.row.point + ' امتیاز ' }}</span>
<span v-else class="text-danger">-</span>
</span>
<span v-else>
<span v-if="scope.row.price">{{ scope.row.price.toLocaleString() + ' ريال ' }}</span>
<span v-else class="text-danger">-</span>
</span>
</template>
</el-table-column>
<el-table-column
v-if="order.orderType === 'online'"
label="قیمت با تخفیف"
width="">
<template slot-scope="scope">
<span v-if="scope.row.static_discount">{{ (scope.row.price - (scope.row.price / 100) * scope.row.static_discount).toLocaleString() + ' ريال ' }}</span>
<span v-else class="text-danger">{{ scope.row.price.toLocaleString() + ' ريال ' }}</span>
</template>
</el-table-column>
<el-table-column
v-if="order.orderType === 'online'"
label="درصد تخفیف"
width="">
<template slot-scope="scope">
<span v-if="scope.row.static_discount" class="text-success">{{ scope.row.static_discount + '%' }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column
label="تعداد"
width="">
<template slot-scope="scope">
<span v-if="scope.row.quantity" class="text-success">{{ scope.row.quantity }}</span>
</template>
</el-table-column>
<el-table-column
v-if="order.orderType === 'online'"
label="جمع بدون تخفیف"
width="">
<template slot-scope="scope">
<span v-if="scope.row.quantity" class="text-success">{{ (scope.row.price * scope.row.quantity).toLocaleString() + ' ریال' }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column
v-if="order.orderType === 'online'"
label="جمع با تخفیف"
width="">
<template slot-scope="scope">
<span v-if="scope.row.quantity" class="text-success">
{{ ((scope.row.price - (scope.row.price / 100) * scope.row.static_discount) * scope.row.quantity).toLocaleString() + ' ریال' }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<!-- <el-table-column-->
<!-- label="مشتری"-->
<!-- width="">-->
<!-- <template slot-scope="scope">-->
<!-- <nuxt-link v-if="scope.row.user_id" :to="{name: 'admin-customers-profile',params: {profile: scope.row.user_id._id}}">{{ scope.row.user_id.first_name + ' ' + scope.row.user_id.last_name }}</nuxt-link>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="جمع کل"-->
<!-- width="">-->
<!-- <template slot-scope="scope">-->
<!-- <span>{{ scope.row.total.toLocaleString() + ' ریال' }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="وضعیت سفارش"-->
<!-- width="">-->
<!-- <template slot-scope="scope" :v-html="showOrderStatus(scope.row.status)">-->
<!-- <el-tag-->
<!-- :type="showOrderStatus(scope.row.status).type"-->
<!-- effect="dark">-->
<!-- <span>{{ showOrderStatus(scope.row.status).message }}</span>-->
<!-- </el-tag>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="وضعیت پرداخت"-->
<!-- width="">-->
<!-- <template slot-scope="scope">-->
<!-- <el-tag-->
<!-- :type="showPaymentStatus(scope.row.paymentStatus).type"-->
<!-- effect="dark">-->
<!-- <span>{{ showPaymentStatus(scope.row.paymentStatus).message }}</span>-->
<!-- </el-tag>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="مشاهده"-->
<!-- width="110"-->
<!-- align="center">-->
<!-- <template slot-scope="scope">-->
<!-- <CButton color="success" variant="outline" :key="scope.row._id" :to="{name: 'admin-orders-order',params: {order: scope.row._id}}">-->
<!-- <i class="far fa-eye"></i>-->
<!-- </CButton>-->
<!-- </template>-->
<!-- </el-table-column>-->
</el-table>
</CCardBody>
</CCard>
</CCol>
</CRow>
<el-dialog
title="تغییر وضعیت سفارش"
:visible.sync="dialogVisible"
width="50%">
<el-select v-model="status" placeholder="">
<el-option
v-for="item in allStatus"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type="success" class="mr-1" @click="updateStatus">ارسال</el-button>
</el-dialog>
<el-dialog
title="تغییر وضعیت پرداخت"
:visible.sync="dialogVisiblePay"
width="50%">
<el-select v-model="statusPay" placeholder="">
<el-option
v-for="item in allStatusPay"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type="success" class="mr-1" @click="updatePaymentStatus">ارسال</el-button>
</el-dialog>
</div>
</template>
<script>
import axiosUploadProcess from "@/mixins/axiosUploadProcess"
import moment from "moment-jalaali"
let mapirVue = {}
if (process.client)
mapirVue = require('mapir-vue')
export default {
components: {
'mapir': mapirVue.mapir,
'mapMarker': mapirVue.mapMarker,
'mapNavigationControl': mapirVue.mapNavigationControl,
'mapGeolocateControl': mapirVue.mapGeolocateControl,
},
data() {
return {
apiKey: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImRiYjIwMmRhYzAxYzFjNzgwYjgxNWQyZDgyMWNmNmY1Njk0MThhMGE3N2Q1M2Y0OTZkYzQzYTgxMmNmN2U3ZWJjNzI5MjY5YjkxMjA4MTYyIn0.eyJhdWQiOiIxNDk3OSIsImp0aSI6ImRiYjIwMmRhYzAxYzFjNzgwYjgxNWQyZDgyMWNmNmY1Njk0MThhMGE3N2Q1M2Y0OTZkYzQzYTgxMmNmN2U3ZWJjNzI5MjY5YjkxMjA4MTYyIiwiaWF0IjoxNjI3MzI2Mzc0LCJuYmYiOjE2MjczMjYzNzQsImV4cCI6MTYyOTkxODM3NCwic3ViIjoiIiwic2NvcGVzIjpbImJhc2ljIl19.hyKNSy4fmPps6yIdm33Wof-mES9ujh5lmI3VFWyecbkNCm9ATPwsZ9s53A3a1wPJmHfLBXpCcob5NGL-GjZlVfqfRBiReRMr_iniCjUOnqENfFwVEJutxI-xrzVe7PZzOgx1Vr6WwSUHvQ36eJSS1lBlHlqCgwRbkG0hs4YdZsKhzhfYdlAluNw9djjUAMbRWZVL0EluP9CYko4w8tB0KHUZMZYGQcevCfb_3OU9ygHo7B--Z5aTPfm7IK4eP0gHsZ_t857B3tu3ZJB1mkgxc2R9gZUflKqj1ZqkYiR0uMGP-571enXh6pYQLXL2k-gOxLIedCaE6XytxVXhENnotA',
order: null,
status: '',
statusPay: '',
pointPrice : 800,
center: [49.6848857, 34.0821617],
validation: {},
dialogVisible: false,
dialogVisiblePay: false,
allStatus: [
{
label: 'لغو شده',
value: 'canceled'
},
{
label: 'در حال آماده سازی',
value: 'processing'
},
// {
// label: 'ارسال شده',
// value: 'sent'
// },
{
label: 'تحویل داده شده',
value: 'delivered'
}
],
allStatusPay: [
{
label: 'بازگشت مبلغ',
value: 'refund'
},
{
label: 'پرداخت شده',
value: 'paid'
},
{
label: 'پرداخت نشده',
value: 'unpaid'
}
]
}
},
mixins: [axiosUploadProcess],
computed: {
title() {
return 'مشاهده سفارش'
},
scoreLogs() {
return this.order.user_id.scoreLogs.filter(item => item?.order_id === this.order._id && item.forWhat === 'buy' && item.action === 'decrease')
}
},
methods: {
openChangeStatus(status) {
this.status = status
this.dialogVisible = true
},
openChangePayStatus(status) {
this.statusPay = status
this.dialogVisiblePay = true
},
showPaymentStatus(status) {
switch (status) {
case 'unpaid':
return {
type: 'danger',
message: 'پرداخت نشده'
}
case 'paid':
return {
type: 'success',
message: 'پرداخت شده'
}
case 'refund':
return {
type: 'warning',
message: 'برگشت خورده'
}
default :
return {
type: 'info',
message: 'وضعیت نا مشخص'
}
}
},
showOrderStatus(status) {
switch (status) {
case 'canceled':
return {
type: 'danger',
message: 'لغو شده'
}
case 'processing':
return {
type: 'primary',
message: 'در حال آماده سازی'
}
case 'sent':
return {
type: 'warning',
message: 'ارسال شده'
}
case 'delivered':
return {
type: 'success',
message: 'تحویل داده شده'
}
default :
return {
type: 'info',
message: 'وضعیت نا مشخص'
}
}
},
jDate(date) {
return moment(date).format('jYYYY/jMM/jDD HH:mm')
},
updateStatus() {
this.validation = {}
const data = new FormData()
data.append('status', this.status)
this.$axios.put(`/api/admin/order/${this.order._id}`, data, this.axiosConfig)
.then(response => {
this.dialogVisible = false
this.$message({
type: 'success',
message: 'وضعیت سفارش تغییر کرد'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) {
this.validation = err.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(err.response.data.error.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
updatePaymentStatus() {
this.validation = {}
const data = new FormData()
data.append('status', this.statusPay)
this.$axios.put(`/api/admin/payments/${this.order._id}`, data, this.axiosConfig)
.then(response => {
this.dialogVisiblePay = false
this.$message({
type: 'success',
message: 'وضعیت پرداخت تغییر کرد'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) {
this.validation = err.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$message({
type: 'error',
message: err.response.data.message
})
}
})
},
remove() {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/order/${this.order._id}`)
.then(res => {
this.$message({
type: 'success',
message: 'سفارش با موفقیت حذف شد'
})
this.$router.push({
name: "admin-branch-orders"
});
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 403) {
return this.$message({
type: 'error',
message: err.response.data.message
})
} else console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
const order = await $axios.get(`/api/admin/order/${params.order}`)
return {
order: order.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
<style lang="scss">
#map {
width: 100vh;
height: 50vh;
}
.holder-logo {
left: 0;
}
.mapboxgl-ctrl-attrib-button {
display: none;
}
.callout {
border: 0.5px solid rgba(#000, 0.3);
border-right: 6px solid blue;
border-radius: 5px;
padding: 3px 5px;
&.rate {
border-right: 5px solid goldenrod;
i {
color: goldenrod;
font-size: 19px;
}
}
}
</style>
+423
View File
@@ -0,0 +1,423 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-filter"></i>
<span style="color:#000">فیلتر</span>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol md="6">
<CRow style="flex-direction : column;">
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>شماره سفارش</span>
</CCol>
<CCol col="md-9">
<el-input style="width : 100%" placeholder="" v-model="search.number"></el-input>
</CCol>
</CRow>
</CCol>
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>مشتری</span>
</CCol>
<CCol col="md-9">
<el-select filterable clearable style="width : 100%" v-model="search.userId"
placeholder="انتخاب مشتری">
<el-option
v-for="item in users"
:key="item._id"
:value="item._id"
:label="item.business_code + ' ' + '(' + item.first_name + ' ' + item.last_name + ')'"/>
</el-select>
</CCol>
</CRow>
</CCol>
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>تاریخ</span>
</CCol>
<CCol col="md-9">
<date-picker range clearable format="YYYY-MM-DD" display-format="jMMMM jD"
v-model="search.date"></date-picker>
</CCol>
</CRow>
</CCol>
</CRow>
</CCol>
<CCol md="6">
<CRow style="flex-direction : column;">
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>وضعیت سفارش</span>
</CCol>
<CCol col="md-9">
<el-select v-model="search.orderStatus" clearable style="width : 100%">
<el-option v-for="item in allStatus" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</CCol>
</CRow>
</CCol>
<CCol class="mt-3">
<CRow style="align-items: baseline;">
<CCol col="md-3" class="mb-2">
<span>وضعیت پرداخت</span>
</CCol>
<CCol col="md-9">
<el-select v-model="search.paymentStatus" clearable style="width : 100%">
<el-option :key="1" label="پرداخت شده" value="paid">
</el-option>
<el-option :key="2" label="پرداخت نشده" value="unpaid">
</el-option>
<el-option :key="3" label="برگشت خورده" value="refund">
</el-option>
</el-select>
</CCol>
</CRow>
</CCol>
</CRow>
</CCol>
</CRow>
<CRow>
<el-button :loading="loading" @click="handleSearch" size="small"
style="width: auto;margin: 25px auto auto auto;" type="primary"
icon="el-icon-search">
جست و جو
</el-button>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
v-loading="loading"
:data="orders.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<!-- <el-table-column-->
<!-- label="شماره سفارش"-->
<!-- prop="number"-->
<!-- width="">-->
<!-- </el-table-column>-->
<el-table-column
label="مشتری"
min-width="150">
<template slot-scope="scope">
<nuxt-link v-if="scope.row.user_id"
:to="{name: 'admin-branch-customers-profile',params: {profile: scope.row.user_id._id}}">{{
scope.row.user_id.first_name + ' ' + scope.row.user_id.last_name }}
</nuxt-link>
</template>
</el-table-column>
<el-table-column
label="امتیاز"
min-width="70">
<template slot-scope="scope">
<span>{{ scope.row.scorePoint.toLocaleString() }}</span>
<!-- <span>{{ scope.row.orderType === 'club' ? ' امتیاز' : ' ریال'}}</span>-->
</template>
</el-table-column>
<el-table-column
label="ارزش امتیاز"
min-width="110">
<template slot-scope="scope">
<span>{{ scope.row.scoreCost.toLocaleString() + ' ریال'}}</span>
<!-- <span>{{ scope.row.orderType === 'club' ? ' امتیاز' : ' ریال'}}</span>-->
</template>
</el-table-column>
<el-table-column
label="کیف پول"
width="">
<template slot-scope="scope">
<span>{{ scope.row.bagCost.toLocaleString() + ' ریال' }}</span>
<!-- <span>{{ scope.row.orderType === 'club' ? ' امتیاز' : ' ریال'}}</span>-->
</template>
</el-table-column>
<el-table-column
label="پرداخت آنلاین"
min-width="115">
<template slot-scope="scope">
<span v-if="scope.row.payTotal">{{ scope.row.payTotal.toLocaleString() + ' ریال' }}</span>
<span v-else>0 ریال</span>
</template>
</el-table-column>
<el-table-column
label="جمع کل"
min-width="115">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<span>{{ scope.row.total.toLocaleString() }}</span>
<span>{{ scope.row.orderType === 'club' ? ' امتیاز' : ' ریال' }}</span>
<div slot="reference" class="name-wrapper">
<span>{{ scope.row.total.toLocaleString() }}</span>
<span>{{ scope.row.orderType === 'club' ? ' امتیاز' : ' ریال' }}</span>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
label="وضعیت سفارش"
min-width="120">
<template slot-scope="scope" :v-html="showOrderStatus(scope.row.status)">
<el-tag
:type="showOrderStatus(scope.row.status).type"
effect="dark">
<span>{{ showOrderStatus(scope.row.status).message }}</span>
</el-tag>
</template>
</el-table-column>
<!-- <el-table-column-->
<!-- label="وضعیت پرداخت"-->
<!-- width="">-->
<!-- <template slot-scope="scope">-->
<!-- <el-tag-->
<!-- :type="showPaymentStatus(scope.row.paymentStatus).type"-->
<!-- effect="dark">-->
<!-- <span>{{ showPaymentStatus(scope.row.paymentStatus).message }}</span>-->
<!-- </el-tag>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column
label="تاریخ"
min-width="150">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p>{{ jDate(scope.row.createdOn) }}</p>
<div slot="reference" class="name-wrapper">
{{ jDate(scope.row.createdOn) }}
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
label="مشاهده"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="success" variant="outline" :key="scope.row._id"
:to="{name: 'admin-branch-orders-order',params: {order: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="orders.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="orders.limit"
@current-change="handleCurrentChange" :current-page.sync="orders.page" :total="orders.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
import moment from "moment-jalaali";
const _ = require('lodash');
export default {
data() {
return {
title: 'لیست سفارشات',
list_title: 'لیست',
orders: null,
search: {},
users: null,
loading: false,
allStatus: [
{
label: 'لغو شده',
value: 'canceled'
},
{
label: 'در حال آماده سازی',
value: 'processing'
},
{
label: 'ارسال شده',
value: 'sent'
},
{
label: 'تحویل داده شده',
value: 'delivered'
}
]
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
jDate(date) {
return moment(date).format('jYYYY/jMM/jDD HH:mm')
},
showPaymentStatus(status) {
switch (status) {
case 'unpaid':
return {
type: 'danger',
message: 'پرداخت نشده'
}
case 'paid':
return {
type: 'success',
message: 'پرداخت شده'
}
case 'refund':
return {
type: 'warning',
message: 'برگشت خورده'
}
default :
return {
type: 'info',
message: 'وضعیت نا مشخص'
}
}
},
showOrderStatus(status) {
switch (status) {
case 'canceled':
return {
type: 'danger',
message: 'لغو شده'
}
case 'processing':
return {
type: 'primary',
message: 'در حال آماده سازی'
}
case 'sent':
return {
type: 'warning',
message: 'ارسال شده'
}
case 'delivered':
return {
type: 'success',
message: 'تحویل داده شده'
}
default :
return {
type: 'info',
message: 'وضعیت نا مشخص'
}
}
},
handleCurrentChange(page) {
if (!_.isEmpty(this.search)) {
this.handleSearch(page);
} else {
this.$router.push({
name: "admin-branch-orders",
query: {
page: page
}
});
}
},
handleSearch(page) {
this.loading = true;
const data = {
branchId: this.$route?.params?.branch,
number: this.search.number,
userId: this.search.userId,
orderStatus: this.search.orderStatus,
paymentStatus: this.search.paymentStatus,
date: this.search.date,
}
this.$axios.post(`/api/admin/order/search?page=${page}`, data, this.axiosConfig)
.then((result) => {
this.orders = result.data;
this.loading = false;
})
.catch(err => {
this.loading = false;
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, query, error , params}) {
try {
const order = await $axios.get(`/api/admin/order/getAll/${params?.branch}?page=${query.page || 1}`)
const users = await $axios.get(`/api/admin/users/getAll/${params?.branch}`)
return {
orders: order.data,
users: users.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+213
View File
@@ -0,0 +1,213 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-branch-party-sets'}">برگشت به صفحه قبل</CButton>
<CButton v-if="$route.params.set === 'new'" size="sm" color="success" class="mr-1" @click="post">افزودن</CButton>
<CButton v-else size="sm" color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="6">
<CCard>
<CCardBody>
<CForm>
<CRow>
<CCol sm="12">
<CInput
:class="validation.title ? 'err' : null"
label="عنوان"
:description="validation.title ? validation.title.msg : null"
v-model="partySet.title"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.description ? 'err' : null"
label="توضیحات"
:description="validation.description ? validation.description.msg : null"
v-model="partySet.description"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.price ? 'err' : null"
label="قیمت (ريال)"
:description="validation.price ? validation.price.msg : null"
v-model="partySet.price"
/>
</CCol>
<CCol s="12">
<span>ترتیب نمایش در منو</span>
</CCol>
<CCol sm="12" class="err">
<el-select v-model="partySet.index" filterable style="width: 100%;margin-top: 5px;">
<el-option
v-for="item in 1000"
v-if="!partySets.filter(item2=>Number(item2.index) === item).length"
:key="item + 202"
:value="item"
:label="item"/>
</el-select>
<p v-if="validation.index" class="text-danger" style="margin-top: 5px;">{{ validation.index.msg }}</p>
</CCol>
<CCol sm="12" class="mt-3">
<el-checkbox v-model="partySet.active">منو برای مشتریان نمایش داده شود</el-checkbox>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h3>تصویر: (اختیاری)</h3>
<el-divider></el-divider>
<img :src="partySet.image" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="image" @change="imagePreview">
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import axiosUploadProcess from "@/mixins/axiosUploadProcess"
export default {
data() {
return {
partySets: null,
partySet: null,
validation: {}
}
},
mixins: [axiosUploadProcess],
computed: {
title() {
return this.$route.params.food === 'new' ? 'افزودن منوی ویژه مهمانی' : 'مشاهده منوی ویژه'
}
},
methods: {
imagePreview(e) {
this.partySet.image = URL.createObjectURL(e.target.files[0])
},
post() {
this.validation = {}
const data = new FormData()
data.append('title', this.partySet.title)
data.append('description', this.partySet.description)
data.append('active', this.partySet.active)
data.append('price', this.partySet.price)
data.append('index', this.partySet.index)
if (this.$refs.image.files[0]) data.append('image', this.$refs.image.files[0])
this.$axios.post(`/api/admin/partySet`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'منوی ویژه با موفقیت ایجاد شد.'
})
this.$router.push({name: 'admin-branch-party-sets'})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
},
update() {
this.validation = {}
const data = new FormData()
data.append('title', this.partySet.title)
data.append('description', this.partySet.description)
data.append('active', this.partySet.active)
data.append('price', this.partySet.price)
data.append('index', this.partySet.index)
if (this.$refs.image.files[0]) data.append('image', this.$refs.image.files[0])
this.$axios.put(`/api/admin/partySet/${this.partySet._id}`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'اطلاعات بروزرسانی شد.'
})
this.$nuxt.refresh()
this.$refs.image.value = null
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
const partySets = await $axios.get(`/api/public/partySets`)
if (params.set !== 'new') {
const partySet = await $axios.get(`/api/public/partySet/${params.set}`)
return {
partySets: partySets.data,
partySet: partySet.data
}
} else {
return {
partySets: partySets.data,
partySet: {
title: '',
description: '',
price: 0,
active: true,
image: '',
index: 0
}
}
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
+181
View File
@@ -0,0 +1,181 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{name: 'admin-branch-party-sets-set',params:{set: 'new'}}" class="mr-auto">
افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="partySets.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="عکس"
width="">
<template slot-scope="scope">
<img v-if="scope.row.image" :src="scope.row.image" alt="" style="width: 100px;">
<i v-else class="fal fa-image-polaroid" style="font-size: 115px;"></i>
</template>
</el-table-column>
<el-table-column
prop="title"
label="عنوان"
width="">
</el-table-column>
<el-table-column
label="قیمت"
width="">
<template slot-scope="scope">
<span v-if="scope.row.price">{{ scope.row.price.toLocaleString() + ' ريال ' }}</span>
<span v-else class="text-danger">بدون قیمت</span>
</template>
</el-table-column>
<el-table-column
label="وضعیت"
width="">
<template slot-scope="scope">
<span class="text-success" v-if="scope.row.active">فعال</span>
<span class="text-danger" v-else>غیر فعال</span>
</template>
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="remove(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id"
:to="{name: 'admin-branch-party-sets-set',params: {set: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="partySets.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="partySets.limit"
@current-change="handleCurrentChange" :current-page.sync="partySets.page" :total="partySets.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست منوهای ویژه مهمانی',
list_title: 'لیست',
partySets: null
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-branch-party-sets",
query: {
page: page
}
});
// }
},
remove(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/partySet/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'منو با موفقیت حذف شد'
})
this.partySets.docs = this.partySets.docs.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 403) {
return this.$message({
type: 'error',
message: err.response.data.message
})
} else console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, query, error}) {
try {
const partySets = await $axios.get(`/api/admin/partySets?page=${query.page || 1}`)
return {
partySets: partySets.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+254
View File
@@ -0,0 +1,254 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardBody>
<CRow>
<CCol sm="6">
<div>از تاریخ:</div>
<div class="mt-3"><date-picker type="datetime" v-model="startDate" clearable format="YYYY-MM-DD HH:mm" display-format="jYYYY-jMM-jDD HH:mm"/></div>
</CCol>
<CCol sm="6">
<div>تا تاریخ:</div>
<div class="mt-3"><date-picker type="datetime" v-model="endDate" clearable format="YYYY-MM-DD HH:mm" display-format="jYYYY-jMM-jDD HH:mm"/></div>
</CCol>
<CCol sm="12" class="text-center mt-4">
<CButton size="sm" color="success" class="mr-1" @click="getReports">گرفتن گزارش</CButton>
</CCol>
</CRow>
<!-- <div class="d-flex justify-content-center align-items-center">-->
<!-- <span>از تاریخ: </span>-->
<!-- <span><date-picker v-model="date" clearable format="YYYY-MM-DD" display-format="jYYYY-jMM-jDD"/></span>-->
<!-- </div>-->
</CCardBody>
</CCard>
<CCard>
<CCardBody>
<CRow>
<CCol col="12" sm="6">
<CCallout color="info">
<small class="text-muted">جمع کل</small><br>
<strong class="h4">{{ reports.total.toLocaleString() + ' ریال' }}</strong>
</CCallout>
</CCol>
<CCol col="12" sm="6">
<CCallout color="danger">
<small class="text-muted">تعداد سفارشات</small><br>
<strong class="h4">{{ reports.count }}</strong>
</CCallout>
</CCol>
</CRow>
</CCardBody>
</CCard>
<!-- <CCard>-->
<!-- <CCardHeader>-->
<!-- <strong>-->
<!-- <span>نمودار تعداد سفارشات</span>-->
<!-- </strong>-->
<!-- </CCardHeader>-->
<!-- <CCardBody>-->
<!-- <canvas id="myChart" width="400" height="400"></canvas>-->
<!-- </CCardBody>-->
<!-- </CCard>-->
<CCard>
<CCardHeader>
<slot name="header">
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="6">
<div class="mt-3">
<span>
<i class="fal fa-money-bill-wave"></i>
جمع کل:
</span>
<span>{{reports.total.toLocaleString() + ' ریال'}}</span>
</div>
<div class="mt-3">
<span>
<i class="fal fa-money-bill-wave"></i>
جمع پرداخت آنلاین:
</span>
<span>{{reports.payOnline.toLocaleString() + ' ریال'}}</span>
</div>
<div class="mt-3">
<span>
<i class="fal fa-money-bill-wave"></i>
جمع هزینه ارسال:
</span>
<span>{{reports.routePrice.toLocaleString() + ' ریال'}}</span>
</div>
</CCol>
<CCol sm="6">
<div class="mt-3">
<span>
<i class="fal fa-money-bill-wave"></i>
جمع کل مبلغ استفاده شده کیف پول:
</span>
<span>{{reports.bagCost.toLocaleString() + ' ریال'}}</span>
</div>
<div class="mt-3">
<span>
<i class="fal fa-money-bill-wave"></i>
جمع امتیاز استفاده شده:
</span>
<span>{{reports.scorePoint}}</span>
</div>
<div class="mt-3">
<span>
<i class="fal fa-money-bill-wave"></i>
جمع ارزش امتیازات استفاده شده:
</span>
<span>{{reports.scoreCost.toLocaleString() + ' ریال'}}</span>
</div>
</CCol>
</CRow>
</CCardBody>
</CCard>
</div>
</template>
<script>
import moment from 'moment-jalaali'
export default {
data() {
return {
title: 'گزارشات',
list_title: 'گزارش',
// base data
reports: null,
startDate : '',
endDate : '',
// validation
validation: {}
}
},
watch: {
},
computed: {
},
methods: {
jDate(date) {
return moment(date, 'X').format('jYYYY/jMM/jDD')
},
getReports(){
this.validation = {}
const data = {
startDate : this.startDate,
endDate :this.endDate
}
this.$axios.$post(`/api/admin/order/report`, data)
.then(response => {
this.reports = response
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) {
this.validation = err.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$message({
type: 'error',
message: err.response.data.message
})
}
})
}
},
head() {
return {
title: this.title
}
},
// async mounted() {
// const counts = {};
// // this.customers.forEach(function (x) { counts[x.job] = (counts[x.job] || 0) + 1; });
// let keys = [1,2,3,4,5,6,7];
// let values = [10,15,4,5,68,15,1];
//
// const CHART_COLORS = {
// red: 'rgb(255, 99, 132)',
// orange: 'rgb(255, 159, 64)',
// yellow: 'rgb(255, 205, 86)',
// green: 'rgb(75, 192, 192)',
// blue: 'rgb(54, 162, 235)',
// purple: 'rgb(153, 102, 255)',
// grey: 'rgb(201, 203, 207)'
// };
//
// const ctx = document.getElementById('myChart');
// const myChart = new Chart(ctx, {
// type: 'line',
// data: {
// labels: keys,
// datasets: [{
// // label: '# of Votes',
// data: values,
// borderColor: 'rgb(54, 162, 235)',
// fill: false,
// borderWidth: 2
// }]
// },
// options: {
// responsive: true,
// legend: {
// position: 'top',
// },
// scales: {
// y: {
// beginAtZero: true
// }
// }
// }
// });
// },
layout: 'admin',
async asyncData({$axios, query, error, params}) {
try {
const reports = await $axios.$post(`/api/admin/order/report/${params?.branch}`)
return {
reports
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
<style lang="scss">
.el-button:focus {
outline-color: #39f !important;
}
</style>
+508
View File
@@ -0,0 +1,508 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" class="mr-auto" @click="addInfo">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol sm="12">
<CCard>
<CCardBody>
<CCol>
<!-- <h5 style="margin-bottom: 16px"></h5>-->
<CCol sm="12">
<el-checkbox v-model="storeInfo.useSpecialMenu" label="نمایش منو سرآشپز"/>
</CCol>
<CCol class="mt-2" sm="6">
<CInput
v-if="$auth.user.permissions.includes('development')"
:class="validation.updateApp ? 'err' : null"
class="input-direction"
label="ورژن اپلیکیشن"
:description="validation.updateApp ? validation.updateApp.msg : null"
v-model="storeInfo.updateApp"
/>
</CCol>
</CCol>
</CCardBody>
</CCard>
</CCol>
<CCol sm="12">
<CCard>
<CCardBody>
<CCol>
<h5 style="margin-bottom: 16px">پیام مدیر</h5>
<CCol sm="12">
<CInput
:class="validation.message ? 'err' : null"
label="پیام روز"
:description="validation.message ? validation.message.msg : null"
v-model="storeInfo.message"
/>
</CCol>
</CCol>
</CCardBody>
</CCard>
</CCol>
<CCol sm="6">
<CCard>
<CCardBody>
<CCol>
<h5 style="margin-bottom: 16px">اطلاعات عمومی</h5>
<CCol sm="12">
<CTextarea
:class="validation.caption ? 'err' : null"
label="توضیحات"
:description="validation.caption ? validation.caption.msg : null"
v-model="storeInfo.caption"
/>
</CCol>
<CCol sm="12">
<CInput
class="input-direction"
:class="validation.email ? 'err' : null"
label="ایمیل"
:description="validation.email ? validation.email.msg : null"
v-model="storeInfo.email"
/>
</CCol>
<CCol sm="12">
<CInput
class="input-direction"
:class="validation.tel ? 'err' : null"
label="تلفن"
:description="validation.tel ? validation.tel.msg : null"
v-model="storeInfo.tel"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.address ? 'err' : null"
label="آدرس"
:description="validation.address ? validation.address.msg : null"
v-model="storeInfo.address"
/>
</CCol>
</CCol>
</CCardBody>
</CCard>
</CCol>
<CCol sm="6">
<CCard>
<CCardBody>
<CCol>
<h5 style="margin-bottom: 16px">شبکه های اجتماعی</h5>
<CCol sm="12">
<CInput
class="input-direction"
:class="validation.socials ? 'err' : null"
label="واتساپ"
:description="validation.socials ? validation.socials.msg : null"
v-model="storeInfo.socials.whatsaap"
/>
</CCol>
<CCol sm="12">
<CInput
class="input-direction"
:class="validation.socials ? 'err' : null"
label="تویتر"
:description="validation.socials ? validation.socials.msg : null"
v-model="storeInfo.socials.twitter"
/>
</CCol>
<CCol sm="12">
<CInput
class="input-direction"
:class="validation.socials ? 'err' : null"
label="فیس بوک"
:description="validation.socials ? validation.socials.msg : null"
v-model="storeInfo.socials.facebook"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.socials ? 'err' : null"
class="input-direction"
label="اینستاگرام"
:description="validation.socials ? validation.socials.msg : null"
v-model="storeInfo.socials.instagram"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.socials ? 'err' : null"
class="input-direction"
label="گوگل پلاس"
:description="validation.socials ? validation.socials.msg : null"
v-model="storeInfo.socials.googlePlus"
/>
</CCol>
</CCol>
</CCardBody>
</CCard>
</CCol>
</CRow>
<CRow>
<CCard>
<CCardBody>
<h5 style="margin-bottom: 16px">تنظیمات هزینه ارسال و مالیات</h5>
<CCol>
<CCol sm="6">
<el-checkbox v-model="storeInfo.tax" label="گرفتن مالیات از مشتری"/>
</CCol>
<CCol sm="6">
<el-checkbox v-model="storeInfo.shippingType" label="هزینه ارسال ثابت باشد"/>
</CCol>
<CCol sm="6">
<CInput
:class="validation.socials ? 'err' : null"
label="هزینه ارسال به ریال(به ازای هر کیلومتر در صورت ثابت نبودن)"
placeholder=""
:description="validation.shippingCost ? validation.shippingCost.msg : null"
v-model="storeInfo.shippingCost"
/>
</CCol>
<el-divider/>
<CCol sm="6">
<CInput
:class="validation.limitPrice ? 'err' : null"
label="حداقل مبلغ خرید(ریال)"
placeholder=""
:description="validation.limitPrice ? validation.limitPrice.msg : null"
v-model="storeInfo.limitPrice"
/>
</CCol>
</CCol>
</CCardBody>
</CCard>
</CRow>
<CRow>
<CCard>
<CCardBody>
<h5 style="margin-bottom: 16px">تنظیمات امتیازات</h5>
<CCol>
<CRow>
<CCol sm="12">
<el-checkbox class="mb-4" v-model="storeInfo.usePointWhenPay" label="اجازه استفاده از امتیاز هنگام پرداخت"/>
</CCol>
<CCol sm="12" class="mb-3">
<span>به ازای هر</span>
<CInput
type="number"
style="display: inline-block"
:class="validation.totalPricePoint ? 'err' : null"
placeholder="قیمت به ریال وارد شود"
:description="validation.totalPricePoint ? validation.totalPricePoint.msg : null"
v-model="storeInfo.totalPricePoint"
/>
<span><b>ریال</b> خرید مقدار</span>
<CInput
type="number"
style="display: inline-block"
:class="validation.pointForBuy ? 'err' : null"
placeholder=""
:description="validation.pointForBuy ? validation.pointForBuy.msg : null"
v-model="storeInfo.pointForBuy"
/>
<span>امتیاز به مشتری داده شود</span>
</CCol>
<CCol sm="12" class="mb-3">
<span>هر</span>
<CInput
type="number"
style="display: inline-block"
:class="validation.pointForChange ? 'err' : null"
placeholder=""
:description="validation.pointForChange ? validation.pointForChange.msg : null"
v-model="storeInfo.pointForChange"
/>
<span>امتیاز برابر با</span>
<CInput
type="number"
style="display: inline-block"
:class="validation.priceForChange ? 'err' : null"
placeholder=""
:description="validation.priceForChange ? validation.priceForChange.msg : null"
v-model="storeInfo.priceForChange"
/>
<span><b>ریال</b> می باشد</span>
</CCol>
<el-divider/>
<CCol sm="6">
<CInput
:class="validation.userRegistrationScore ? 'err' : null"
label="امتیاز ثبت نام"
placeholder=""
:description="validation.userRegistrationScore ? validation.userRegistrationScore.msg : null"
v-model="storeInfo.userRegistrationScore"
/>
<!-- <CInput-->
<!-- :class="validation.userEmailVerifyScore ? 'err' : null"-->
<!-- label="امتیاز وارد کردن ایمیل"-->
<!-- placeholder=""-->
<!-- :description="validation.userEmailVerifyScore ? validation.userEmailVerifyScore.msg : null"-->
<!-- v-model="storeInfo.userEmailVerifyScore"-->
<!-- />-->
<CInput
:class="validation.pointBirthDate ? 'err' : null"
label="امتیاز تاریخ تولد"
placeholder=""
:description="validation.pointBirthDate ? validation.pointBirthDate.msg : null"
v-model="storeInfo.pointBirthDate"
/>
</CCol>
<CCol sm="6">
<CInput
:class="validation.pointMarriageDate ? 'err' : null"
label="امتیاز تاریخ ازدواج"
placeholder=""
:description="validation.pointMarriageDate ? validation.pointMarriageDate.msg : null"
v-model="storeInfo.pointMarriageDate"
/>
<CInput
:class="validation.invitePoint ? 'err' : null"
label="امتیاز دعوت کردن"
placeholder=""
:description="validation.invitePoint ? validation.invitePoint.msg : null"
v-model="storeInfo.invitePoint"
/>
</CCol>
</CRow>
</CCol>
</CCardBody>
</CCard>
</CRow>
<CRow>
<CCard>
<CCardBody>
<h5 style="margin-bottom: 16px">تنظیمات ساعت کار رستوران</h5>
<CCol>
<CRow>
<CCol sm="6">
<el-checkbox v-model="storeInfo.closeStore" label="فروشگاه تعطیل است"/>
</CCol>
<CRow v-if="!storeInfo.closeStore" class="mb-5">
<CCol sm="6">
<CCol col="md-3" class="mb-2">
<span>ساعت شروع</span>
</CCol>
<CCol col="md-9">
<date-picker type="time" format="HH:mm" display-format="HH:mm" clearable v-model="storeInfo.firstStartTime"></date-picker>
<p class="text-danger" v-if="validation.firstStartTime">
{{ validation.firstStartTime.msg }}
</p>
</CCol>
</CCol>
<CCol sm="6">
<CCol col="md-3" class="mb-2">
<span>ساعت پایان</span>
</CCol>
<CCol col="md-9">
<date-picker type="time" format="HH:mm" display-format="HH:mm" clearable v-model="storeInfo.firstEndTime"></date-picker>
<p class="text-danger" v-if="validation.firstEndTime">
{{ validation.firstEndTime.msg }}
</p>
</CCol>
</CCol>
</CRow>
<CRow v-if="!storeInfo.closeStore">
<el-divider/>
<CCol sm="6">
<CCol col="md-3" class="mb-2">
<span>ساعت شروع</span>
</CCol>
<CCol col="md-9">
<date-picker type="time" format="HH:mm" display-format="HH:mm" clearable v-model="storeInfo.secondStartTime"></date-picker>
<p class="text-danger" v-if="validation.secondStartTime">
{{ validation.secondStartTime.msg }}
</p>
</CCol>
</CCol>
<CCol sm="6">
<CCol col="md-3" class="mb-2">
<span>ساعت پایان</span>
</CCol>
<CCol col="md-9">
<date-picker type="time" format="HH:mm" display-format="HH:mm" clearable v-model="storeInfo.secondEndTime"></date-picker>
<p class="text-danger" v-if="validation.secondEndTime">
{{ validation.secondEndTime.msg }}
</p>
</CCol>
</CCol>
</CRow>
</CRow>
</CCol>
</CCardBody>
</CCard>
</CRow>
<CRow>
<CCard>
<CCardHeader>
<h5>مشخص کردن مکان رستوران روی نقشه</h5>
</CCardHeader>
<CCardBody class="text-center">
<template>
<no-ssr>
<mapir class="d-inline-flex" id="map" :min-zoom="12" :max-zoom="18" :zoom="15" logo-position="top-left" :center="storeInfo.location.coordinates || center" @click="mapOnClick" :apiKey="apiKey">
<mapNavigationControl position="top-right"/>
<mapGeolocateControl position="top-right"/>
<mapMarker
:coordinates.sync="storeInfo.location.coordinates || center"
color="red"
@click="markerOnClick"
:draggable="true"
@dragend="getlatLng"
/>
</mapir>
</no-ssr>
</template>
</CCardBody>
</CCard>
</CRow>
</div>
</template>
<script>
import moment from 'moment-jalaali'
let mapirVue = {}
if (process.client)
mapirVue = require('mapir-vue')
export default {
components: {
'mapir': mapirVue.mapir,
'mapMarker': mapirVue.mapMarker,
'mapNavigationControl': mapirVue.mapNavigationControl,
'mapGeolocateControl': mapirVue.mapGeolocateControl,
},
data() {
return {
apiKey: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImRiYjIwMmRhYzAxYzFjNzgwYjgxNWQyZDgyMWNmNmY1Njk0MThhMGE3N2Q1M2Y0OTZkYzQzYTgxMmNmN2U3ZWJjNzI5MjY5YjkxMjA4MTYyIn0.eyJhdWQiOiIxNDk3OSIsImp0aSI6ImRiYjIwMmRhYzAxYzFjNzgwYjgxNWQyZDgyMWNmNmY1Njk0MThhMGE3N2Q1M2Y0OTZkYzQzYTgxMmNmN2U3ZWJjNzI5MjY5YjkxMjA4MTYyIiwiaWF0IjoxNjI3MzI2Mzc0LCJuYmYiOjE2MjczMjYzNzQsImV4cCI6MTYyOTkxODM3NCwic3ViIjoiIiwic2NvcGVzIjpbImJhc2ljIl19.hyKNSy4fmPps6yIdm33Wof-mES9ujh5lmI3VFWyecbkNCm9ATPwsZ9s53A3a1wPJmHfLBXpCcob5NGL-GjZlVfqfRBiReRMr_iniCjUOnqENfFwVEJutxI-xrzVe7PZzOgx1Vr6WwSUHvQ36eJSS1lBlHlqCgwRbkG0hs4YdZsKhzhfYdlAluNw9djjUAMbRWZVL0EluP9CYko4w8tB0KHUZMZYGQcevCfb_3OU9ygHo7B--Z5aTPfm7IK4eP0gHsZ_t857B3tu3ZJB1mkgxc2R9gZUflKqj1ZqkYiR0uMGP-571enXh6pYQLXL2k-gOxLIedCaE6XytxVXhENnotA',
title: 'اطلاعات فروشگاه',
list_title: 'لیست',
// base data
storeInfo: null,
center: [49.6848857, 34.0821617],
// validation
validation: {}
}
},
methods: {
mapOnClick(e) {
this.storeInfo.location = {
type: 'Point',
coordinates: [e.actualEvent.lngLat.lng , e.actualEvent.lngLat.lat]
}
},
markerOnClick(e) {
},
getlatLng(e) {
},
addInfo() {
this.validation = {}
this.storeInfo.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
this.$axios.post(`/api/admin/store/${this.$route.params.branch}`, this.storeInfo)
.then(res => {
this.$message({
type: 'success',
message: 'تغییرات با موفقیت انجام شد'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 403) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 500) {
return this.$message({
type: "error",
message: "مشکلی در ارسال درخواست پیش آمده",
});
}
if (err.response.status === 422){
this.$message({
type: 'warning',
message: 'پارامترها را بررسی کنید'
})
this.validation = err.response.data.validation;
} else console.log(err.response.data);
});
},
jDate(date) {
return moment(date, 'X').format('jYYYY/jMM/jDD')
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, error , params}) {
try {
const store = await $axios.get(`/api/admin/store/${params.branch}`)
return {
storeInfo: store.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
<style lang="scss">
.el-button:focus {
outline-color: #39f !important;
}
#map {
width: 100vh;
height: 50vh;
}
.holder-logo{
left: 0;
}
.mapboxgl-ctrl-attrib-button{
display: none;
}
</style>
+382
View File
@@ -0,0 +1,382 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-branch-users'}">برگشت به صفحه قبل</CButton>
<CButton v-if="$route.params.profile === 'new'" size="sm" color="success" class="mr-1" @click="post">افزودن</CButton>
<CButton v-else size="sm" color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol>
<CCard>
<CCardBody>
<CRow>
<CCol lg="6">
<CForm>
<template v-if="$route.params.profile !== 'new'">
<h4>مشخصات کاربر</h4>
<el-divider/>
</template>
<CRow>
<CCol sm="12">
<CInput
:class="validation.first_name ? 'err' : null"
label="نام"
:description="validation.first_name ? validation.first_name.msg : null"
v-model="user.first_name"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.last_name ? 'err' : null"
label="نام خانوادگی"
:description="validation.last_name ? validation.last_name.msg : null"
v-model="user.last_name"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.username ? 'err' : null"
label="نام کاربری"
:description="validation.username ? validation.username.msg : null"
v-model="user.username"
/>
<p class="form-err" v-if="validation.username">{{ validation.username.msg }}</p>
</CCol>
<CCol sm="12">
<CInput
:class="validation.mobile_number ? 'err' : null"
label="تلفن همراه"
v-model="user.mobile_number"
:description="validation.mobile_number ? validation.mobile_number.msg : null"
placeholder="اختیاری"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.email ? 'err' : null"
label="ایمیل"
v-model="user.email"
:description="validation.email ? validation.email.msg : null"
placeholder="اختیاری"
/>
</CCol>
<template v-if="$route.params.profile === 'new'">
<CCol sm="12">
<CInput
:class="validation.password ? 'err' : null"
label="کلمه عبور"
type="password"
:description="validation.password ? validation.password.msg : null"
v-model="user.password"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.password_confirmation ? 'err' : null"
label="تکرار کلمه عبور"
type="password"
:description="validation.password_confirmation ? validation.password_confirmation.msg : null"
v-model="user.password_confirmation"
/>
</CCol>
</template>
</CRow>
<el-divider/>
<h6>انتخاب شعبه قابل دسترسی</h6>
<el-select v-model="user.branches" multiple placeholder="انتخاب کنید" style="width: 100%;">
<el-option v-for="item in branches" :key="item._id" :label="item.title" :value="item._id"/>
</el-select>
<p style="margin-top : 5px !important ; color : red" class="form-err" v-if="validation.branches">{{ validation.branches.msg }}</p>
<el-divider/>
<h6>دسترسی های کاربر</h6>
<div class="user-permissions">
<el-tag
class="ml-2 mb-2"
style="cursor: pointer"
v-for="(item,index) in user.permissions"
:key="index + Math.random() + 1"
closable
disable-transitions
@close="removePermission(item)"
>{{ getPermissionName(item) }}
</el-tag>
</div>
</CForm>
</CCol>
<CCol lg="6">
<CForm>
<CRow>
<CCol sm="12">
<h4>عکس پروفایل</h4>
<el-divider/>
<CCol>
<img :src="user.profile_pic" style="width: 100%;max-width: 250px;" alt="">
</CCol>
<input type="file" ref="profile_pic" @change="imagePreview">
<p style="margin-top : 5px !important ;" class="form-err" v-if="validation.profile_pic">{{ validation.profile_pic.msg }}</p>
<p class="mt-3 text-muted">عکس 500*500 باشد. در غیر این صورت اتوماتیک بریده می شود.</p>
<CCol>
</CCol>
<p style="margin-top : 0px !important ; " class="form-err" v-if="validation.password_confirmation">{{ validation.password_confirmation.msg }}</p>
</CCol>
<template v-if="$route.params.profile !== 'new'">
<CCol sm="12" class="mt-5">
<h4>تغییر کلمه عبور</h4>
<el-divider/>
<CInput
:class="validation.password ? 'err' : null"
label="کلمه عبور"
type="password"
:description="validation.password ? validation.password.msg : null"
v-model="newPass.password"
/>
</CCol>
<CCol sm="12">
<CInput
:class="validation.password_confirmation ? 'err' : null"
label="تکرار کلمه عبور"
type="password"
:description="validation.password_confirmation ? validation.password_confirmation.msg : null"
v-model="newPass.password_confirmation"
/>
<CButton size="sm" color="success" class="mr-1 mt-3" @click="updatePassword">تغییر کلمه عبور</CButton>
</CCol>
</template>
</CRow>
</CForm>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardBody>
<h6>لیست کل دسترسی ها</h6>
<div class="permissions">
<el-tag
class="ml-2 mb-2"
style="cursor: pointer"
v-for="(item,index) in permissions"
:key="index + Math.random() + 2"
:type="hasPermission(item.value) ? 'success' : 'primary'"
disable-transitions
@click="addPermission(item.value)"
>{{ item.name }}
</el-tag>
</div>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import axiosUploadProcess from "@/mixins/axiosUploadProcess"
export default {
data() {
return {
user: null,
permissions: null,
branches: null,
newPass: {
password: '',
password_confirmation: ''
},
validation: {}
}
},
mixins: [axiosUploadProcess],
computed: {
title() {
return this.$route.params.profile === 'new' ? 'افزودن کاربر' : 'مشاهده پروفایل کاربر'
}
},
methods: {
getPermissionName(value) {
return this.permissions.filter(item => item.value === value)[0].name
},
addPermission(val) {
if (!this.user.permissions.includes(val)) this.user.permissions.push(val)
else this.$message({
type: 'warning',
message: 'کاربر از قبل این دسترسی را دارد'
})
},
removePermission(val) {
this.user.permissions = this.user.permissions.filter(item => item !== val)
},
hasPermission(val) {
return this.user.permissions.includes(val)
},
imagePreview(e) {
this.user.profile_pic = URL.createObjectURL(e.target.files[0])
},
post() {
this.validation = {}
const data = new FormData()
data.append("first_name", this.user.first_name)
data.append("last_name", this.user.last_name)
data.append("mobile_number", this.user.mobile_number)
data.append("email", this.user.email)
data.append("username", this.user.username)
data.append("permissions", JSON.stringify(this.user.permissions))
data.append("branches", JSON.stringify(this.user.branches))
data.append("password", this.user.password)
data.append("password_confirmation", this.user.password_confirmation)
if (this.$refs.profile_pic.files[0]) data.append("profile_pic", this.$refs.profile_pic.files[0])
this.$axios.post(`/api/admin/admin`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'کاربر با موفقیت ایجاد شد.'
})
this.$router.push({name: 'admin-branch-users'})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
},
update() {
this.validation = {}
const data = new FormData()
data.append("first_name", this.user.first_name)
data.append("last_name", this.user.last_name)
data.append("mobile_number", this.user.mobile_number)
data.append("email", this.user.email)
data.append("username", this.user.username)
data.append("permissions", JSON.stringify(this.user.permissions))
data.append("branches", JSON.stringify(this.user.branches))
data.append("password", this.user.password)
data.append("password_confirmation", this.user.password_confirmation)
if (this.$refs.profile_pic.files[0]) data.append("profile_pic", this.$refs.profile_pic.files[0])
this.$axios.put(`/api/admin/admin/${this.user._id}`, data, this.axiosConfig)
.then(response => {
this.$message({
type: 'success',
message: 'اطلاعات بروزرسانی شد.'
})
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
},
updatePassword() {
this.validation = {}
this.$axios.put(`/api/admin/changeAdminPasswordByAdmin/${this.user._id}`, this.newPass)
.then(response => {
this.$message({
type: 'success',
message: 'کلمه عبور بروزرسانی شد.'
})
this.newPass = {
password: '',
password_confirmation: ''
}
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
const permissions = await $axios.get('/api/admin/permissions')
const branches = await $axios.$get('/api/admin/store/getAll')
if (params.profile !== 'new') {
const user = await $axios.get(`/api/admin/admin/${params.profile}`)
return {
permissions: permissions.data,
user: user.data,
branches
}
} else {
return {
permissions: permissions.data,
branches,
user: {
first_name: '',
last_name: '',
mobile_number: '',
email: '',
username: '',
password: '',
password_confirmation: '',
profile_pic: '',
permissions: [],
branches: []
}
}
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
+161
View File
@@ -0,0 +1,161 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{name: 'admin-branch-users-profile',params:{profile: 'new'}}"
class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="users.docs"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="first_name"
label="نام"
width="">
</el-table-column>
<el-table-column
prop="last_name"
label="نام خانوادگی"
width="">
</el-table-column>
<el-table-column
prop="username"
label="نام کاربری"
width="">
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="deleteUser(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id"
:to="{name: 'admin-branch-users-profile',params: {profile: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="users.totalDocs>5">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="users.limit"
@current-change="handleCurrentChange" :current-page.sync="users.page" :total="users.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست کاربران',
list_title: 'لیست',
users: null
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch:{
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-branch-users",
query: {
page: page
}
});
// }
},
deleteUser(id) {
this.$confirm('کاربر حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/admin/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'کاربر با موفقیت حذف شد'
})
this.users.docs = this.users.docs.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, query , error , params}) {
try {
const users = await $axios.get(`/api/admin/admins/${params?.branch}?page=${query.page}`)
return {
users: users.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
@@ -0,0 +1,108 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-contact-us-messages'}">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<!-- <i class="fal fa-bars"></i>-->
<!-- <span>{{ list_title }}</span>-->
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol md="6">
<CForm class="message">
<CRow>
<CCol sm="12">
<CInput
label="نام"
:value="message.name"
disabled
/>
<CInput
label="شماره تماس"
:value="message.phone"
disabled
/>
<CInput
label="ایمیل"
:value="message.email"
disabled
/>
<CTextarea
label="پیام"
disabled=""
:value="message.message"
rows="10"
/>
<p class="form-err" v-if="validation.caption">{{ validation.caption.msg }}</p>
</CCol>
</CRow>
</CForm>
</CCol>
</CRow>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'مشاهده پیام',
message: null,
validation: {}
}
},
computed: {},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
const message = await $axios.get(`/api/admin/contactUsMessages/${params.message}`)
return {
message: message.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
<style lang="scss">
.message {
input:disabled, textarea:disabled {
color: #000 !important;
}
}
</style>
+143
View File
@@ -0,0 +1,143 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="messages.docs"
style="width: 100%"
:row-class-name="readStatus">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="name"
label="نام"
width="">
</el-table-column>
<el-table-column
prop="email"
label="ایمیل"
width="">
</el-table-column>
<el-table-column
prop="phone"
label="شماره تماس"
width=""
class-name="phoneNumber">
</el-table-column>
<el-table-column
label="مشاهده"
width="80"
align="center">
<template slot-scope="scope">
<CButton color="success" variant="outline" :key="scope.row._id" :to="{name: 'admin-contact-us-messages-message',params: {message: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col" v-if="messages.totalDocs>20">
<CRow alignHorizontal="center" style="padding : 10px">
<el-pagination :hide-on-single-page="true" layout="prev, pager, next" :page-size="messages.limit"
@current-change="handleCurrentChange" :current-page.sync="messages.page" :total="messages.totalDocs">
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست اسلایدهای صفحه اصلی',
list_title: 'لیست',
messages: null,
}
},
computed: {
pageQuery() {
return this.$route.query.page;
}
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
}
},
methods: {
handleCurrentChange(page) {
// if (!_.isEmpty(this.search)) {
// this.handleSearch(page);
// } else {
this.$router.push({
name: "admin-contact-us-messages",
query: {
page: page
}
});
// }
},
readStatus({row, rowIndex}) {
return row.read ? null : 'unread'
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, query, error}) {
try {
const messages = await $axios.get(`/api/admin/contactUsMessages?page=${query.page || 1}`)
return {
messages: messages.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
<style lang="scss">
.phoneNumber {
div {
direction: ltr;
text-align: right;
}
}
.unread {
background: rgba(255, 173, 0, 0.12) !important;
}
</style>
+186
View File
@@ -0,0 +1,186 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-gallery'}">برگشت به صفحه قبل</CButton>
<CButton size="sm" v-if="newPage" color="success" class="mr-1" @click="add">افزودن</CButton>
<CButton size="sm" v-else color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<!-- <i class="fal fa-bars"></i>-->
<!-- <span>{{ list_title }}</span>-->
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol md="6">
<CForm>
<CRow>
<CCol sm="12">
<CTextarea
:class="validation.caption ? 'err' : null"
label="توضیحات"
v-model="image.caption"
rows="10"
/>
<p class="form-err" v-if="validation.caption">{{ validation.caption.msg }}</p>
</CCol>
</CRow>
</CForm>
</CCol>
<CCol md="6">
<h4>تصویر:</h4>
<el-divider/>
<img :src="image.image" alt="" style="width: 100%">
<input type="file" ref="image" @change="preview">
<p class="form-err" style="color: red" v-if="validation.image">{{ validation.image.msg }}</p>
</CCol>
</CRow>
</CCardBody>
</CCard>
</div>
</template>
<script>
import axiosUploadProcess from "@/mixins/axiosUploadProcess"
export default {
data() {
return {
image: null,
validation: {}
}
},
mixins: [axiosUploadProcess],
computed: {
title() {
return this.$route.params.image === 'new' ? 'افزودن تصویر' : 'ویرایش تصویر'
},
newPage() {
return this.$route.params.image === 'new'
}
},
methods: {
add() {
this.validation = {}
const data = new FormData()
data.append('caption', this.image.caption)
data.append('image', this.$refs.image.files[0])
this.$axios.post(`/api/admin/gallery`, data, this.axiosConfig)
.then(response => {
this.$message({
message: 'اسلاید با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push({name: 'admin-gallery'})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) {
this.validation = err.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(err.response.data.error.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
update() {
this.validation = {}
const data = new FormData()
data.append('caption', this.image.caption)
if (this.$refs.image.files[0]) data.append('image', this.$refs.image.files[0])
this.$axios.put(`/api/admin/gallery/${this.image._id}`, data, this.axiosConfig)
.then(response => {
this.$message({
message: 'تغییرات با موفقیت انجام شد.',
type: 'success'
})
this.$refs.image.value = null
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) {
this.validation = err.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(err.response.data.error.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
preview(event) {
this.image.image = URL.createObjectURL(event.target.files[0])
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
if (params.image !== 'new') {
const image = await $axios.get(`/api/public/gallery/${params.image}`)
return {
image: image.data
}
} else {
return {
image: {
caption: '',
image: ''
}
}
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
+127
View File
@@ -0,0 +1,127 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{name: 'admin-gallery-image',params:{image: 'new'}}" class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="gallery"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="تصویر"
width="200">
<template slot-scope="scope">
<img :src="scope.row.thumb" style="width: 100%" alt="">
</template>
</el-table-column>
<el-table-column
prop="shortCaption"
label="توضیحات"
width="">
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="remove(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id" :to="{name: 'admin-gallery-image',params: {image: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست گالری تصاویر',
list_title: 'لیست',
gallery: null,
}
},
computed: {},
methods: {
remove(id) {
this.$confirm('این تصویر حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/gallery/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'تصویر با موفقیت حذف شد'
})
this.gallery = this.gallery.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, error}) {
try {
const gallery = await $axios.get('/api/public/gallery')
return {
gallery: gallery.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+190
View File
@@ -0,0 +1,190 @@
<template>
<div>
<!-- <TheSidebar :branch="branches"/>-->
<CRow class="d-flex flex-row" :class="branches.length ? '' : 'justify-content-center'">
<!-- <CCol class="col-12 col-md-6 col-xl-4">-->
<!-- <CCard class="my-card" @click="addBranch()">-->
<!-- <CCardBody class="d-flex flex-column justify-content-center align-items-center">-->
<!-- <i class="far fa-plus" style="font-size: 28px"></i>-->
<!-- <p class="mt-4">اضافه کردن شعبه</p>-->
<!-- </CCardBody>-->
<!-- </CCard>-->
<!-- </CCol>-->
<CCol class="col-12 col-md-6 col-xl-4" v-for="(item , index) in branches" :key="index">
<CCard class="my-card-dynamic">
<NuxtLink class="link-style" :to="{name : 'admin-branch' , params:{branch: item._id}}">
<CCardBody class="d-flex flex-row align-items-center">
<template>
<!-- <el-image v-if="!item.logo.includes('undefined')" style="width: 100px; height: 100px" :src="$config.apiUrl + item.logo" fit="contain"></el-image>-->
<el-image style="width: 100px; height: 100px;" src="/favicon.png" fit="contain"></el-image>
</template>
<p class="mt-4 mr-4 list-services">{{ item.title }}</p>
</CCardBody>
</NuxtLink>
<CCardFooter class="d-flex justify-content-between align-items-center">
<!-- <NuxtLink v-if="hasPermission('super-admin') || hasPermission('branch')" class="btn btn-info" :to="{name : 'admin-branches-branch' , params:{branch: item._id}}">بروزرسانی</NuxtLink>-->
<div>
<span class="ml-2" v-if="item.active">فعال</span>
<span class="ml-2" v-else>غیر فعال</span>
<span><i class="fad fa-circle" :style="item.active ? 'color: #0ce10c' : 'color: red'"></i></span>
</div>
</CCardFooter>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import moment from "moment-jalaali"
// import login from "@/pages/admin/login";
import axiosUploadProcess from "@/mixins/axiosUploadProcess";
// import HorizontalScroll from 'vue-horizontal-scroll'
// import 'vue-horizontal-scroll/dist/vue-horizontal-scroll.css'
import TheSidebar from "@/components/admin/TheSidebar";
export default {
components: {TheSidebar},
data() {
return {
mark: '',
title: 'داشبورد',
list_title: 'لیست',
branches: [],
loading: false,
validation: {},
}
},
computed: {
colorTheme: {
get() {
return `rgba(${this.hexToRgb(this.branches.colorTheme)} ,1)`
},
set(value) {
this.branches.colorTheme = value
}
},
},
methods: {
jDate(date) {
return moment(date).format("jYYYY/jMM/jDD")
},
imagePreview(e) {
this.branches.logo = URL.createObjectURL(e.target.files[0]);
},
addInfo() {
this.validation = {};
const data = new FormData();
data.append("title", this.branches?.title?.trim());
data.append("caption", this.branches?.caption?.trim());
data.append("email", this.branches.email);
data.append("tel", this.branches.tel);
data.append("location", '[49.67720236907016,34.07654928061605]');
data.append("address", this.branches.address);
data.append("socials", JSON.stringify(this.branches.socials));
data.append("colorTheme", this.branches.colorTheme);
if (this.$refs.logo.files[0]) data.append("logo", this.$refs.logo.files[0]);
this.$axios
.post(`/api/admin/store`, data, this.axiosConfig)
.then((response) => {
this.$message({
type: "success",
message: "اطلاعات شما با موفقیت ثبت شد",
});
window.location.replace('/admin')
})
.catch((err) => {
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 403) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 500) {
return this.$message({
type: "error",
message: "مشکلی در ارسال درخواست پیش آمده",
});
}
if (err.response.status === 422) {
this.validation = err.response.data.validation;
this.$message({
type: 'warning',
message: 'پارامتر هارو بررسی کنید'
})
} else console.log(err.response.data);
});
},
addBranch() {
this.$router.push({name : 'admin-branches-branch' , params:{branch: 'new'}})
},
status(store) {
},
hasPermission(permission) {
if (this.$auth.loggedIn) return this.$auth.user.permissions.includes(permission)
else return false
},
},
head() {
return {
title: this.title,
// link: [
// {rel: 'icon', type: 'image/x-icon', href: '/favicon.png'}
// ],
}
},
layout: 'admin',
mixins: [axiosUploadProcess],
async asyncData({$axios, $store, error}) {
try {
const requests = [
$axios.$get(`/api/admin/store/getAll`),
]
const fetch = await Promise.all(requests)
const [branches] = fetch
return {
branches
}
} catch (e) {
console.log(e.message)
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
+139
View File
@@ -0,0 +1,139 @@
<template>
<CRow class="justify-content-center">
<CCol lg="5">
<CCardGroup>
<CCard class="p-4">
<CCardBody>
<CForm @submit.prevent="doLogin">
<h1 class="text-muted text-center mb-5">پنل مدیریت کافه رستوران برگ</h1>
<CInput
:class="validation.username ? 'err' : null"
placeholder="نام کاربری"
:description="validation.username ? validation.username.msg : null"
autocomplete="username email"
v-model="login.username"
>
<template #prepend-content>
<CIcon name="cil-user"/>
</template>
</CInput>
<div class="butt">
<CInput
:class="validation.password ? 'err' : null"
placeholder="کلمه عبور"
:type="passwordState"
:description="validation.password ? validation.password.msg : null"
autocomplete="curent-password"
v-model="login.password"
>
<template #prepend-content>
<CIcon name="cil-lock-locked"/>
</template>
</CInput>
<i @click="showPass = !showPass" class="far fa-eye"></i>
</div>
<CInputCheckbox label="مرا به خاطر بسپار" @update:checked="val => login.remember_me = val"/>
<p class="text-muted mt-3" style="font-size: 11px;">*درصورتی که گزینه "مرا به خاطر بسپار" را فعال نکنید بعد از 1 ساعت باید دوباره وارد سیستم شوید.</p>
<CRow>
<CCol col="12" class="text-right mt-2">
<CButton color="primary" type="submit" class="px-4">ورود</CButton>
</CCol>
<!-- <CCol col="6" class="text-right">-->
<!-- <CButton color="link" class="px-0">Forgot password?</CButton>-->
<!-- <CButton color="link" class="d-lg-none">Register now!</CButton>-->
<!-- </CCol>-->
</CRow>
</CForm>
</CCardBody>
</CCard>
<!-- <CCard-->
<!-- color="primary"-->
<!-- text-color="white"-->
<!-- class="text-center py-5 d-md-down-none"-->
<!-- body-wrapper>-->
<!-- <CCardBody>-->
<!-- <h2>Sign up</h2>-->
<!-- <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>-->
<!-- <CButton-->
<!-- color="light"-->
<!-- variant="outline"-->
<!-- size="lg"-->
<!-- >-->
<!-- Register Now!-->
<!-- </CButton>-->
<!-- </CCardBody>-->
<!-- </CCard>-->
</CCardGroup>
</CCol>
</CRow>
</template>
<script>
export default {
data() {
return {
showPass: false,
login: {
username: '',
password: '',
remember_me: false
},
validation: {}
}
},
computed: {
passwordState() {
return this.showPass ? "text" : "password"
},
branchId(){
return this.$store?.state?.admin?.branchId
}
},
methods: {
doLogin() {
this.validation = {}
this?.$auth?.logout()
this.$auth.loginWith('local', {
data: this.login
})
.then(response => {
window.location.replace(`/admin`)
})
.catch(err => {
if (err?.response?.status === 422) this.validation = err?.response?.data?.validation
else console.log(err?.message)
})
}
},
layout: 'admin-auth'
}
</script>
<style lang="scss">
.butt {
position: relative;
i {
position: absolute;
left: 7px;
top: 11px;
z-index: 3;
cursor: pointer;
color: rgba(#000, 0.5);
-webkit-transition: 0.2s;
-moz-transition: 0.2s;
-ms-transition: 0.2s;
-o-transition: 0.2s;
transition: 0.2s;
&:hover {
color: #000;
}
}
}
</style>
+186
View File
@@ -0,0 +1,186 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-slider'}">برگشت به صفحه قبل</CButton>
<CButton size="sm" v-if="newPage" color="success" class="mr-1" @click="add">افزودن</CButton>
<CButton size="sm" v-else color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<!-- <i class="fal fa-bars"></i>-->
<!-- <span>{{ list_title }}</span>-->
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol md="6">
<CForm>
<CRow>
<CCol sm="12">
<CTextarea
:class="validation.caption ? 'err' : null"
label="توضیحات"
v-model="slide.caption"
rows="10"
/>
<p class="form-err" v-if="validation.caption">{{ validation.caption.msg }}</p>
</CCol>
</CRow>
</CForm>
</CCol>
<CCol md="6">
<h4>تصویر:</h4>
<el-divider/>
<img :src="slide.image" alt="" style="width: 100%">
<input type="file" ref="image" @change="preview">
<p class="form-err" style="color: red" v-if="validation.image">{{ validation.image.msg }}</p>
</CCol>
</CRow>
</CCardBody>
</CCard>
</div>
</template>
<script>
import axiosUploadProcess from "@/mixins/axiosUploadProcess"
export default {
data() {
return {
slide: null,
validation: {}
}
},
mixins: [axiosUploadProcess],
computed: {
title() {
return this.$route.params.slide === 'new' ? 'افزودن اسلاید' : 'ویرایش اسلاید'
},
newPage() {
return this.$route.params.slide === 'new'
}
},
methods: {
add() {
this.validation = {}
const data = new FormData()
data.append('caption', this.slide.caption)
data.append('image', this.$refs.image.files[0])
this.$axios.post(`/api/admin/slider`, data, this.axiosConfig)
.then(response => {
this.$message({
message: 'اسلاید با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push({name: 'admin-slider'})
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) {
this.validation = err.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(err.response.data.error.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
update() {
this.validation = {}
const data = new FormData()
data.append('caption', this.slide.caption)
if (this.$refs.image.files[0]) data.append('image', this.$refs.image.files[0])
this.$axios.put(`/api/admin/slider/${this.slide._id}`, data, this.axiosConfig)
.then(response => {
this.$message({
message: 'تغییرات با موفقیت انجام شد.',
type: 'success'
})
this.$refs.image.value = null
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
if (err.response.status === 422) {
this.validation = err.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(err.response.data.error.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
preview(event) {
this.slide.image = URL.createObjectURL(event.target.files[0])
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
if (params.slide !== 'new') {
const slide = await $axios.get(`/api/public/slider/${params.slide}`)
return {
slide: slide.data
}
} else {
return {
slide: {
caption: '',
image: ''
}
}
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
+127
View File
@@ -0,0 +1,127 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{name: 'admin-slider-slide',params:{slide: 'new'}}" class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="slides"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="تصویر"
width="200">
<template slot-scope="scope">
<img :src="scope.row.image" style="width: 100%" alt="">
</template>
</el-table-column>
<el-table-column
prop="caption"
label="توضیحات"
width="">
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="remove(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id" :to="{name: 'admin-slider-slide',params: {slide: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست اسلایدهای صفحه اصلی',
list_title: 'لیست',
slides: null,
}
},
computed: {},
methods: {
remove(id) {
this.$confirm('اسلاید حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/slider/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'اسلاید با موفقیت حذف شد'
})
this.slides = this.slides.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, error}) {
try {
const slides = await $axios.get(`/api/public/slider`)
return {
slides: slides.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+128
View File
@@ -0,0 +1,128 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{name: 'admin-subscribers'}">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol>
<CCard>
<CCardBody>
<CRow>
<CCol lg="6">
<CForm>
<template v-if="$route.params.profile !== 'new'">
<h4>اطلاعات فرم</h4>
<el-divider/>
</template>
<CRow>
<CCol sm="12">
<CInput
label="نام"
disabled
:value="subscriber.full_name"
/>
</CCol>
<CCol sm="12">
<CInput
label="تاریخ ازدواج"
disabled
:value="subscriber.birth_date"
/>
</CCol>
<CCol sm="12">
<CInput
label="شماره تماس"
disabled
class="subs_phone_number"
:value="subscriber.mobile"
/>
</CCol>
<CCol sm="12">
<CInput
label="ایمیل"
disabled
:value="subscriber.email"
/>
</CCol>
<CCol sm="12">
<CTextarea
label="آدرس"
disabled
:value="subscriber.address"
/>
</CCol>
</CRow>
</CForm>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
data() {
return {
title: 'اطلاعات فرم',
subscriber: null
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params, error}) {
try {
const subscriber = await $axios.get(`/api/admin/subscriber/${params.subscriber}`)
return {
subscriber: subscriber.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (e?.response?.status === 403) {
error({
status: 403,
message: e?.response?.data?.message,
});
}
if (e?.response?.status === 500) {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات پیش آمده",
});
} else
error({
status: 404,
message: "اطلاعات مورد نظر پیدا نشد",
});
}
}
}
</script>
<style>
.subs_phone_number input{
direction: ltr !important;
text-align: right;
}
</style>
+139
View File
@@ -0,0 +1,139 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="subscribers"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
prop="full_name"
label="نام"
width="">
</el-table-column>
<el-table-column
prop="mobile"
label="شماره تماس"
width=""
class-name="subs_phone_number"
>
</el-table-column>
<el-table-column
prop="email"
label="ایمیل"
width="">
</el-table-column>
<el-table-column
label="ویرایش"
width="110"
align="center">
<template slot-scope="scope">
<CButton color="danger" variant="outline" :key="scope.row._id + Math.random()" @click="remove(scope.row._id)">
<i class="far fa-trash-alt"></i>
</CButton>
<CButton color="success" variant="outline" :key="scope.row._id" :to="{name: 'admin-subscribers-subscriber',params: {subscriber: scope.row._id}}">
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
data() {
return {
title: 'امور مشترکین',
list_title: 'لیست',
subscribers: null
}
},
computed: {},
methods: {
remove(id) {
this.$confirm('حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(async () => {
this.$axios.delete(`/api/admin/subscriber/${id}`)
.then(res => {
this.$message({
type: 'success',
message: 'با موفقیت حذف شد'
})
this.subscribers = this.subscribers.filter(item => item._id !== id)
})
.catch(err => {
if (err.response.status === 401) {
return this.$message({
type: 'error',
message: 'لطفا دوباره وارد سیستم شوید.'
})
}
console.log(err.response.data)
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, error}) {
try {
const subscribers = await $axios.get(`/api/admin/subscribers`)
return {
subscribers: subscribers.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
<style>
.subs_phone_number .cell{
direction: ltr;
text-align: right;
}
</style>
+62
View File
@@ -0,0 +1,62 @@
<template>
<section class="home--page page--container d-flex justify-content-center">
<SiteHeader/>
<div class="d-flex flex-column align-self-center" style="padding: 50px 8px; text-align: center">
<div v-if="$route.query.code" class="text-invite">
<p>بعد از نصب اپلیکیشن از طریق لینک های زیر هنگام ثبت نام کد زیر را در کادر کد دعوت وارد کنید:</p>
<p class="invite-code">
<span @click="copyText()" id="code">{{$route.query.code}}</span>
</p>
</div>
<div class="download-app d-flex flex-column justify-content-center">
<a href="/app/barg.apk">
<img src="/img/Android.png" style="width: 250px" alt="دانلود اندروید">
</a>
<a href="https://anardoni.com/ios/app/M5nS-_TLU">
<img src="/img/anardoni.png" alt="دانلود از اناردونی" style="width: 250px;" />
</a>
<a href="https://iapps.ir/app/برگ-من/995773100">
<img src="https://developer.iapps.ir/images/Iapps-Badge-Black.svg" alt="دانلود از آی اپس" style="width: 250px;" />
</a>
<a href="https://app.bargrestaurant.com">
<img src="/img/pwa.png" alt="pwa" style="width: 250px;" />
</a>
</div>
</div>
<SiteFooter/>
</section>
</template>
<script>
export default {
layout: 'blank',
data() {
return {
payment: null
}
},
computed: {},
watch: {},
methods:{
copyText(){
const copyText = document.getElementById("code");
navigator.clipboard.writeText(copyText.innerText);
this.$message({
message: 'کپی شد!',
type: 'success',
center: false
});
},
back(){
}
},
async asyncData({$axios, query, error}) {
}
}
</script>
<style scoped>
</style>
+62
View File
@@ -0,0 +1,62 @@
<template>
<section class="home--page page--container d-flex justify-content-center">
<SiteHeader/>
<div class="d-flex flex-column align-self-center" style="padding: 50px 8px; text-align: center">
<div v-if="$route.query.code" class="text-invite">
<p>بعد از نصب اپلیکیشن از طریق لینک های زیر هنگام ثبت نام کد زیر را در کادر کد دعوت وارد کنید:</p>
<p class="invite-code">
<span @click="copyText()" id="code">{{$route.query.code}}</span>
</p>
</div>
<div class="download-app d-flex flex-column justify-content-center">
<a href="/app/barg.apk">
<img src="/img/Android.png" style="width: 250px" alt="دانلود اندروید">
</a>
<a href="https://anardoni.com/ios/app/M5nS-_TLU">
<img src="/img/anardoni.png" alt="دانلود از اناردونی" style="width: 250px;" />
</a>
<a href="https://iapps.ir/app/برگ-من/995773100">
<img src="https://developer.iapps.ir/images/Iapps-Badge-Black.svg" alt="دانلود از آی اپس" style="width: 250px;" />
</a>
<a href="https://app.bargrestaurant.com">
<img src="/img/pwa.png" alt="pwa" style="width: 250px;" />
</a>
</div>
</div>
<SiteFooter/>
</section>
</template>
<script>
export default {
layout: 'blank',
data() {
return {
payment: null
}
},
computed: {},
watch: {},
methods:{
copyText(){
const copyText = document.getElementById("code");
navigator.clipboard.writeText(copyText.innerText);
this.$message({
message: 'کپی شد!',
type: 'success',
center: false
});
},
back(){
}
},
async asyncData({$axios, query, error}) {
}
}
</script>
<style scoped>
</style>
+63
View File
@@ -0,0 +1,63 @@
<template>
<section class="home--page page--container d-flex justify-content-center">
<SiteHeader/>
<div class="d-flex flex-column align-self-center" style="padding: 50px 8px; text-align: center">
<div class="download-app d-flex flex-column justify-content-center">
<div class="d-flex align-self-center mb-4" style="width: 100%">
<el-card class="box-card" style="width: 100%; border-radius: 17px">
<div class="row">
<div class="col-12 d-flex justify-content-evenly align-items-center">
<div class="logo-image"><img src="/favicon.png" style="width: 40px" alt=""></div>
<div class="d-flex flex-column justify-content-start" style="text-align: right">
<p style="font-size: 18px; font-weight: bold">BARG CATERING</p>
<p style="font-size: 16px; font-weight: bold" class="mt-2">کترینگ برگ</p>
</div>
</div>
<div class="col-12 mt-3">
<a href="/menu_barg.pdf" class="contactBtnSocial">
<span class="m-1"><i class="fal fa-download"></i></span>
<span>مشاهده منو</span>
</a>
</div>
</div>
</el-card>
</div>
</div>
</div>
<SiteFooter/>
</section>
</template>
<script>
export default {
layout: 'blank',
data() {
return {
payment: null
}
},
computed: {},
watch: {},
methods:{
copyText(){
const copyText = document.getElementById("code");
navigator.clipboard.writeText(copyText.innerText);
this.$message({
message: 'کپی شد!',
type: 'success',
center: false
});
},
back(){
}
},
async asyncData({$axios, query, error}) {
}
}
</script>
<style scoped>
</style>
+136
View File
@@ -0,0 +1,136 @@
<template>
<div class="contact--page page--container">
<div class="s1">
<div class="container">
<div class="row">
<div class="col-12 order-1 order-lg-0 col-lg-8 right">
<h1>نظرات و پیشنهادات</h1>
<p>اگر هر سوالی در رابطه با کافه رستوران برگ دارید:</p>
<form class="form" @submit.prevent="upload">
<div class="form--row" :class="validation.name ? 'err' : null">
<input type="text" v-model="formData.name" placeholder="نام">
<p v-if="validation.name">{{ validation.name.msg }}</p>
</div>
<div class="form--row" :class="validation.phone ? 'err' : null">
<input type="text" v-model="formData.phone" placeholder="شماره تلفن" id="phoneNumber">
<p v-if="validation.phone">{{ validation.phone.msg }}</p>
</div>
<div class="form--row" :class="validation.email ? 'err' : null">
<input type="email" v-model="formData.email" placeholder="ایمیل">
<p v-if="validation.email">{{ validation.email.msg }}</p>
</div>
<div class="form--row" :class="validation.message ? 'err' : null">
<input type="text" v-model="formData.message" placeholder="پیام">
<p v-if="validation.message">{{ validation.message.msg }}</p>
</div>
<button>
<span>ارسال</span>
<IconsLeftArrow/>
</button>
</form>
</div>
<div class="col-12 order-0 order-lg-1 col-lg-4 left">
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-5 mb-lg-0 col-lg">
<IconsLocation/>
<p v-if="storeInfo">{{storeInfo.address}}</p>
</div>
<div class="col-6 col-lg">
<IconsPhone/>
<a v-if="storeInfo" :href="`tel: ${storeInfo.tel}`">{{storeInfo.tel}}</a>
</div>
<div class="col-6 col-lg">
<IconsMail/>
<a v-if="storeInfo" :href="`mailto: ${storeInfo.email}`">{{storeInfo.email}}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
formData: {
name: '',
phone: '',
email: '',
message: ''
},
storeInfo : null,
validation: {}
}
},
methods: {
upload() {
this.validation = {}
const data = this.formData
this.$axios.post('/api/public/contact', data)
.then(response => {
this.$alert(response.data.message, 'ثبت موفق', {
confirmButtonText: 'باشه',
callback: action => {
this.formData = {
name: '',
phone: '',
email: '',
message: ''
}
}
})
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.error.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
}
},
mounted() {
},
created() {
if (process.client) $('body').attr('class', 'contactPage--theme')
},
async asyncData({$axios, error}) {
try {
const storeInfo = await $axios.get('/api/public/storeInfo')
return {
storeInfo: storeInfo.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+29
View File
@@ -0,0 +1,29 @@
<template>
<div class="franchise--page page--container">
<div class="s1">
<div class="container">
<div class="txtBox">
<h1>فرانچایز یا نمایندگی</h1>
<p>قرارداد اعطای نمایندگی (فرانشیز) یک مدل کسب و کار است که طی آن امتیاز، امکان بهره برداری و عرضه علامت تجاری محصول و یا شیوه کسب و کار از سوی دارنده یا امتیاز دهنده درمقابل مال یا نسبتی معینی از سود به طرف دیگر یعنی دریافت کننده امتیاز برای مدت معلوم واگذار میشود.
<br>
کافه رستوران برگ به منظور گسترش رستوران و کافه خود و ایجاد فرصت مناسب برای علاقهمندان به فعالیت در حوزه رستوران داری، حق امتیاز نمایندگی خود را به متقاضیان واجد شرایط واگذار مینماید. این همکاری برای افرادی با تجربه کاری مرتبط، توانایی مدیریتی و روحیه تعاملی و همچنین توانایی تامین ملک (ترجیح به مالکیت )، فعالیت ۱۶ ساعته روزانه در کل ایام سال با سرمایه ای درحدود یک میلیارد تومان جهت خرید تجهیزات مورد نیاز، می تواند مسبب کسب سود مناسب باشد.
</p>
</div>
</div>
</div>
<!-- watermarks -->
<WatermarksBargIcon class="w1"/>
<WatermarksLeafShape1 class="w2"/>
<!-- watermarks -->
</div>
</template>
<script>
export default {
created() {
if (process.client) $('body').attr('class', 'reverse--theme')
}
}
</script>
+53
View File
@@ -0,0 +1,53 @@
<template>
<div class="gallery--page page--container">
<div class="s1">
<div class="container">
<div class="row images">
<div class="col-12 col-sm-6 col-md-4 mb-4" v-for="(image,index) in gallery" :key="image._id">
<a :href="image.image">
<img :src="image.thumb" :alt="image.caption" :title="image.caption"/>
</a>
</div>
</div>
<!-- <div class="indicators">-->
<!-- <div class="active">1</div>-->
<!-- <div>2</div>-->
<!-- <div>3</div>-->
<!-- </div>-->
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
gallery: null
}
},
mounted() {
new SimpleLightbox('.images a')
},
async asyncData({$axios, error}) {
try {
const gallery = await $axios.get('/api/public/gallery')
return {
gallery: gallery.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+69
View File
@@ -0,0 +1,69 @@
<template>
<div class="home--page page--container">
<section class="s1">
<div class="slider" id="slider">
<div class="slide" v-for="slide in slider" :key="slide._id">
<img :src="slide.image" :alt="slide.caption">
<div class="txt">
<p>{{ slide.caption }}</p>
</div>
</div>
</div>
<!-- <div class="btns">-->
<!-- <div class="next"> ></div>-->
<!-- <div class="prev"> <</div>-->
<!-- </div>-->
</section>
<SiteFooter/>
</div>
</template>
<script>
if (process.client) require('slick-carousel')
export default {
data() {
return {
slider: null
}
},
computed: {
preLoader() {
return this.$store.state.global_vars.preLoader
}
},
watch: {
preLoader: function () {
this.slideInterval = setInterval(() => {
if (!this.sliding) $('.slider .btns .next').click()
}, (this.autoSlideTime * 1000) + (this.slideDuration * 1000))
}
},
mounted() {
$(document).ready(() => {
$('#slider').slick({
slidesToShow: 1,
rtl: true,
dots: true,
arrows: true,
autoplay: true,
autoplaySpeed: 6000,
responsive: [
{
breakpoint: 768,
settings: {
arrows: false
}
}
]
})
})
},
async asyncData({$axios}) {
const slider = await $axios.get('/api/public/slider')
return {
slider: slider.data
}
}
}
</script>
+575
View File
@@ -0,0 +1,575 @@
<template>
<div class="menu--page page--container">
<section class="s1 clearfix">
<div class="container">
<div class="mainSectionAnimation">
<livePictureMap set_class="d-none d-md-block imgMap"/>
<div class="shape1">
<WatermarksCircleShape1/>
</div>
<div class="shape2">
<WatermarksLeafShape1/>
</div>
<div class="shape3">
<WatermarksLeafShape1/>
</div>
<img class="mainA" src="~/assets/img/menuPage/livePicture/main.png" alt="">
<img class="kebabA d-none d-md-block" src="~/assets/img/menuPage/livePicture/kabab.png" alt="">
<img class="chickenA d-none d-md-block" src="~/assets/img/menuPage/livePicture/juj.png" alt="">
<img class="fishA d-none d-md-block" src="~/assets/img/menuPage/livePicture/fish.png" alt="">
<div class="caption kebabC d-none d-md-block">
<h3>کباب قفقازی</h3>
<p>فیله گوساله</p>
</div>
<div class="caption chickenC d-none d-md-block">
<h3>جوجه کباب مخصوص</h3>
<p>شنسل مرغ</p>
</div>
<div class="caption fishC d-none d-md-block">
<h3>ماهی قزل آلا سرخ شده</h3>
<p>ماهی قزل آلا بدون استخوان</p>
</div>
<div class="caption sauceC d-none d-md-block">
<h3>سس مخصوص رستوران برگ</h3>
</div>
<div class="tapHere kebabT d-none d-md-block">
<div class="tc1"></div>
<div class="tc2"></div>
</div>
<div class="tapHere chickenT d-none d-md-block">
<div class="tc1"></div>
<div class="tc2"></div>
</div>
<div class="tapHere fishT d-none d-md-block">
<div class="tc1"></div>
<div class="tc2"></div>
</div>
<div class="tapHere sauceT d-none d-md-block">
<div class="tc1"></div>
<div class="tc2"></div>
</div>
</div>
</div>
<div class="mainCaption">
<div class="relativePos">
<div class="bg">
<p>
"ما تلاش میکنیم منوی غذای خودرا به تازگی و سلامتی ممکن، با استفاده از سبزیجات محلی و فصلی نگهداریم.همچنین از مواد غیرطبیعی
و افزودنی های غذایی در طبخ غذا ها استفاده نمیکنیم." </p>
</div>
</div>
</div>
</section>
<section class="s2 section">
<div class="food--menu relativePos">
<div class="container">
<div class="waterMark">
<WatermarksMenuS2W1/>
</div>
<div class="row">
<div class="col-12 col-md-6 menuColumn"
v-for="category in foodCategories"
:key="category._id"
v-if="!category.type.isCafeMenu && category.type.showOnWebSite && categoryFoodLength(category._id)">
<h2 class="menu--heading">{{ '/ ' + category.name + '.' }}</h2>
<div class="f1 lists">
<div class="foodFrame relativePos" v-for="food in menu" v-if="food.category === category._id">
<h3>{{ food.name }}</h3>
<p v-if="food.description">{{ food.description }}</p>
<span v-if="food.price">{{ food.price.toLocaleString() }} ريال</span>
<span v-else>برای قیمت تماس بگیرید</span>
<!-- <img v-if="food.image" :src="food.image" :alt="food.name">-->
</div>
</div>
</div>
</div>
</div>
<div class="bg--shapes">
<div class="circle2">
<WatermarksCircleShape2/>
</div>
<WatermarksLeafShape2 class="leaf2"/>
<WatermarksLeafShape3 class="leaf3"/>
<div class="leaf4">
<WatermarksLeafShape1/>
</div>
<div class="leaf5">
<WatermarksLeafShape1/>
</div>
<WatermarksLeafShape3 class="leaf6"/>
</div>
</div>
<div class="coffee--menu relativePos" v-if="cafeMenuCategories">
<div class="container">
<div class="waterMark">
<WatermarksMenuS2W2/>
</div>
<div class="row">
<div class="col-12 col-md-6 menuColumn"
v-for="category in foodCategories"
:key="category._id"
v-if="category.type.isCafeMenu && category.type.showOnWebSite && categoryFoodLength(category._id)">
<h2 class="menu--heading">{{ '/ ' + category.name + '.' }}</h2>
<div class="c1 lists">
<div class="foodFrame relativePos" v-for="food in menu" :key="food._id" v-if="food.category === category._id">
<h3>{{ food.name }}</h3>
<p v-if="food.description">{{ food.description }}</p>
<span v-if="food.price">{{ food.price.toLocaleString() }} ريال</span>
<span v-else>برای قیمت تماس بگیرید</span>
<img v-if="food.image" :src="food.image" :alt="food.name">
</div>
</div>
</div>
</div>
</div>
<div class="bg--shapes">
<div class="nut1">
<WatermarksCoffeeNut/>
</div>
<WatermarksCoffeeNut class="nut2"/>
<WatermarksLeafShape4 class="leaf1"/>
<WatermarksLeafShape4 class="leaf2"/>
<WatermarksCoffeeCup class="cup"/>
</div>
</div>
</section>
<section class="s3 section">
<WatermarksWave class="wave"/>
<div class="container">
<div class="row">
<div class="col-12 d-lg-none ext--title">
<h2>منوی ویژه مهمانی</h2>
</div>
<div class="col-lg-4 col-12 align-self-start info">
<div class="row">
<div class="col-6">
<div class="top">
<IconsTea/>
<h3>چای رایگان</h3>
<p>چای سبز / چای سیاه</p>
</div>
<div class="bott">
<IconsMenuIcon/>
<h3>قیمت ها برحسب منو</h3>
</div>
</div>
<div class="col-6">
<div class="top">
<IconsClock/>
<h3>از شنبه تا چهارشنبه</h3>
<p>20:00 - 23:30</p>
</div>
<div class="bott">
<IconsTakeAway/>
<h3>به همراه پیک</h3>
</div>
</div>
</div>
<div class="reservation">
<nuxt-link :to="{name: 'reservation'}">رزرو کنید</nuxt-link>
</div>
</div>
<div id="partyMenu" v-if="partySet.length" class="col-lg-8 col-12 party--menu">
<div class="row">
<div class="col-12 d-none d-lg-block title">
<h2>منوی ویژه مهمانی</h2>
</div>
<div class="col-12 offers">
<h3>{{ shownMenu(menuIndex).title }}</h3>
<p>{{ shownMenu(menuIndex).description }}</p>
<span v-if="shownMenu(menuIndex).price">{{ shownMenu(menuIndex).price.toLocaleString() + ' ريال ' }}</span>
<span v-else>برای قیمتتماس بگیرید</span>
</div>
<div class="indicators">
<ul>
<li v-for="(item , index) in partySet"
:key="item._id"
:data-indicator="index"
:class="index === 0 ? 'active' : ''"
@click="menuIndicator(index)"
>
<span>{{ index + 1 }}</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
import Vue from 'vue'
export default {
data() {
return {
foodCategories: null,
menu: null,
partySet: null,
menuIndex: 0
}
},
computed: {
cafeMenuCategories() {
return Boolean(this.foodCategories.filter(item => item.type.isCafeMenu).length)
}
},
methods: {
categoryFoodLength(id) {
return Boolean(this.menu.filter(item => item.category === id).length)
},
menuIndicator(index) {
this.$gsap.timeline()
.to($('.menu--page .s3 .offers'), {
opacity: 0,
duration: 0.1,
onComplete: () => {
this.menuIndex = index
}
})
.to($('.menu--page .s3 .offers'), {opacity: 1, duration: 0.1})
$('.menu--page .s3 .indicators li').removeClass('active')
$(`.menu--page .s3 .indicators li[data-indicator="${index}"]`).addClass('active')
},
shownMenu(index) {
return {
title: this.partySet[index].title,
description: this.partySet[index].description,
price: this.partySet[index].price
}
}
},
mounted() {
// console.log(typeof $(".menu--page .coffee--menu").height())
const renderDelay = 300 // milliseconds
setTimeout(() => {
/////////////////////////////////////////////////////////////////////////
/// global vars
const that = this
const _du = this.$store.state.animations.scroll.duration
const _th = this.$store.state.animations.scroll.triggerHook
const _rev = this.$store.state.animations.scroll.reverse
////////////////////////////////////// cafe menu color theme
// const cafe_theme = this.$scrollmagic.scene({
// triggerElement: '.menu--page .coffee--menu',
// triggerHook: _th,
// duration: () => {
// if (this.$router.history.current.name === 'menu') {
// return $(".menu--page .coffee--menu").height() + 80;
// } else {
// return 0
// }
// },
// reverse: true
// })
// .on('start end', () => {
// if (this.$router.history.current.name === 'menu') {
// $(":root").css({
// '--theme': '#513616',
// '--theme-hover': '#352716',
// '--bg-color': 'rgba(0,0,0,0.4)'
// })
// $('body').addClass('cafe--theme')
// document.querySelector('meta[name="theme-color"]').setAttribute("content", '#513616');
// }
// })
// .on('leave', () => {
// $(":root").css({
// '--theme': '#8DC640',
// '--theme-hover': '#5E943C',
// '--bg-color': '#F2F2F2'
// })
// $('body').removeClass('cafe--theme')
// document.querySelector('meta[name="theme-color"]').setAttribute("content", '#8DC640');
// })
//
// this.$scrollmagic.addScene(cafe_theme)
/////////////////////////////////////// mobile lists
if (window.innerWidth < 768) {
$(".menu--page .s2 .lists").slideUp()
}
$(window).resize(function () {
if (window.innerWidth >= 768) {
$(".menu--page .s2 .lists").slideDown()
} else {
$(".menu--page .s2 .lists").slideUp()
}
})
$('.menu--page .s2 .menu--heading').click(function () {
$(this).next().slideToggle()
})
/////////////////////////////////////// foodFrame images
$(".menu--page .foodFrame h3").hover(function () {
if (window.innerWidth >= 768) {
$(".menu--page .foodFrame h3").mousemove(function (e) {
let left = e.offsetX - 255
let top = e.offsetY - 155
$("~ img", this).css({
display: 'block',
opacity: 1,
top: top,
left: left
})
})
}
}, function () {
if (window.innerWidth >= 768) {
$("~ img", this).css({opacity: 0})
setTimeout(() => {
$("~ img", this).css({display: 'none'})
}, 200)
}
})
/////////////////////////////////////// live picture program
$("#kebab").hover(() => {
this.$gsap.timeline()
.to($(".kebabA"), {opacity: 1, duration: 0})
.to($(".kebabA"), {
scale: 1.2,
y: function () {
if (window.innerWidth > 1400) {
return -50
} else if (window.innerWidth > 1200) {
return -40
} else if (window.innerWidth >= 992) {
return -30
} else if (window.innerWidth >= 768) {
return -25
}
},
x: function () {
if (window.innerWidth > 1400) {
return 30
} else if (window.innerWidth > 1200) {
return 25
} else if (window.innerWidth >= 992) {
return 20
} else if (window.innerWidth >= 768) {
return 15
}
},
duration: 0.3
})
.to($(".kebabC"), {opacity: 1, duration: 0.3}, 0)
.to($(".kebabT"), {opacity: 0, duration: 0.3}, 0)
}, () => {
this.$gsap.timeline()
.to($(".kebabA"), {scale: 1, y: 0, x: 0, duration: 0.3})
.to($(".kebabA"), {opacity: 0, duration: 0})
.to($(".kebabC"), {opacity: 0, duration: 0.3}, 0)
.to($(".kebabT"), {opacity: 1, duration: 0.3}, 0)
})
$("#fish").hover(() => {
this.$gsap.timeline()
// .to($(".fishA"),0,{opacity:1})
// .to($(".fishA"),0.3,{scale: 1.5,y: -120,x: -60})
.to($(".fishC"), {opacity: 1, duration: 0.3}, 0)
.to($(".fishT"), {opacity: 0, duration: 0.3}, 0)
}, () => {
this.$gsap.timeline()
// .to($(".fishA"),0.3,{scale: 1,y:0,x: 0})
// .to($(".fishA"),0,{opacity:0})
.to($(".fishC"), {opacity: 0, duration: 0.3}, 0)
.to($(".fishT"), {opacity: 1, duration: 0.3}, 0)
})
$("#chicken").hover(() => {
this.$gsap.timeline()
.to($(".chickenA"), {opacity: 1, duration: 0})
.to($(".chickenA"), {
scale: 1.2,
y: function () {
if (window.innerWidth > 1400) {
return 45
} else if (window.innerWidth > 1200) {
return 35
} else if (window.innerWidth >= 992) {
return 30
} else if (window.innerWidth >= 768) {
return 20
}
},
x: function () {
if (window.innerWidth > 1400) {
return -35
} else if (window.innerWidth > 1200) {
return -30
} else if (window.innerWidth >= 992) {
return -25
} else if (window.innerWidth >= 768) {
return -20
}
},
duration: 0.3
})
.to($(".chickenC"), {opacity: 1, duration: 0.3}, 0)
.to($(".chickenT"), {opacity: 0, duration: 0.3}, 0)
}, () => {
this.$gsap.timeline()
.to($(".chickenA"), {scale: 1, y: 0, x: 0, duration: 0.3})
.to($(".chickenA"), {opacity: 0, duration: 0})
.to($(".chickenC"), {opacity: 0, duration: 0.3}, 0)
.to($(".chickenT"), {opacity: 1, duration: 0.3}, 0)
})
$("#sauce").hover(() => {
this.$gsap.timeline()
.to($(".sauceC"), {opacity: 1, duration: 0.3}, 0)
.to($(".sauceT"), {opacity: 0, duration: 0.3}, 0)
}, () => {
this.$gsap.timeline()
.to($(".sauceC"), {opacity: 0, duration: 0.3}, 0)
.to($(".sauceT"), {opacity: 1, duration: 0.3}, 0)
})
/////// tap animation
const tapAnim = this.$gsap.timeline({repeat: -1})
.to($(".tc1"), {scale: 1.3, opacity: 0.4, duration: 0.3, stagger: 2.5}, 0)
.to($(".tc1"), {scale: 0.5, opacity: 0.4, duration: 0.4, stagger: 2.5}, 0.3)
.to($(".tc2"), {scale: 2, opacity: 0.3, duration: 0.8, stagger: 2.5}, 0)
.to($(".tc2"), {scale: 0.8, opacity: 0.3, duration: 0.9, stagger: 2.5}, 0.8)
.to($(".tc1"), {opacity: 0, duration: 0.3, stagger: 2.5}, 1.2)
.to($(".tc2"), {opacity: 0, duration: 0.3, stagger: 2.5}, 1.2)
/////////////////////////////////////// scroll animations
////////////////////////////////////////////////////
const globalPageAnimationVars = {
opacity: 0,
y: 10,
duration: _du
}
/////////////// watermarks animation
const watermarks = $('.menu--page .waterMark')
const watermarksTl = []
const watermarksScene = []
for (let i = 0; i < watermarks.length; i++) {
watermarksTl[i] = this.$gsap.from($(watermarks[i]), globalPageAnimationVars).pause()
watermarksScene[i] = this.$scrollmagic.scene({
triggerElement: watermarks[i],
triggerHook: _th
}).on('progress', e => {
if (e.progress === 1) watermarksTl[i].play()
})
this.$scrollmagic.addScene(watermarksScene[i])
}
/////////////// foodFrames animation
const foodFrames = $('.menu--page .foodFrame')
const foodFrameTl = []
const foodFrameScene = ['0']
for (let i = 0; i < foodFrames.length; i++) {
foodFrameTl[i] = this.$gsap.from($(foodFrames[i]), globalPageAnimationVars).pause()
foodFrameScene[i] = this.$scrollmagic.scene({
triggerElement: foodFrames[i],
triggerHook: _th
}).on('progress', e => {
if (e.progress === 1) foodFrameTl[i].play()
})
this.$scrollmagic.addScene(foodFrameScene[i])
}
/////////////// menu heading animation
const menuHeadings = $('.menu--page .menu--heading')
const menuHeadingTl = []
const menuHeadingScene = []
for (let i = 0; i < menuHeadings.length; i++) {
menuHeadingTl[i] = this.$gsap.from($(menuHeadings[i]), globalPageAnimationVars).pause()
menuHeadingScene[i] = this.$scrollmagic.scene({
triggerElement: menuHeadings[i],
triggerHook: _th
}).on('progress', e => {
if (e.progress === 1) menuHeadingTl[i].play()
})
this.$scrollmagic.addScene(menuHeadingScene[i])
}
/////////////// watermark shapes animations
const watermarkShapes = $('.menu--page .bg--shapes').children()
const watermarkShapesTl = []
const watermarkShapesScene = []
for (let i = 0; i < watermarkShapes.length; i++) {
watermarkShapesTl[i] = this.$gsap.from($(watermarkShapes[i]), {opacity: 0, duration: _du, ease: 'power0'}).pause()
watermarkShapesScene[i] = this.$scrollmagic.scene({
triggerElement: watermarkShapes[i],
triggerHook: 0.7
})
.on('progress', e => {
if (e.progress > 0) watermarkShapesTl[i].play()
})
this.$scrollmagic.addScene(watermarkShapesScene[i])
}
/////////////// party set animation
const partySetAnim = this.$gsap.timeline({paused: true})
.from($(".menu--page .s3 .wave"), {y: 30, opacity: 0, duration: 0.2, ease: 'power2.inOut'})
.from($(".menu--page .s3 .info"), {x: 500, opacity: 0, duration: 0.4, ease: 'power2.inOut'})
.from($(".menu--page .s3 .title,.menu--page .s3 .ext--title"), {x: -500, opacity: 0, duration: 0.4, ease: 'power2.inOut'}, 0)
.from($(".menu--page .s3 .offers").children(), {y: 30, opacity: 0, duration: 0.3, stagger: 0.08, ease: 'power1.inOut'})
.from($(".menu--page .s3 .indicators"), {y: 30, opacity: 0, duration: 0.3, ease: "back.inOut(10)"}, '-=0.2')
const partySetScene = this.$scrollmagic.scene({
triggerElement: '.menu--page .s3 .info',
triggerHook: 1
}).on('start', () => {
partySetAnim.play()
})
this.$scrollmagic.addScene(partySetScene)
/////////////////////////////////////////////////////////////////////////
}, renderDelay)
},
async asyncData({$axios, store , error}) {
try {
const foodCategories = await $axios.get(`/api/public/foodCategories/getAll`)
const menu = await $axios.get('/api/public/foods/allWebsite')
const partySet = await $axios.get('/api/public/partySets')
return {
foodCategories: foodCategories.data,
menu: menu.data,
partySet: partySet.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
+73
View File
@@ -0,0 +1,73 @@
<template>
<div class="page--container d-flex justify-content-center bg-payResult">
<el-card class="d-flex align-self-center justify-content-center w-100" style="padding: 85px 40px; text-align: center">
<div class="row">
<i v-if="payment.status" class="fal fa-check-circle" style="font-size: 200px; color: #8DC640"></i>
<i v-else class="fal fa-times-circle" style="font-size: 200px; color: red"></i>
</div>
<div class="row mt-4">
<h2>{{ payment.message }}</h2>
</div>
<div v-if="payment.status" class="row mt-4">
<h3 class="mb-3" style="line-height: 1.5;">نوش جانتان از اعتماد و خرید شما متشکریم</h3>
<h3> مجموعه برگ</h3>
</div>
<div v-if="payment.refId" class="row mt-4">
<p class="mb-3">{{ `شماره پیگیری پرداخت شما` }}</p>
<p>{{ payment.refId }}</p>
</div>
<div class="row mt-4">
<template v-if="payment.fromWhere === 'app'">
<a v-if="payment.status" class="btn btn-success-result" href="barg://route/order/true">برگشت</a>
<a v-else class="btn btn-failed-result" href="barg://route/drawer/false">برگشت</a>
</template>
<template v-else>
<a v-if="payment.status" class="btn btn-success-result" href="https://app.bargrestaurant.com/order">برگشت</a>
<a v-else class="btn btn-failed-result" href="https://app.bargrestaurant.com/home">برگشت</a>
</template>
</div>
</el-card>
</div>
</template>
<script>
export default {
layout: 'blank',
data() {
return {
payment: null
}
},
computed: {},
watch: {},
methods: {
back() {
}
},
async asyncData({$axios, query, error}) {
try {
const pay = await $axios.get(`/api/public/order/responsePayment?Authority=${query.Authority}&Status=${query.Status}`)
return {
payment: pay.data
}
} catch (e) {
if (e?.response?.status === 401) {
error({
status: 401,
message: 'شما اجازه دسترسی به این صفحه را ندارید لطفا دوباره وارد شوید'
})
} else {
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
}
}
}
</script>
<style scoped>
</style>
+104
View File
@@ -0,0 +1,104 @@
<template>
<section class="home--page page--container d-flex justify-content-center">
<SiteHeader/>
<div class="d-flex flex-column align-self-center mt-4" style="padding: 50px 8px; text-align: center">
<!---------------------- card header -------------------------->
<div class="d-flex align-self-center mb-4" style="width: 100%">
<el-card class="box-card" style="width: 100%; border-radius: 17px">
<div class="row">
<div class="col-12 d-flex justify-content-evenly align-items-center">
<div class="logo-image"><img src="/favicon.png" style="width: 40px" alt=""></div>
<div class="d-flex flex-column justify-content-start" style="text-align: right">
<p style="font-size: 18px; font-weight: bold">BARG RESTAURANT</p>
<p style="font-size: 16px; font-weight: bold" class="mt-2">رستوران برگ</p>
</div>
</div>
<div class="col-12 mt-3">
<nuxt-link to="/contact" class="contactBtnSocial">
<span class="m-1"><i class="fal fa-phone"></i></span>
<span>اطلاعات تماس</span>
</nuxt-link>
</div>
</div>
</el-card>
</div>
<!---------------------- socials -------------------------->
<div class="download-app d-flex flex-column justify-content-center" style="width: 100%">
<el-card class="box-card" style="width: 100%; border-radius: 17px">
<a href="https://instagram.com/barg.cafe.restaurant?igshid=ZnNkYzU1NndyZGxi" target="_blank"
class="d-flex align-items-center social-links">
<div class="icon-social-link"><i class="fab fa-instagram"></i></div>
<div class="d-flex flex-column" style="text-align: right">
<p class="social-title">اینستاگرام رستوران</p>
<p class="mt-3">ما را دنبال کنید</p>
</div>
</a>
</el-card>
<el-card class="box-card mt-3" style="width: 100%; border-radius: 17px">
<a href="https://instagram.com/barg.jordan?igshid=MXE2OXkzMmtmc2oyeA=="
target="_blank" class="d-flex align-items-center social-links">
<div class="icon-social-link"><i class="fab fa-instagram"></i></div>
<div class="d-flex flex-column" style="text-align: right">
<p class="social-title">اینستاگرام کترینگ</p>
<p class="mt-3">ما را دنبال کنید</p>
</div>
</a>
</el-card>
<el-card class="box-card mt-3" style="width: 100%; border-radius: 17px">
<a href="/applanding" class="d-flex align-items-center social-links">
<div class="icon-social-link"><i class="fal fa-mobile"></i></div>
<div class="d-flex flex-column" style="text-align: right">
<p class="social-title">دانلود اپلیکیشن</p>
<p class="mt-3">برای استفاده راحت تر، اپلیکیشن برگ را دانلود کنید</p>
</div>
</a>
</el-card>
<el-card class="box-card mt-3 mb-5" style="width: 100%; border-radius: 17px">
<a href="/cateringmenu" class="d-flex align-items-center social-links">
<div class="icon-social-link"><i class="fal fa-book-open"></i></div>
<div class="d-flex flex-column" style="text-align: right">
<p class="social-title">مشاهده منو کترینگ</p>
<p class="mt-3">برای مشاهده ضربه بزنید</p>
</div>
</a>
</el-card>
</div>
</div>
<SiteFooter/>
</section>
</template>
<script>
export default {
layout: 'blank',
data() {
return {
payment: null
}
},
computed: {},
watch: {},
methods:{
copyText(){
const copyText = document.getElementById("code");
navigator.clipboard.writeText(copyText.innerText);
this.$message({
message: 'کپی شد!',
type: 'success',
center: false
});
},
back(){
}
},
async asyncData({$axios, query, error}) {
}
}
</script>
<style scoped>
</style>
+5
View File
@@ -0,0 +1,5 @@
<template>
<div class="reservation--page">
<h1>این امکان فعلا موجود نمیباشد.</h1>
</div>
</template>
+19
View File
@@ -0,0 +1,19 @@
<template>
<div class="socialR--page page--container">
<div class="s1">
<div class="container">
<div class="txtBox">
<h1>قبال پرسنل , همشهریان , محیط زیست </h1>
<p>مسئولیت اجتماعی شرکتها یا مسئولیت اجتماعی سازمانها از جستارهای «اخلاق کسب و کار» است که به نقش شرکتها درحوزه اجتماع میپردازد. مسئولیت اجتماعی شرکتی مجموعه وظایف و تعهداتی است که شرکت بایستی در جهت حفظ، مراقبت و کمک به جامعهای که در آن فعالیت میکند، انجام دهد.
<br>
مسئولیت اجتماعی شرکتها در پیوند با مسئولیت شرکت در برابر جامعه، انسانها، و محیطی است که شرکت در آن فعالیت میکند و این مسئولیت از جستارهای اقتصادی و مالی فراتر میرود. مسئولیت اجتماعی شرکت در تعریفی روشنتر این گونه تعریف شدهاست: «مسئولیت اجتماعی شرکت فعالیتهایی است که پیش برنده سود و منفعت اجتماعی بوده و فراتر از منافع سازمان و آن چیزی است که قانون بایسته میدارد»
<br>
مطالبه از سازمانها برای «مسئولانه عمل کردن» در قبال جامعه، موضوعی است که با گسترش روزافزون اثرگذاری آنها بر محورهای تشکیل دهنده توسعه پایدار یعنی «اقتصاد»، «جامعه» و «محیطزیست»، در دهههای پایانی قرن بیستم شدت گرفته و منجر به این شدهاست که مفهومی به نام مسئولیت اجتماعی سازمانها یا CSR در دنیای مدیریت ظهور پیدا کند. CSR در یک تعریف ساده، یعنی اینکه سازمانها در مقابل جامعه ای که در آن فعالیت می کنند مسئول هستند؛ چرا که از منابع انسانی، طبیعی و اقتصادی آن استفاده می کنند. بر خلاف نگاه سنتی به مدیریت و کسب و کار، سازمانها دیگر فقط در مقابل سهامداران شان مسئول نیستند و نباید فقط به افزایش سود کوتاه مدت سهامداران خود بیندیشند. بدین ترتیب انتظار می رود سازمانها که در ارتباط با ذینفعان دیگری نیز هستند، خواستههای مشروع آنها را هم مورد لحاظ قرار دهند.
<br>
در هر کسب و کاری و از جمله شرکتهایی که برای تولید ثروت و کسب و کار ایجاد شدهاند باید صد در صد مسئولیت تمام کارهای خود که جنبه اجتماعی دارند را به عهده بگیرند. این مسئولیت در کسب و کار معمولی بر عهده صاحب آن و در شرکتها بر عهده هیئت مدیره و مدیر عامل آن شرکت است. همچنین مسئولیت اجتماعی یا تعهدات اجتماعی شرکت را به چهار جنبه ی مسئولیت اجتماعی زیست محیطی، سرمایه انسانی ، خیرخواهانه و اخلاقی تقسیم کرده اند که مهم ترین آن ها مسئولیت اجتماعی زیست محیطی] است.
</p>
</div>
</div>
</div>
</div>
</template>
+147
View File
@@ -0,0 +1,147 @@
<template>
<div class="subs--page page--container">
<section class="s1">
<div class="subscription--box clearfix relativePos">
<div class="letters l1">
<IconsLetters/>
</div>
<div class="letters l2">
<IconsLetters/>
</div>
<IconsSubsAfairIcon class="subs--icon"/>
<form class="form" @submit.prevent="upload">
<div class="container-fluid">
<div class="row">
<div class="col-12 col-lg-6 form--row" :class="validation.full_name ? 'err' : null">
<label for="name">نام و نام خانوادگی:</label>
<input type="text" v-model="formData.full_name" id="name">
<p v-if="validation.full_name">{{ validation.full_name.msg }}</p>
</div>
<div class="col-12 col-lg-6 form--row" :class="validation.birth_date ? 'err' : null">
<label for="birthDate">تاریخ تولد:</label>
<input type="text" v-model="formData.birth_date" id="birthDate">
<p v-if="validation.birth_date">{{ validation.birth_date.msg }}</p>
</div>
<div class="col-12 col-lg-6 form--row" :class="validation.job ? 'err' : null">
<label for="job">شغل:</label>
<input type="text" v-model="formData.job" placeholder="اختیاری" id="job">
<p v-if="validation.job">{{ validation.job.msg }}</p>
</div>
<div class="col-12 col-lg-6 form--row" :class="validation.marrage_date ? 'err' : null">
<label for="marrageDate">سالگرد ازدواج:</label>
<input type="text" v-model="formData.marrage_date" placeholder="اختیاری" id="marrageDate">
<p v-if="validation.marrage_date">{{ validation.marrage_date.msg }}</p>
</div>
<div class="col-12 col-lg-6 form--row" :class="validation.email ? 'err' : null">
<label for="email">ایمیل:</label>
<input type="email" v-model="formData.email" id="email">
<p v-if="validation.email">{{ validation.email.msg }}</p>
</div>
<div class="col-12 col-lg-6 form--row" :class="validation.mobile ? 'err' : null">
<label for="phoneNumber">شماره موبایل:</label>
<input type="text" v-model="formData.mobile" id="phoneNumber">
<p v-if="validation.mobile">{{ validation.mobile.msg }}</p>
</div>
<div class="col-12 form--row" :class="validation.address ? 'err' : null">
<label for="address">آدرس:</label>
<input type="text" v-model="formData.address" id="address">
<p class="addressValidation" v-if="validation.address">{{ validation.address.msg }}</p>
</div>
<div class="col-12 form--row">
<button>
<span>ارسال</span>
<IconsLeftArrow/>
</button>
</div>
</div>
</div>
</form>
</div>
</section>
</div>
</template>
<script>
export default {
created() {
if (process.client) $('body').addClass('reverse--theme')
},
data() {
return {
formData: {
full_name: '',
birth_date: '',
job: '',
marrage_date: '',
email: '',
mobile: '',
address: ''
},
validation: {}
}
},
mounted() {
//////////////////////////////////////////////////////////////////////////
const paperPlanAnimation = this.$gsap.timeline({repeat: -1, repeatDelay: 5})
.to($('#bell'), {rotate: 25, y: -9, x: 7, duration: 0.1})
.to($('#bell'), {rotate: 0, y: 0, x: 0, duration: 0.1})
.from($('#paperPlane'), {opacity: 0, y: 25, x: 20, duration: 0.7}, '-=0.5')
.from($('#paperPlaneL'), {opacity: 0, duration: 0.1}, '-=0.15')
.from($('#dash path'), {scale: 0, opacity: 0, duration: 0.2, stagger: -0.02}, '-=0.5')
.from($('#letterText path'), {scale: 0, opacity: 0, duration: 0.7, stagger: 0.2}, '-=0.5')
const dotsTl = this.$gsap.timeline({repeat: -1, yoyo: true})
.from($('#circles path'), {opacity: 0, duration: 0.5, stagger: 0.08})
//////////////////////////////////////////////////////////////////////////
},
methods: {
upload() {
this.validation = {}
const data = this.formData
this.$axios.post('/api/public/subscribers', data)
.then(response => {
this.$alert(response.data.message, 'ثبت موفق', {
confirmButtonText: 'باشه',
callback: action => {
this.formData = {
full_name: '',
birth_date: '',
job: '',
marrage_date: '',
email: '',
mobile: '',
address: ''
}
}
})
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.error.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
}
}
}
</script>