somewhere

This commit is contained in:
Swift
2023-08-17 13:05:51 +03:30
parent 30c7eb0e7b
commit 53843207cc
429 changed files with 117489 additions and 1 deletions
+132
View File
@@ -0,0 +1,132 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" class="mr-auto" @click="post">افزودن</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="ticket.title"
label="عنوان تیکت"
horizontal
:description="validation.title ? validation.title.msg : null"
:class="validation.title ? 'err' : null"
/>
<div class="form-group form-row mb-3" :class="validation.user_id ? 'err' : null">
<CCol sm="3" class="col-form-label">
<label>کد مشتری</label>
</CCol>
<CCol sm="9">
<el-select v-model="ticket.user_id" filterable placeholder="" style="width: 100%">
<el-option-group :key="0" label="کد مشتری های وریتی">
<el-option
v-for="item in users"
:key="item._id + '_verityIDs'"
:label="item.verity_businessCode"
:value="item._id"
>
</el-option>
</el-option-group>
<el-option-group :key="1" label="کد مشتری های پاناتک">
<el-option
v-for="item in users"
:key="item._id + '_panatechIDs'"
:label="item.panatech_businessCode"
:value="item._id"
>
</el-option>
</el-option-group>
</el-select>
<small v-if="validation.user_id" class="form-text text-muted w-100">{{
validation.user_id.msg
}}</small>
</CCol>
</div>
<CInput
v-model="ticket.transaction_id"
label="کد پذیرش"
horizontal
placeholder="اختیاری"
:description="validation.transaction_id ? validation.transaction_id.msg : null"
:class="validation.transaction_id ? 'err' : null"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminAddTicket',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const users = await $axios.get('/api/admin/allUsers')
return {
users: users.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'افزودن تیکت برای مشتری',
users: null,
ticket: {
title: '',
transaction_id: '',
user_id: ''
},
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
post() {
this.validation = {}
this.$axios
.post('/api/admin/addTicket', this.ticket)
.then(res => {
this.$message({
type: 'success',
message: 'تیکت با موفقیت ثبت شد، پیام خودرا بنویسید.'
})
this.$router.push({ name: 'admin-tickets-ticket', params: { ticket: res.data._id } })
})
.catch(err => {
if (err.response.data.status === 401) {
return this.$message({
type: 'warning',
message: 'لطفا دوباره وارد حساب خود شوید'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err)
})
},
mappedArray(arr) {
return arr.map(item => {
return {
label: item.arpa_businessCode,
value: item.arpa_businessCode
}
})
}
}
}
</script>
+274
View File
@@ -0,0 +1,274 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="admin._creator && admin._creator.first_name" type="primary">
<span>ایجاد یا اصلاح کننده: </span>
<span> {{ admin._creator.first_name + ' ' + admin._creator.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-admins' }">برگشت به صفحه قبل</CButton>
<CButton v-if="$route.params.admin === 'new'" size="sm" color="success" style="margin-right: 10px" @click="add"
>افزودن</CButton
>
<CButton v-else size="sm" color="success" style="margin-right: 10px" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="admin.first_name"
label="نام"
horizontal
:description="validation.first_name ? validation.first_name.msg : null"
:class="validation.first_name ? 'err' : null"
/>
<CInput
v-model="admin.last_name"
label="نام خانوادگی"
horizontal
:description="validation.last_name ? validation.last_name.msg : null"
:class="validation.last_name ? 'err' : null"
/>
<CInput
v-model="admin.username"
label="نام کاربری"
horizontal
:description="validation.username ? validation.username.msg : null"
:class="validation.username ? 'err' : null"
/>
<template v-if="$route.params.admin === 'new'">
<CInput
v-model="admin.password"
label="کلمه عبور"
horizontal
type="password"
:description="validation.password ? validation.password.msg : null"
:class="validation.password ? 'err' : null"
/>
<CInput
v-model="admin.password_confirmation"
label="تکرار کلمه عبور"
horizontal
type="password"
:description="validation.password_confirmation ? validation.password_confirmation.msg : null"
:class="validation.password_confirmation ? 'err' : null"
/>
</template>
<el-divider />
<h6>دسترسی های کاربر</h6>
<div class="user-permissions">
<el-tag
v-for="(item, index) in admin.permissions"
:key="index + Math.random() + 1"
class="ml-2 mb-2"
style="cursor: pointer"
closable
disable-transitions
@close="removePermission(item)"
>{{ getPermissionName(item) }}
</el-tag>
</div>
</CForm>
</CCardBody>
</CCard>
<CCard>
<CCardBody>
<h6>لیست کل دسترسی ها</h6>
<div class="permissions">
<el-tag
v-for="(item, index) in permissions"
:key="index + Math.random() + 2"
class="ml-2 mb-2"
style="cursor: pointer"
:type="hasPermission(item.value) ? 'success' : 'primary'"
disable-transitions
@click="addPermission(item.value)"
>{{ item.name }}
</el-tag>
</div>
</CCardBody>
</CCard>
</CCol>
<CCol v-if="$route.params.admin !== 'new'" xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="newPass.password"
label="کلمه عبور"
horizontal
type="password"
:description="validation.password ? validation.password.msg : null"
:class="validation.password ? 'err' : null"
/>
<CInput
v-model="newPass.password_confirmation"
label="تکرار کلمه عبور"
horizontal
type="password"
:description="validation.password_confirmation ? validation.password_confirmation.msg : null"
:class="validation.password_confirmation ? 'err' : null"
/>
<CButton color="success" variant="outline" @click="changePass">بروزرسانی کلمه عبور</CButton>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminAdminDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const data = {}
const permissions = await $axios.get('/api/admin/permissions')
data.permissions = permissions.data
if (params.admin !== 'new') {
const admin = await $axios.get(`/api/admin/admin/${params.admin}`)
data.admin = admin.data
}
return data
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: this.$route.params.admin === 'new' ? 'افزودن کاربر' : 'ویرایش ادمین',
admin: {
first_name: '',
last_name: '',
username: '',
permissions: [],
password: '',
password_confirmation: ''
},
permissions: null,
validation: {},
newPass: {
password: '',
password_confirmation: ''
}
}
},
head() {
return {
title: this.title
}
},
methods: {
add() {
this.validation = {}
this.$axios
.post(`/api/admin/addAdmin`, this.admin)
.then(response => {
if (response.data) {
this.$message({
message: 'کاربر با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push({ name: 'admin-admins' })
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
update() {
this.validation = {}
this.$axios
.put(`/api/admin/updateAdmin/${this.admin._id}`, this.admin)
.then(response => {
if (response.data) {
this.$message({
message: 'کاربر با موفقیت بروزرسانی شد.',
type: 'success'
})
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
getPermissionName(value) {
return this.permissions.filter(item => item.value === value)[0].name
},
addPermission(val) {
if (!this.admin.permissions.includes(val)) this.admin.permissions.push(val)
else
this.$message({
type: 'warning',
message: 'کاربر از قبل این دسترسی را دارد'
})
},
removePermission(val) {
this.admin.permissions = this.admin.permissions.filter(item => item !== val)
},
hasPermission(val) {
return this.admin.permissions.includes(val)
},
changePass() {
this.validation = {}
const data = {
_id: this.admin._id,
password: this.newPass.password,
password_confirmation: this.newPass.password_confirmation
}
this.$axios
.put('/api/admin/updateAdminPassword', data)
.then(res => {
this.$message({
type: 'success',
message: 'کلمه عبور با موفقیت بروزرسانی شد'
})
this.newPass = {
password: '',
password_confirmation: ''
}
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
else {
this.$message({
type: 'error',
message: err.response.data.message
})
}
})
}
}
}
</script>
+108
View File
@@ -0,0 +1,108 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{ name: 'admin-admins-admin', params: { admin: 'new' } }" class="mr-auto"
>افزودن</CButton
>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="admins" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="username" label="نام کاربری" width=""> </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 label="ویرایش" width="105" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="warning"
variant="outline"
:to="{ name: 'admin-admins-admin', params: { admin: scope.row._id } }"
>
<i class="fal fa-pencil"></i>
</CButton>
<CButton color="danger" variant="outline" @click="del(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminAdminsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const admins = await $axios.get(`/api/admin/admins`)
return {
admins: admins.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'ادمین های سایت',
list_title: 'لیست',
admins: null
}
},
head() {
return {
title: this.title
}
},
computed: {},
methods: {
del(id) {
this.$confirm('این کاربر حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/deleteAdmin/${id}`)
.then(response => {
this.admins = this.admins.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'کاربر حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
File diff suppressed because it is too large Load Diff
+66
View File
@@ -0,0 +1,66 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="12">
<CCard>
<CCardBody>
<EnrollRepresentationForm :data="agent" is-admin />
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminAgentUpdate',
layout: 'admin',
async asyncData({ $axios, query, error }) {
try {
const agent = await $axios.get(`/api/admin/agentDetails/${query.agent}`)
if (agent.data._revoked) throw new Error('err')
return {
agent: agent.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'ویرایش اطلاعات نماینده',
agent: null,
validation: {}
}
},
head() {
return {
title: this.title
}
},
mounted() {
this.updateNotice()
},
methods: {
updateNotice() {
const title = 'هشدار'
const msg =
'توجه داشته باشید با تغییر اطللاعات نماینده اطلاعات چاپی روی رسید پذیرش موقت مشتریان تحت تاثیر قرار خواهند گرفت.'
this.$confirm(msg, title, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
}).catch(() => {
this.$router.go(-1)
})
}
}
}
</script>
+621
View File
@@ -0,0 +1,621 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="agent._updatedBy && agent._updatedBy.first_name" type="primary" class="ml-1">
<span>ایجاد یا اصلاح کننده: </span>
<span> {{ agent._updatedBy.first_name + ' ' + agent._updatedBy.last_name }} </span>
</el-tag>
<el-tag v-if="agent._revoked && agent._revokedBy.first_name" type="danger">
<span>صلب امتیاز شده توسط: </span>
<span> {{ agent._revokedBy.first_name + ' ' + agent._revokedBy.last_name }} </span>
</el-tag>
<CButton
v-if="updatePermission && !agent._revoked"
size="sm"
color="warning"
class="mr-auto"
@click="goToUpdatePage"
>
<span style="color: #fff"> تغییر اطلاعات نماینده </span>
</CButton>
<CButton size="sm" color="danger" class="mr-1" @click="revoke">
<span style="color: #fff">ابطال امتیاز نماینده</span>
</CButton>
<CButton
size="sm"
color="primary"
:class="updatePermission && !agent._revoked ? 'mr-1' : 'mr-auto'"
@click="$router.go(-1)"
>برگشت به صفحه قبل</CButton
>
</CustomSubHeader>
<CRow>
<CCol lg="12">
<CCard>
<CCardBody>
<h6>گزارش کلی عملکرد نماینده:</h6>
<CRow class="align-items-stretch mt-3">
<CCol sm="6" md="4" class="mb-1">
<div class="card" style="height: 100%">
<div class="card-body d-flex align-items-center p-3">
<div class="ml-3 text-white bg-warning p-3">
<i class="fal fa-inbox"></i>
</div>
<div>
<div class="text-value text-info">{{ getAgentInboxCount('unread') }}</div>
<div class="text-muted text-uppercase font-weight-bold small">صندوق ورودی (دیده نشده)</div>
</div>
</div>
</div>
</CCol>
<CCol sm="6" md="4" class="mb-1">
<div class="card" style="height: 100%">
<div class="card-body d-flex align-items-center p-3">
<div class="ml-3 text-white bg-danger p-3">
<i class="fal fa-inbox"></i>
</div>
<div>
<div class="text-value text-info">{{ getAgentInboxCount('ttl') }}</div>
<div class="text-muted text-uppercase font-weight-bold small">صندوق ورودی (در انتظار پذیرش)</div>
</div>
</div>
</div>
</CCol>
<CCol sm="6" md="4" class="mb-1">
<div class="card" style="height: 100%">
<div class="card-body d-flex align-items-center p-3">
<div class="ml-3 text-white bg-success p-3">
<i class="fal fa-inbox"></i>
</div>
<div>
<div class="text-value text-info">{{ getAgentInboxCount('atl') }}</div>
<div class="text-muted text-uppercase font-weight-bold small">صندوق ورودی (پذیرش شده)</div>
</div>
</div>
</div>
</CCol>
<CCol sm="6" md="4" class="mb-1">
<div class="card" style="height: 100%">
<div class="card-body d-flex align-items-center p-3">
<div class="ml-3 text-white bg-primary p-3">
<i class="fas fa-wrench"></i>
</div>
<div>
<div class="text-value text-info">{{ agentPr.length }}</div>
<div class="text-muted text-uppercase font-weight-bold small">درخواست قطعه</div>
</div>
</div>
</div>
</CCol>
<CCol sm="6" md="4" class="mb-1">
<div class="card" style="height: 100%">
<div class="card-body d-flex align-items-center p-3">
<div class="ml-3 text-white bg-primary p-3">
<i class="fas fa-backpack"></i>
</div>
<div>
<div class="text-value text-info">{{ agentOpr.length }}</div>
<div class="text-muted text-uppercase font-weight-bold small">درخواست قطعه داغی</div>
</div>
</div>
</div>
</CCol>
<CCol sm="6" md="4" class="mb-1">
<div class="card" style="height: 100%">
<div class="card-body d-flex align-items-center p-3">
<div class="ml-3 text-white bg-primary p-3">
<i class="fab fa-buffer"></i>
</div>
<div>
<div class="text-value text-info">{{ agentBr.length }}</div>
<div class="text-muted text-uppercase font-weight-bold small">درخواست کالای بافر</div>
</div>
</div>
</div>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<h6>تغییر وضعیت آپلود مدارک</h6>
<el-divider></el-divider>
<CButtonGroup>
<CButton :color="agent.upload ? 'primary' : 'light'" @click="updateStatus('uploadOn')">
دسترسی آپلود
</CButton>
<CButton :color="!agent.upload ? 'primary' : 'light'" @click="updateStatus('uploadOff')">
عدم دسترسی آپلود
</CButton>
</CButtonGroup>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<h6>دسترسی ویرایش اطلاعات نمایندگی</h6>
<el-divider></el-divider>
<CButtonGroup>
<CButton :color="agent.editAccess ? 'primary' : 'light'" @click="updateStatus('editAccessOn')">
دسترسی ویرایش
</CButton>
<CButton :color="!agent.editAccess ? 'primary' : 'light'" @click="updateStatus('editAccessOff')">
عدم دسترسی ویرایش
</CButton>
</CButtonGroup>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>مشخصات فردی نماینده:</h6>
<el-divider></el-divider>
<nuxt-link :to="{ name: 'admin-customers-customer', params: { customer: agent.user_id } }"
>مشاهده اکانت کاربری</nuxt-link
>
<el-divider></el-divider>
<CForm>
<CInput label="نام مشتری" horizontal disabled :value="agent.full_name" />
<CInput label="کد ملی" horizontal disabled :value="agent.national_code" />
<CInput label="شماره شناسنامه" horizontal disabled :value="agent.id_number" />
<CInput label="محل صدور" horizontal disabled :value="agent.place_of_issue" />
<CInput label="تاریخ تولد" horizontal disabled :value="agent.birth_date" />
<CInput label="نام پدر" horizontal disabled :value="agent.fathers_name" />
<CInput label="میزان تحصیلات" horizontal disabled :value="agent.education_level" />
<CInput label="وضعیت نظام وظیفه" horizontal disabled :value="agent.military_status" />
<CTextarea label="گواهینامه های تخصصی اخذ شده" horizontal disabled rows="5" :value="agent.certificates" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>اطلاعات تماس:</h6>
<el-divider></el-divider>
<CForm>
<CInput label="استان" horizontal disabled :value="agent.province_name" />
<CInput label="شهر" horizontal disabled :value="agent.city_name" />
<CInput label="نام شرکت/تعمیرگاه" horizontal disabled :value="agent.store_name" />
<CInput label="کد پستی" horizontal disabled :value="agent.postal_code" />
<CInput label="تلفن همراه" horizontal disabled :value="agent.mobile_number" />
<CInput label="تلفن شرکت/تعمیرگاه" horizontal disabled :value="agent.tel_number" />
<CInput label="فکس شرکت/تعمیرگاه" horizontal disabled :value="agent.fax_number" />
<CInput label="کد اقتصادی" horizontal disabled :value="agent.economic_code" />
<CInput label="ایمیل" horizontal disabled :value="agent.email" />
<CTextarea label="آدرس" horizontal disabled rows="5" :value="agent.address" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>مشخصات مکان نماینده:</h6>
<el-divider></el-divider>
<CForm>
<CInput label="جواز کسب" horizontal disabled :value="business_license" />
<CInput label="نوع مالکیت" horizontal disabled :value="ownership_type" />
<CInput label="متراژ کل (متر)" horizontal disabled :value="agent.total_area" />
<CInput label="متراژ محل تعمیرات (متر)" horizontal disabled :value="agent.repair_area" />
<CInput label="متراژ انبار (متر)" horizontal disabled :value="agent.stock_area" />
<CInput label="طبقه محل مراجعه مشتریان" horizontal disabled :value="agent.customer_reference_floor" />
<CInput label="موقعیت مکانی" horizontal disabled :value="place_location" />
<CInput label="موقعیت جغرافیایی" horizontal disabled :value="geo_location" />
<CInput label="تعداد و ابعاد تابلو" horizontal disabled :value="agent.banner_info" />
<CInput label="تعداد تکنسین های تعمیرگاه" horizontal disabled :value="agent.repair_technicians" />
<CInput label="تعداد استادکار تعمیرگاه" horizontal disabled :value="agent.repair_masters" />
<CInput label="تعداد کارکنان اداری" horizontal disabled :value="agent.office_workers" />
<CInput label="تعداد پیک موتوری" horizontal disabled :value="agent.bike_deliveries" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>آشنایی با آسان سرویس:</h6>
<el-divider></el-divider>
<CForm>
<CInput label="نحوه آشنایی با شرکت" horizontal disabled :value="know_asanServ_from" />
<CTextarea
label="در صورتیکه معرف دارید مشخصات ایشان را ذکر کنید"
horizontal
disabled
rows="5"
:value="agent.introducer_info"
/>
<CInput
label="میزان آشنایی با محصولات آسان سرویس"
horizontal
disabled
:value="asanServ_products_knowledge"
/>
<CInput
label="آیا در زمینه فروش لوازم جانبی موبایل و کامپیوتر فعالیت دارید؟"
horizontal
disabled
:value="computer_saling_exp"
/>
<CTextarea
label="در صورت فعالیت فروش، نام شرکت و نوع محصول را نام ببرید"
horizontal
disabled
rows="5"
:value="agent.computer_saling_description"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>سایر توضیحات:</h6>
<el-divider></el-divider>
<CForm>
<CTextarea label="سایر توضیحات" horizontal disabled rows="5" :value="agent.more_descriptions" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>سابقه فعالیت:</h6>
<el-divider></el-divider>
<CForm>
<CInput
label="سابقه فعالیت در تعمیر ابزار جانبی موبایل و کامپیوتر (سال)"
horizontal
disabled
:value="agent.computer_repair_exp"
/>
<CInput
label="سابقه فعالیت در تعمیر لوزام صوتی و تصویری (سال)"
horizontal
disabled
:value="agent.multimedia_repair_exp"
/>
<CInput label="سابقه در محل کسب (سال)" horizontal disabled :value="agent.business_exp" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<h6>نمایندگی نشان تجاری دیگر:</h6>
<el-divider></el-divider>
<el-table :data="agent.other_representations" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="trademark" label="نشان تجاری" width=""> </el-table-column>
<el-table-column prop="company_name" label="نام شرکت" width=""> </el-table-column>
<el-table-column prop="cooperation_history" label="سابقه همکاری (سال)" width=""> </el-table-column>
<el-table-column prop="cooperation_start_year" label="سال شروع همکاری" width=""> </el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
<CCol v-for="item in agentAssetCategories" :key="item.fieldName" lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<h6>
{{ item.title }}
(عکس های آپلود شده)
<el-button
size="small"
:type="editFiles === item.fieldName ? 'success' : 'info'"
@click="toggleEditFiles(item.fieldName)"
>
<span style="color: #fff"> ویرایش مدارک </span>
</el-button>
</h6>
<el-divider></el-divider>
<template v-if="editFiles === item.fieldName">
<RepresentationImageUploader
:name="item.fieldName"
:files-list="agent[item.fieldName] || []"
:representation_code="agent.representation_code"
is-admin
/>
</template>
<template v-else>
<el-image
v-for="image in agent[item.fieldName] || []"
:key="image._id"
style="width: 100px; height: 100px"
:src="image.url"
:preview-src-list="getImagePreviewList(agent[item.fieldName] || [])"
fit="cover"
class="ml-2"
>
</el-image>
</template>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'AdminAgentDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const allData = await Promise.all([
// agent
$axios.get(`/api/admin/agentDetails/${params.agent}`),
// agentInbox
$axios.get(`/api/admin/agentInbox/${params.agent}`),
// agent buffer request
$axios.get(`/api/admin/agentBr/${params.agent}`),
// agent oldPiece request
$axios.get(`/api/admin/agentOpr/${params.agent}`),
// agent piece request
$axios.get(`/api/admin/agentPr/${params.agent}`)
])
const agent = allData[0]
const agentInbox = allData[1]
const agentBr = allData[2]
const agentOpr = allData[3]
const agentPr = allData[4]
return {
agent: agent.data,
agentInbox: agentInbox.data,
agentBr: agentBr.data,
agentOpr: agentOpr.data,
agentPr: agentPr.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده درخواست نمایندگی',
agent: null,
agentInbox: null,
agentBr: null,
agentOpr: null,
agentPr: null,
editFiles: '',
validation: {}
}
},
head() {
return {
title: this.title
}
},
computed: {
...mapGetters({
agentAssetCategories: 'front/agentAssetCategories'
}),
updatePermission() {
return this.$auth.user.permissions.includes('agentUpdate')
},
business_license() {
if (this.agent.business_license) return 'دارد'
else return 'ندارد'
},
ownership_type() {
if (this.agent.ownership_type === 'owner') return 'مالک'
else if (this.agent.ownership_type === 'rent') return 'استیجاری'
else return 'سرقفلی'
},
place_location() {
if (this.agent.place_location === 'tech_passage') return 'مرکز صنف موبایل و کامپیوتر'
else return 'سایر'
},
geo_location() {
if (this.agent.geo_location === 'main_street') return 'خیابان اصلی'
else if (this.agent.geo_location === 'side_street') return 'خیابان فرعی'
else if (this.agent.geo_location === 'alley') return 'کوچه'
else if (this.agent.geo_location === 'inside_passage') return 'داخل پاساژ'
else return 'بر پاساژ'
},
know_asanServ_from() {
if (this.agent.know_asanServ_from === 'company_agents') return 'نماینده فروش'
else if (this.agent.know_asanServ_from === 'website') return 'وب سایت'
else if (this.agent.know_asanServ_from === 'company_workers') return 'پرسنل سازمان'
else if (this.agent.know_asanServ_from === 'exhibition') return 'نمایشگاه'
else if (this.agent.know_asanServ_from === 'introduced') return 'معرفی'
else return 'سایر'
},
asanServ_products_knowledge() {
if (this.agent.asanServ_products_knowledge === 4) return 'زیاد'
else if (this.agent.asanServ_products_knowledge === 3) return 'نسبتاً خوب'
else if (this.agent.asanServ_products_knowledge === 2) return 'متوسط'
else if (this.agent.asanServ_products_knowledge === 1) return 'کم'
else return 'خیلی کم'
},
computer_saling_exp() {
if (this.agent.computer_saling_exp) return 'دارد'
else return 'ندارد'
}
},
watch: {
editFiles(newVal, oldVal) {
this.$nuxt.refresh()
}
},
methods: {
goToUpdatePage() {
const title = 'هشدار'
const msg =
'توجه داشته باشید با تغییر اطللاعات نماینده اطلاعات چاپی روی رسید پذیرش موقت مشتریان تحت تاثیر قرار خواهند گرفت.'
this.$confirm(msg, title, {
confirmButtonText: 'رفتن به صفحه ویرایش',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$router.push({ name: 'admin-agentUpdate', query: { agent: this.agent._id } })
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
getAgentInboxCount(status) {
return this.agentInbox.filter(item => {
if (status === 'unread') return !item.seen
if (status === 'ttl') return !item.ItemReceptionTransNumber
if (status === 'atl') return item.ItemReceptionTransNumber
return false
}).length
},
updateStatus(status) {
if (status === this.agent.status) return
const title = 'هشدار'
function getMsg() {
const msg1 = 'با تغییر وضعیت فرم به بررسی مدارک بلافاصله پیامک اطلاع رسانی برای متقاضی ارسال خواهد شد'
const msg2 =
'با تغییر وضعیت به رد شده یا تایید شده دیگر امکان تغییر وضعیت نخواهید داشت و پیامک تغییر وضعیت بلافاصله برای متقاضی ارسال خواهد شد، ادامه میدهید؟'
const msg3 = 'پیامک ایجاد دسرترسی آپلود برای متقاضی ارسال خواهد شد، ادامه میدهید؟'
const msg4 = 'با برداشتن دسترسی آپلود پیامکی برای متقاضی ارسال نخواهد شد'
const msg5 = 'پیامک ایجاد دسرترسی ویرایش برای متقاضی ارسال خواهد شد، ادامه میدهید؟'
const msg6 = 'با برداشتن دسترسی ویرایش پیامکی برای متقاضی ارسال نخواهد شد'
if (status === 'verification') return msg1
else if (status === 'rejected' || status === 'accepted') return msg2
else if (status === 'uploadOn') return msg3
else if (status === 'uploadOff') return msg4
else if (status === 'editAccessOn') return msg5
else return msg6
}
this.$confirm(getMsg(), title, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.put(`/api/admin/representationStatus/${this.agent._id}`, { status })
.then(response => {
this.$message({
type: 'success',
message: response.data.message
})
this.$nuxt.refresh()
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
getImagePreviewList(images) {
return images.map(item => item.url)
},
async revoke() {
try {
const title1 = ' هشدار - مرحله اول'
const title2 = ' هشدار - مرحله دوم'
const title3 = ' هشدار - مرحله آخر'
const msg1 = 'امتیاز نمایندگی از این نماینده صلب خواهد شد!'
const msg2 =
'با ابطال امتیاز نمایندگی دیگر امکان تغییر وجود ندارد و در صورت نیاز به اعطای مجدد امتیاز نمایندگی به این کاربر نیاز به ثبت درخواست مجدد توسط خود کاربر خواهد بود. '
const msg3 = 'ادامه میدهید؟'
/// first step
await this.$confirm(msg1, title1, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
/// second step
await this.$confirm(msg2, title2, {
confirmButtonText: 'متوجه شدم ',
cancelButtonText: 'لغو',
type: 'warning'
})
/// the last confirmation and send request
await this.$confirm(msg3, title3, {
confirmButtonText: 'ابطال نمایندگی ',
cancelButtonText: 'لغو',
type: 'warning'
})
/// send request
this.$axios
.post(`/api/admin/revokeAgent/${this.agent._id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'admin-agents', query: { agent: true } })
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در روند انجام عملیات پیش آمده'
})
})
} catch (e) {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
}
},
toggleEditFiles(fieldName) {
this.editFiles === fieldName ? (this.editFiles = '') : (this.editFiles = fieldName)
}
}
}
</script>
+194
View File
@@ -0,0 +1,194 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" class="mr-auto" @click="addAgentModal = true">
<span style="color: #fff"> افزودن نماینده </span>
</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="12">
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="کد نماینده - شماره موبایل - استان - شهر"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="filteredItems" 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_number" label="شماره موبایل" width=""> </el-table-column>
<el-table-column label="نوع نماینده" width="300">
<template slot-scope="scope">
<span v-if="scope.row.representation_type === 'both'">نماینده هر دو نوع لوازم</span>
<span v-if="scope.row.representation_type === 'verity'">نماینده لوازم جانبی کامپیوتر و موبایل</span>
<span v-if="scope.row.representation_type === 'panatech'">نماینده لوازم صوتی تصویری خودرو</span>
</template>
</el-table-column>
<el-table-column prop="agent_code" label="کد نماینده" width=""> </el-table-column>
<el-table-column prop="province_name" label="استان" width=""> </el-table-column>
<el-table-column prop="city_name" label="شهر" width=""> </el-table-column>
<el-table-column label="مشاهده" width="70" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-agents-agent', params: { agent: scope.row._id }, query: { ...$route.query } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<el-dialog :visible.sync="addAgentModal">
<el-select v-model="selectedUserForNewAgent" style="width: 100%" label="کاربر را انتخاب کنید" filterable>
<el-option
v-for="item in users"
:key="item._id"
:label="item.first_name + ' ' + item.last_name + ' (' + item.national_code + ')'"
:value="item._id"
></el-option>
</el-select>
<br />
<br />
<el-button type="success" :disabled="!selectedUserForNewAgent" @click="addAgent">
<span style="color: #fff">افزودن</span>
</el-button>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'AdminAgentsList',
layout: 'admin',
async asyncData({ $axios, query, error }) {
try {
let agents
if (query?.revoked) {
agents = await $axios.get('/api/admin/revokedAgents')
} else {
agents = await $axios.get('/api/public/agents')
}
return {
agents: agents.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
list_title: 'لیست',
agents: null,
users: [],
filterText: '',
addAgentModal: false,
selectedUserForNewAgent: null
}
},
head() {
return {
title: this.title
}
},
computed: {
revokedAgentsList() {
return this.$route.query?.revoked
},
title() {
if (this.revokedAgentsList) return 'لیست نمایندگان صلب امتیاز شده'
else return 'لیست نمایندگان'
},
filteredItems() {
const filterText = this.filterText.toLowerCase()
if (!filterText.length) return this.agents
else
return this.agents.filter(item => {
return (
item.agent_code.toLowerCase().includes(filterText) ||
item.full_name.toLowerCase().includes(filterText) ||
item.mobile_number.toLowerCase().includes(filterText) ||
item.province_name.toLowerCase().includes(filterText) ||
item.city_name.toLowerCase().includes(filterText)
)
})
}
},
watch: {
revokedAgentsList(newVal, oldVal) {
this.$nuxt.refresh()
},
addAgentModal(newVal, oldVal) {
this.selectedUserForNewAgent = null
}
},
mounted() {
this.$axios.$get('/api/admin/users').then(res => {
this.users = res
})
},
methods: {
addAgent() {
if (!this.selectedUserForNewAgent) {
return this.$message({
type: 'error',
message: 'ابتدا کاربر مورد نظر را انتخاب نمایید'
})
}
this.$axios
.$post('/api/admin/addAgentByAdmin', { user: this.selectedUserForNewAgent })
.then(res => {
this.$router.push({
name: 'admin-agents-agent',
params: { agent: res.representationId },
query: { ...this.$route.query }
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
}
}
}
</script>
+199
View File
@@ -0,0 +1,199 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="12">
<CCard>
<CCardBody>
<el-collapse>
<el-collapse-item title="مشخصات مشتری">
<CForm>
<CInput label="کد مشتری وریتی" horizontal disabled :value="transaction.user_id.verity_businessCode" />
<CInput
label="کد مشتری پاناتک"
horizontal
disabled
:value="transaction.user_id.panatech_businessCode"
/>
<CInput label="نام" horizontal disabled :value="transaction.user_id.first_name" />
<CInput label="نام خانوادگی" horizontal disabled :value="transaction.user_id.last_name" />
<CInput label="کد ملی" horizontal disabled :value="transaction.user_id.national_code" />
<CInput label="تلفن همراه" horizontal disabled :value="transaction.user_id.mobile_number" />
<CInput label="استان" horizontal disabled :value="transaction.user_id.province_name" />
<CInput label="شهر" horizontal disabled :value="transaction.user_id.city_name" />
<CInput label="آدرس" horizontal disabled :value="transaction.user_id.address" />
<CInput label="کد پستی" horizontal disabled :value="transaction.user_id.postal_code" />
</CForm>
<el-divider></el-divider>
<div style="text-align: center">
<nuxt-link :to="{ name: 'admin-customers-customer', params: { customer: transaction.user_id._id } }"
>مشاهده اکانت مشتری</nuxt-link
>
</div>
</el-collapse-item>
</el-collapse>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<el-collapse>
<el-collapse-item title="مشخصات نماینده">
<CForm>
<CInput label="نام و نام خانوادگی" horizontal disabled :value="transaction.agent_id.full_name" />
<CInput label="کد نماینده" horizontal disabled :value="transaction.agent_id.agent_code" />
<CInput label="تلفن همراه" horizontal disabled :value="transaction.agent_id.mobile_number" />
<CInput label="تلفن شرکت/تعمیرگاه" horizontal disabled :value="transaction.agent_id.tel_number" />
<CInput label="فکس شرکت/تعمیرگاه" horizontal disabled :value="transaction.agent_id.fax_number" />
<CInput label="استان" horizontal disabled :value="transaction.agent_id.province_name" />
<CInput label="شهر" horizontal disabled :value="transaction.agent_id.city_name" />
<CInput label="آدرس" horizontal disabled :value="transaction.agent_id.address" />
<CInput label="کد پستی" horizontal disabled :value="transaction.agent_id.postal_code" />
<CInput label="نام شرکت/تعمیرگاه" horizontal disabled :value="transaction.agent_id.store_name" />
</CForm>
<el-divider></el-divider>
<div style="text-align: center">
<nuxt-link :to="{ name: 'admin-agents-agent', params: { agent: transaction.agent_id._id } }"
>مشاهده اکانت نماینده</nuxt-link
>
</div>
</el-collapse-item>
</el-collapse>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<el-collapse>
<el-collapse-item title="تاریخچه وضعیت های فرم">
<el-table :data="transaction.statusHistory" style="width: 100%">
<el-table-column prop="name" label="وضعیت">
<template slot-scope="scope">
<span>{{ getStatusName(scope.row.status) }}</span>
</template>
</el-table-column>
<el-table-column prop="date" label="تاریخ">
<template slot-scope="scope">
<span style="display: inline-block; direction: ltr">{{ $jDateTime(scope.row.date) }}</span>
</template>
</el-table-column>
</el-table>
</el-collapse-item>
</el-collapse>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<CForm>
<CInput label="وضعیت فعلی فرم" horizontal disabled :value="getStatusName(transaction.status)" />
<CInput label="شماره پذیرش موقت" horizontal disabled :value="transaction.TempReceiptTransNumber" />
<CInput
label="شماره پذیرش دائم"
horizontal
disabled
:value="transaction.ItemReceptionTransNumber || '-'"
/>
<CInput
label="تاریخ پذیرش موقت"
horizontal
disabled
:value="$jDate(transaction.TempReceiptTransDate)"
/>
<CInput
label="تاریخ پذیرش دائم"
horizontal
disabled
:value="$jDate(transaction.ItemReceptionTransDate)"
/>
<CTextarea label="آدرس فرم" horizontal disabled rows="5" :value="transaction.cAddress1" />
<CTextarea label="توضیحات فرم" horizontal disabled rows="5" :value="transaction.Description" />
</CForm>
<h6>لیست کالاهای فرم:</h6>
<el-divider></el-divider>
<el-table :data="transaction.items" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="ItemName" label="نام کالا" width="">
<template slot-scope="scope">
<span>{{ getItemName(scope.row.ItemID) || 'درحال بارگیری ...' }}</span>
</template>
</el-table-column>
<el-table-column prop="SerialNo1" label="سریال کالا" width="">
<template slot-scope="scope">
<span>{{ scope.row.SerialNo1 || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="MjQty" label="تعداد" width=""></el-table-column>
</el-table>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminAgentInboxDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const transaction = await $axios.get(`/api/admin/allAgentsInbox/${params.tr}`)
if (!transaction.data.user_id) throw new Error('err')
return {
transaction: transaction.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده درخواست کالای بافر',
transaction: null
}
},
head() {
return {
title: this.title
}
},
computed: {
products() {
if (this.transaction.db_name === 'verity') return this.$store.state.admin.verityProducts
else if (this.transaction.db_name === 'panatech') return this.$store.state.admin.panatechProducts
else return []
},
allItemsAreinDraftsItems() {
return this.agentDraftItems.length === this.transaction.items.length
}
},
methods: {
getItemName(ItemID) {
return this.products.find(item => item.ItemID === ItemID)?.ItemName
},
getStatusName(status) {
if (status === 'saved') return 'ثبت شده'
else if (status === 'recieved') return 'پذیرش'
else if (status === 'ongoing') return 'در دست اقدام'
else if (status === 'waiting') return 'در انتظار قطعه'
else if (status === 'delivered') return 'تحویل شد'
else return 'invalid status'
}
}
}
</script>
+339
View File
@@ -0,0 +1,339 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="12">
<div class="mb-5">
<el-select v-model="selectedAgent" style="" clearable filterable placeholder="فیلتر بر اساس نماینده">
<el-option-group label="نمایندگان فعال">
<el-option
v-for="item of agents"
:key="item._id"
:value="item._id"
:label="item.full_name + ' ' + `(نمایندگی ${item.city_name} - کد ${item.agent_code})`"
></el-option>
</el-option-group>
<el-option-group label="نمایندگان صلب امتیاز شده">
<el-option
v-for="item of revokedAgents"
:key="item._id"
:value="item._id"
:label="item.full_name + ' ' + `(نمایندگی ${item.city_name} - کد ${item.agent_code})`"
></el-option>
</el-option-group>
</el-select>
<el-select
v-model="selectedProvince"
style=""
:disabled="Boolean(selectedAgent)"
clearable
filterable
placeholder="فیلتر بر اساس استان"
>
<el-option
v-for="item of iranProvinces"
:key="item.ProvinceID"
:value="item.ProvinceID"
:label="item.ProvinceName"
></el-option>
</el-select>
<el-select
v-model="selectedCity"
style=""
:disabled="Boolean(selectedAgent)"
clearable
filterable
placeholder="فیلتر بر اساس شهر"
>
<el-option
v-for="item of filteredCities"
:key="item.CityID"
:value="item.CityID"
:label="item.CityName"
></el-option>
</el-select>
</div>
<div class="statusBtns">
<CButtonGroup>
<CButton
:color="filterType === 'all' ? 'primary' : 'light'"
:class="filterType === 'all' && 'selected'"
@click="filterType = 'all'"
>
<span>همه</span>
<span> ({{ filteredItems.length }}) </span>
</CButton>
<CButton
:color="filterType === 'saved' ? 'primary' : 'light'"
:class="filterType === 'saved' && 'selected'"
@click="filterType = 'saved'"
>
<span>جدید</span>
<span> ({{ getListCountByStatus('saved') }}) </span>
</CButton>
<CButton
:color="filterType === 'recieved' ? 'primary' : 'light'"
:class="filterType === 'recieved' && 'selected'"
@click="filterType = 'recieved'"
>
<span>پذیرش شده</span>
<span> ({{ getListCountByStatus('recieved') }}) </span>
</CButton>
<CButton
:color="filterType === 'ongoing' ? 'primary' : 'light'"
:class="filterType === 'ongoing' && 'selected'"
@click="filterType = 'ongoing'"
>
<span>در دست اقدام</span>
<span> ({{ getListCountByStatus('ongoing') }}) </span>
</CButton>
<CButton
:color="filterType === 'waiting' ? 'primary' : 'light'"
:class="filterType === 'waiting' && 'selected'"
@click="filterType = 'waiting'"
>
<span>در انتظار قطعه</span>
<span> ({{ getListCountByStatus('waiting') }} )</span>
</CButton>
<CButton
:color="filterType === 'delivered' ? 'primary' : 'light'"
:class="filterType === 'delivered' && 'selected'"
@click="filterType = 'delivered'"
>
<span>تحویل شده</span>
<span> ({{ getListCountByStatus('delivered') }}) </span>
</CButton>
</CButtonGroup>
</div>
</CCol>
<CCol sm="12">
<el-divider></el-divider>
</CCol>
<CCol sm="12">
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="کد پذیرش موقت - کد پذیرش دائم - کد مشتری"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="filteredItems"
style="width: 100%"
:row-class-name="({ row, rowIndex }) => row.status === 'saved' && 'unread'"
>
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="تاریخ ثبت درخواست" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.sendDate) }} </span>
</template>
</el-table-column>
<el-table-column prop="TempReceiptTransNumber" label="کد پذیرش موقت" width=""> </el-table-column>
<el-table-column prop="ItemReceptionTransNumber" label="کد پذیرش دائم" width="">
<template slot-scope="scope">
<span>{{ scope.row.ItemReceptionTransNumber || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="user_id.province_name" label="استان" width=""> </el-table-column>
<el-table-column prop="user_id.city_name" label="شهر" width=""> </el-table-column>
<el-table-column prop="agent_id.agent_code" label="کد نماینده" width=""> </el-table-column>
<el-table-column label="وضعیت" width="" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 'saved'" type="info">جدید</el-tag>
<el-tag v-if="scope.row.status === 'recieved'" type="info">پذیرش شده</el-tag>
<el-tag v-if="scope.row.status === 'ongoing'" type="primary">در دست اقدام</el-tag>
<el-tag v-if="scope.row.status === 'waiting'" type="warning">در انتظار قطعه</el-tag>
<el-tag v-if="scope.row.status === 'delivered'" type="success">تحویل شده</el-tag>
</template>
</el-table-column>
<el-table-column label="بررسی" width="65" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-agentsInbox-tr', params: { tr: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminAgentsInboxList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const transactions = await $axios.get('/api/admin/allAgentsInbox')
const agents = await $axios.get('/api/public/agents')
const revokedAgents = await $axios.get('/api/admin/revokedAgents')
return {
transactions: transactions.data,
agents: agents.data,
revokedAgents: revokedAgents.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'صندوق ورودی نمایندگان',
list_title: 'لیست',
transactions: null,
agents: null,
revokedAgents: null,
filterText: '',
selectedAgent: '',
selectedProvince: '',
selectedCity: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
iranProvinces() {
return this.$store.state.admin.iranProvinces
},
iranCities() {
return this.$store.state.admin.iranCities
},
filteredCities() {
if (this.selectedProvince) {
return this.iranCities.filter(item => item.ProvinceID === this.selectedProvince)
} else return this.iranCities
},
filteredItems() {
const filterStep1 = this.transactions.filter(item => {
if (this.selectedAgent) {
if (this.selectedAgent === item.agent_id?._id) return item
return false
} else return item
})
const filterStep2 = filterStep1.filter(item => {
if (this.selectedProvince) {
if (this.selectedProvince === item.user_id?.province_id) return item
return false
} else return item
})
const filterStep3 = filterStep2.filter(item => {
if (this.selectedCity) {
if (this.selectedCity === item.user_id?.city_id) return item
return false
} else return item
})
const filterByStatus = filterStep3.filter(item =>
this.filterType === 'all' ? item : item.status === this.filterType
)
const filterText = this.filterText
if (!this.filterText.length) return filterByStatus
else
return filterByStatus.filter(item => {
return (
item.TempReceiptTransNumber.includes(filterText) ||
item.ItemReceptionTransNumber.includes(filterText) ||
item.user_id.verity_businessCode.includes(filterText) ||
item.user_id.panatech_businessCode.includes(filterText)
)
})
},
filterType: {
get() {
return this.$route.query.status
},
set(val) {
this.$router.push({ name: 'admin-agentsInbox', query: { status: val } })
}
}
},
watch: {
selectedProvince(newVal, oldVal) {
this.selectedCity = ''
},
selectedAgent(newVal, oldVal) {
this.selectedProvince = ''
this.selectedCity = ''
}
},
methods: {
getListCountByStatus(status) {
return this.filteredItems.filter(item => item.status === status).length
}
}
}
</script>
<style lang="scss" scopped>
.statusBtns {
.selected {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
z-index: 2;
span {
color: #fff;
}
}
}
.unread {
background: rgba(orange, 0.1) !important;
}
</style>
+226
View File
@@ -0,0 +1,226 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
<CButton v-if="isNew" size="sm" color="success" class="mr-1" @click="post">افزودن</CButton>
<!-- <CButton size="sm" v-else color="success" class="mr-1" @click="update">بروزرسانی</CButton>-->
</CustomSubHeader>
<CRow>
<CCol v-if="type" sm="12">
<CCard>
<CCardBody>
<h6>متن اعلان:</h6>
<el-divider></el-divider>
<CForm>
<CInput
v-model="announcement.title"
label="عنوان"
horizontal
:class="validation.title && 'err'"
:disabled="!isNew"
:description="validation.title && validation.title.msg"
/>
<CTextarea
v-model="announcement.caption"
label="متن"
horizontal
rows="5"
:class="validation.caption && 'err'"
:disabled="!isNew"
:description="validation.caption && validation.caption.msg"
/>
</CForm>
<el-divider></el-divider>
<h6>تاریخ منقضی شدن اعلان:</h6>
<p v-if="type === 'user'" class="mb-4" style="font-size: 12px; color: gray">
*زمانی که اعلان منقضی شود از لیست حذف نخواهد شد و فقط در پنل کاربران قابل مشاهده نخواهد بود.
</p>
<p v-if="type === 'agent'" class="mb-4" style="font-size: 12px; color: gray">
*زمانی که اعلان منقضی شود از لیست حذف نخواهد شد و فقط در پنل نمایندگان قابل مشاهده نخواهد بود.
</p>
<persian-date-picker
v-model="expireDate"
display-format="jYYYY/jMM/jDD"
:min="today"
format="x"
:disabled="!isNew"
placeholder="تاریخ را انتخاب کنید"
color="#065495"
/>
<p v-if="validation.expireDate" style="color: red">{{ validation.expireDate.msg }}</p>
</CCardBody>
</CCard>
</CCol>
<CCol v-if="$route.params.item !== 'new' && type" sm="12">
<CCard>
<CCardBody>
<h6>وضعیت بازدید اعلان:</h6>
<el-divider></el-divider>
<div class="progressBar">
<el-progress
:text-inside="true"
:stroke-width="26"
:color="customColors"
:percentage="seenPercentage"
></el-progress>
</div>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminAnnouncementDetails',
layout: 'admin',
async asyncData({ $axios, params, query, error }) {
try {
if (params.item !== 'new') {
const announcement = await $axios.get(`/api/admin/announcements/${params.item}`)
const users = await $axios.get(`/api/admin/announcementsUsers`)
const agents = await $axios.get('/api/public/agents')
return {
announcement: announcement.data,
users: users.data,
agents: agents.data
}
} else {
return {
announcement: {
title: '',
caption: '',
expireDate: '',
isForAgents: !!query?.agent
}
}
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
announcement: null,
users: null,
agents: null,
customColors: [
{ color: '#f56c6c', percentage: 20 },
{ color: '#e6a23c', percentage: 40 },
{ color: '#1989fa', percentage: 60 },
{ color: '#5cb87a', percentage: 80 },
{ color: '#5cb87a', percentage: 100 }
],
validation: {}
}
},
head() {
return {
title: this.title
}
},
computed: {
title() {
if (this.type === 'agent' && this.isNew) return 'افزودن اطلاعیه برای نمایندگان'
if (this.type === 'user' && this.isNew) return 'افزودن اعلان برای مشتریان'
if (this.type === 'agent') return 'مشاهده اطلاعیه نمایندگان'
if (this.type === 'user') return 'مشاهده اعلان مشتریان'
return null
},
type() {
if (this.$route.query?.user) return 'user'
if (this.$route.query?.agent) return 'agent'
return null
},
isNew() {
return this.$route.params.item === 'new'
},
seenPercentage() {
let totalAudience
if (this.type === 'user') totalAudience = this.users.length || 1
if (this.type === 'agent') totalAudience = this.agents.length || 1
const percenteage = Number(((this.announcement.seenBy.length * 100) / totalAudience).toFixed(2))
return percenteage > 100 ? 100 : percenteage
},
today() {
return Date.now().toString()
},
expireDate: {
get() {
return this.announcement.expireDate.toString()
},
set(val) {
this.announcement.expireDate = val
}
}
},
methods: {
post() {
this.validation = {}
this.$axios
.post('/api/admin/announcements', this.announcement)
.then(res => {
this.$message({
type: 'success',
message: 'پیام با موفقیت برای کاربران ارسال شد'
})
this.$router.push({ name: 'admin-announcements', query: { ...this.$route.query } })
})
.catch(err => {
if (err.response.status === 422) {
this.$message({
type: 'warning',
message: 'پارامتر ها رو بررسی کنید'
})
this.validation = err.response.data.validation
}
if (err.response.status === 401)
this.$message({
type: 'error',
message: 'دوباره وارد سیستم شوید'
})
})
}
// update() {
// this.validation = {}
// this.$axios.put(`/api/admin/announcement/${this.announcement._id}`, this.announcement)
// .then(res => {
// this.$message({
// type: 'success',
// message: 'پیام با موفقیت بروزرسانی شد'
// })
// this.$router.push({name: 'admin-announcements'})
// })
// .catch(err => {
// if (err.response.status === 422) {
// this.$message({
// type: 'warning',
// message: 'پارامتر ها رو بررسی کنید'
// })
// this.validation = err.response.data.validation
// }
// if (err.response.status === 401) this.$message({
// type: 'error',
// message: 'دوباره وارد سیستم شوید'
// })
// else console.log(err)
// })
// },
}
}
</script>
<style lang="scss">
.progressBar {
.el-progress-bar__inner {
left: auto;
right: 0;
text-align: left;
}
}
</style>
+151
View File
@@ -0,0 +1,151 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton
size="sm"
color="success"
class="mr-auto"
:to="{ name: 'admin-announcements-item', params: { item: 'new' }, query: { ...$route.query } }"
>افزودن</CButton
>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="filteredByType" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="title" label="عنوان" width=""> </el-table-column>
<el-table-column prop="caption" label="متن" width="">
<template slot-scope="scope">
<span class="singleLineTxt" :title="scope.row.caption"> {{ scope.row.caption }} </span>
</template>
</el-table-column>
<el-table-column prop="caption" label="تاریخ ایجاد" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.created_at) }} </span>
</template>
</el-table-column>
<el-table-column prop="caption" label="تاریخ انقضا" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.expireDate) }} </span>
</template>
</el-table-column>
<el-table-column prop="caption" label="وضعیت اعلان" width="">
<template slot-scope="scope">
<el-tag v-if="scope.row.expired" type="danger">منقضی شده</el-tag>
<el-tag v-else type="success">معتبر</el-tag>
</template>
</el-table-column>
<el-table-column label="ویرایش" width="110" align="center">
<template slot-scope="scope">
<CButton :key="scope.row._id" color="danger" variant="outline" @click="removeAnnouncement(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
<CButton
:key="scope.row._id + type"
color="success"
variant="outline"
:to="{ name: 'admin-announcements-item', params: { item: scope.row._id }, query: { ...$route.query } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminAnnouncementsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const announcements = await $axios.get('/api/admin/announcements')
return {
announcements: announcements.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
list_title: 'لیست',
announcements: null
}
},
head() {
return {
title: this.title
}
},
computed: {
title() {
if (this.type === 'user') return 'اعلانات مشتریان'
if (this.type === 'agent') return 'اطلاعیه های نمایندگان'
return 'invalid params'
},
type() {
if (this.$route.query?.user) return 'user'
if (this.$route.query?.agent) return 'agent'
return null
},
filteredByType() {
return this.announcements.filter(item => {
if (this.type === 'user' && !item.isForAgents) return item
if (this.type === 'agent' && item.isForAgents) return item
return false
})
}
},
methods: {
removeAnnouncement(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/announcements/${id}`)
.then(res => {
this.announcements = this.announcements.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+225
View File
@@ -0,0 +1,225 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="bufferRequest._openedBy && bufferRequest._openedBy.first_name" type="primary" class="ml-1">
<span>اولین مشاهده توسط: </span>
<span> {{ bufferRequest._openedBy.first_name + ' ' + bufferRequest._openedBy.last_name }} </span>
</el-tag>
<el-tag v-if="bufferRequest._updatedBy && bufferRequest._updatedBy.first_name" type="primary" class="ml-1">
<span>تغییر وضعیت توسط: </span>
<span> {{ bufferRequest._updatedBy.first_name + ' ' + bufferRequest._updatedBy.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol v-if="!bufferRequest.archived && bufferRequest.status !== 'rejected'" lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol lg="6">
<h6>تغییر وضعیت فرم</h6>
<el-divider></el-divider>
<CButtonGroup>
<!-- <CButton
:color="bufferRequest.status === 'ongoing' ? 'warning' : 'light'"
@click="updateStatus('ongoing')"
>
در دست اقدام
</CButton> -->
<CButton
:color="bufferRequest.status === 'waiting' ? 'warning' : 'light'"
@click="updateStatus('waiting')"
>
در انتظار قطعه
</CButton>
<el-popover
v-model="deliverPopover"
placement="bottom"
width="160"
:disabled="bufferRequest.status === 'delivered'"
@click="deliveryPopover = true"
>
<el-input v-model="deliveryCode" placeholder="کد ارسال مرسوله"></el-input>
<div class="mt-1" style="text-align: center">
<el-button
size="mini"
type="text"
class="agentsStatus-popover-insideBtn"
@click="updateStatus('delivered')"
>ارسال</el-button
>
</div>
<CButton slot="reference" :color="bufferRequest.status === 'delivered' ? 'success' : 'light'">
تحویل شده
</CButton>
</el-popover>
</CButtonGroup>
<div v-if="bufferRequest.status === 'delivered'" class="mt-3">
<p>
<span>کد ارسال مرسوله: </span>
<b>{{ bufferRequest.deliveryCode || '-' }} </b>
</p>
</div>
</CCol>
<CCol lg="6">
<h6>تاریخچه وضعیت های فرم</h6>
<el-divider></el-divider>
<el-table :data="bufferRequest.statusHistory" style="width: 100%">
<el-table-column prop="name" label="وضعیت">
<template slot-scope="scope">
<span v-if="scope.row.status === 'temp'">پیشنویس</span>
<span v-if="scope.row.status === 'sent'">ارسال</span>
<span v-if="scope.row.status === 'ongoing'">در دست اقدام</span>
<span v-if="scope.row.status === 'waiting'">در انتظار قطعه</span>
<span v-if="scope.row.status === 'delivered'">تحویل شده</span>
</template>
</el-table-column>
<el-table-column prop="date" label="تاریخ">
<template slot-scope="scope">
<span style="display: inline-block; direction: ltr">{{ $jDateTime(scope.row.date) }}</span>
</template>
</el-table-column>
</el-table>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<el-collapse>
<el-collapse-item title="مشخصات نماینده">
<CForm>
<CInput label="نام و نام خانوادگی" horizontal disabled :value="bufferRequest.agent_id.full_name" />
<CInput label="کد ملی" horizontal disabled :value="bufferRequest.agent_id.national_code" />
<CInput label="تلفن همراه" horizontal disabled :value="bufferRequest.agent_id.mobile_number" />
<CInput label="تلفن شرکت/تعمیرگاه" horizontal disabled :value="bufferRequest.agent_id.tel_number" />
<CInput label="فکس شرکت/تعمیرگاه" horizontal disabled :value="bufferRequest.agent_id.fax_number" />
<CInput label="استان" horizontal disabled :value="bufferRequest.agent_id.province_name" />
<CInput label="شهر" horizontal disabled :value="bufferRequest.agent_id.city_name" />
<CInput label="آدرس" horizontal disabled :value="bufferRequest.agent_id.address" />
<CInput label="کد پستی" horizontal disabled :value="bufferRequest.agent_id.postal_code" />
<CInput label="نام شرکت/تعمیرگاه" horizontal disabled :value="bufferRequest.agent_id.store_name" />
</CForm>
<el-divider></el-divider>
<div style="text-align: center">
<nuxt-link :to="{ name: 'admin-agents-agent', params: { agent: bufferRequest.user_id } }"
>مشاهده اکانت نماینده</nuxt-link
>
</div>
</el-collapse-item>
</el-collapse>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<CForm>
<CTextarea label="توضیحات فرم" horizontal disabled rows="5" :value="bufferRequest.description" />
</CForm>
<h6>لیست کالاهای بافر درخواستی:</h6>
<el-divider></el-divider>
<el-table :data="bufferRequest.items" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="ItemName" label="نام کالا" width=""></el-table-column>
<el-table-column prop="bufferQuantity" label="تعداد" width=""></el-table-column>
</el-table>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminBufferRequestDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const bufferRequest = await $axios.get(`/api/admin/br/${params.brId}`)
return {
bufferRequest: bufferRequest.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده درخواست کالای بافر',
bufferRequest: null,
deliverPopover: false,
deliveryCode: '',
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
updateStatus(status) {
if (status === this.bufferRequest.status) return
if (this.bufferRequest.status === 'delivered') return
const title = 'هشدار'
function getMsg() {
const msg1 = 'با تغییر وضعیت فرم به در انتظار قطعه بلافاصله پیامک اطلاع رسانی برای نماینده ارسال خواهد شد'
const msg2 =
'با تغییر وضعیت فرم به تحویل شده بلافاصله پیامک اطلاع رسانی برای نماینده ارسال خواهد شد. توجه داشته باشید بعدا نمیتوانید کد ارسال مرسوله را تغییر دهید.'
if (status === 'ongoing') return msg1
else return msg2
}
this.$confirm(getMsg(), title, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.put(`/api/admin/brStatus/${this.bufferRequest._id}`, { status, deliveryCode: this.deliveryCode })
.then(response => {
this.$message({
type: 'success',
message: response.data.message
})
this.deliveryCode = ''
this.$nuxt.refresh()
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+219
View File
@@ -0,0 +1,219 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="12">
<CButtonGroup>
<CButton
:color="filterType === 'all' ? 'primary' : 'light'"
:class="filterType === 'all' && 'selected'"
@click="filterType = 'all'"
>
<span>همه</span>
<span> ({{ brList.length }}) </span>
</CButton>
<CButton
:color="filterType === 'sent' ? 'primary' : 'light'"
:class="filterType === 'sent' && 'selected'"
@click="filterType = 'sent'"
>
<span>جدید</span>
<span> ({{ getListCountByStatus('sent') }}) </span>
</CButton>
<CButton
:color="filterType === 'ongoing' ? 'primary' : 'light'"
:class="filterType === 'ongoing' && 'selected'"
@click="filterType = 'ongoing'"
>
<span>در دست اقدام</span>
<span> ({{ getListCountByStatus('ongoing') }}) </span>
</CButton>
<CButton
:color="filterType === 'waiting' ? 'primary' : 'light'"
:class="filterType === 'waiting' && 'selected'"
@click="filterType = 'waiting'"
>
<span>در انتظار قطعه</span>
<span> ({{ getListCountByStatus('waiting') }} )</span>
</CButton>
<CButton
:color="filterType === 'delivered' ? 'primary' : 'light'"
:class="filterType === 'delivered' && 'selected'"
@click="filterType = 'delivered'"
>
<span>تحویل شده</span>
<span> ({{ getListCountByStatus('delivered') }}) </span>
</CButton>
</CButtonGroup>
</CCol>
<CCol sm="12">
<el-divider></el-divider>
</CCol>
<CCol sm="12">
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="کد پیگیری - کد نماینده - شماره موبایل نماینده - کد ملی نماینده - استان - شهر"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="filteredItems"
style="width: 100%"
:row-class-name="({ row, rowIndex }) => row.status === 'sent' && 'unread'"
>
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="تاریخ ثبت درخواست" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.sendDate) }} </span>
</template>
</el-table-column>
<el-table-column prop="trackingCode" label="کد پیگیری" width=""> </el-table-column>
<el-table-column prop="agent_id.province_name" label="استان" width=""> </el-table-column>
<el-table-column prop="agent_id.city_name" label="شهر" width=""> </el-table-column>
<el-table-column prop="agent_id.agent_code" label="کد نماینده" width=""> </el-table-column>
<el-table-column label="وضعیت" width="" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 'sent'" type="info">جدید</el-tag>
<el-tag v-if="scope.row.status === 'ongoing'" type="primary">در دست اقدام</el-tag>
<el-tag v-if="scope.row.status === 'waiting'" type="warning">در انتظار قطعه</el-tag>
<el-tag v-if="scope.row.status === 'delivered'" type="success">تحویل شده</el-tag>
</template>
</el-table-column>
<el-table-column label="بررسی" width="65" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-buffer-requests-brId', params: { brId: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminBufferRequestsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const brList = await $axios.get('/api/admin/brList')
return {
brList: brList.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'درخواست های کالای بافر',
list_title: 'لیست',
brList: null,
filterText: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
filteredItems() {
const filterData = this.brList.filter(item =>
this.filterType === 'all' ? item : item.status === this.filterType
)
const filterText = this.filterText
if (!this.filterText.length) return filterData
else
return filterData.filter(item => {
return (
item.trackingCode.includes(filterText) ||
item.agent_id.agent_code.includes(filterText) ||
item.agent_id.full_name.includes(filterText) ||
item.agent_id.mobile_number.includes(filterText) ||
item.agent_id.national_code.includes(filterText) ||
item.agent_id.province_name.includes(filterText) ||
item.agent_id.city_name.includes(filterText)
)
})
},
filterType: {
get() {
return this.$route.query.status
},
set(val) {
this.$router.push({ name: 'admin-buffer-requests', query: { status: val } })
}
}
},
methods: {
getListCountByStatus(status) {
return this.brList.filter(item => item.status === status).length
}
}
}
</script>
<style lang="scss" scopped>
.selected {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
z-index: 2;
span {
color: #fff;
}
}
.unread {
background: rgba(orange, 0.1) !important;
}
</style>
+54
View File
@@ -0,0 +1,54 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="message.read_by && message.read_by.first_name" type="primary">
<span>خوانده شده توسط: </span>
<span> {{ message.read_by.first_name + ' ' + message.read_by.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-contact-us' }">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput v-model="message.full_name" label="نام و نام خانوادگی" horizontal disabled />
<CInput label="ایمیل" horizontal disabled :value="message.email" />
<CTextarea label="پیام" horizontal disabled rows="20" :value="message.message" />
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminContactUsMsgDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const message = await $axios.get(`/api/admin/contact/${params.message}`)
return {
message: message.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'پیام',
message: null
}
},
head() {
return {
title: this.title
}
}
}
</script>
+116
View File
@@ -0,0 +1,116 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<!-- <CButton size="sm" color="success" :to="{name: 'admin-FAQ-new'}" class="mr-auto">افزودن</CButton>-->
</CustomSubHeader>
<CRow>
<CCol col="col">
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-filter"></i>
<span>فیلتر</span>
</slot>
</CCardHeader>
<CCardBody>
<CButtonGroup>
<CButton color="primary" :class="filter === 'all' && 'selected'" @click="filter = 'all'">همه</CButton>
<CButton color="warning" :class="!filter && 'selected'" @click="filter = false">خوانده نشده</CButton>
<CButton color="success" :class="filter === true && 'selected'" @click="filter = true"
>خوانده شده</CButton
>
</CButtonGroup>
</CCardBody>
</CCard>
</CCol>
</CRow>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="filtered" :row-class-name="readStatus" 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="email" label="ایمیل" width=""> </el-table-column>
<el-table-column label="مشاهده" width="70" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="`/admin/contact-us/${scope.row._id}`"
>
<i class="far fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminContactUsMsgList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const messages = await $axios.get(`/api/admin/contact`)
return {
messages: messages.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'پیام ها',
list_title: 'لیست',
messages: null,
filter: 'all'
}
},
head() {
return {
title: this.title
}
},
computed: {
filtered() {
if (this.filter === 'all') return this.messages
else return this.messages.filter(item => item.read === this.filter)
}
},
methods: {
readStatus({ row, rowIndex }) {
return row.read ? null : 'unread'
}
}
}
</script>
<style>
.unread {
background: rgb(255, 173, 0, 0.12) !important;
}
.selected {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
z-index: 2;
}
</style>
+269
View File
@@ -0,0 +1,269 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<!-- verity info -->
<CCol sm="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<h6>اطلاعات مشتری در سیستم وریتی</h6>
<el-divider></el-divider>
<CForm>
<CInput
:label="user.old_verity_businessCode ? 'شناسه وریتی قبلی مشتری' : 'شناسه وریتی مشتری'"
horizontal
disabled
:value="user.old_verity_businessCode || user.verity_businessCode"
/>
<CInput
:label="user.old_verity_businessID ? 'آیدی قبلی وریتی مشتری' : 'آیدی وریتی مشتری'"
horizontal
disabled
:value="user.old_verity_businessID || user.verity_businessID"
/>
<template v-if="user.old_verity_businessID && user.old_verity_businessCode">
<CInput label="شناسه وریتی جدید مشتری" horizontal disabled :value="user.verity_businessCode" />
<CInput label="آیدی وریتی جدید مشتری" horizontal disabled :value="user.verity_businessID" />
</template>
</CForm>
</CCol>
<CCol>
<h6>تغییر اطلاعات مشتری در سیستم وریتی</h6>
<el-divider></el-divider>
<CForm @submit.prevent="updateVerityInfo">
<CInput
v-model="newVerityInfo.verity_businessCode"
label="شناسه وریتی جدید مشتری"
:class="validation.verity_businessCode && 'err'"
horizontal
:description="validation.verity_businessCode && validation.verity_businessCode.msg"
/>
<CInput
v-model="newVerityInfo.verity_businessID"
label="آیدی وریتی جدید مشتری"
:class="validation.verity_businessID && 'err'"
horizontal
:description="validation.verity_businessID && validation.verity_businessID.msg"
/>
<CButton color="success" type="submit">بروزرسانی</CButton>
</CForm>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<!-- panatech info -->
<CCol sm="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<h6>اطلاعات مشتری در سیستم پاناتک</h6>
<el-divider></el-divider>
<CForm>
<CInput
:label="user.old_panatech_businessCode ? 'شناسه پاناتک قبلی مشتری' : 'شناسه پاناتک مشتری'"
horizontal
disabled
:value="user.old_panatech_businessCode || user.panatech_businessCode"
/>
<CInput
:label="user.old_panatech_businessID ? 'آیدی قبلی پاناتک مشتری' : 'آیدی پاناتک مشتری'"
horizontal
disabled
:value="user.old_panatech_businessID || user.panatech_businessID"
/>
<template v-if="user.old_panatech_businessID && user.old_panatech_businessCode">
<CInput label="شناسه پاناتک جدید مشتری" horizontal disabled :value="user.panatech_businessCode" />
<CInput label="آیدی پاناتک جدید مشتری" horizontal disabled :value="user.panatech_businessID" />
</template>
</CForm>
</CCol>
<CCol>
<h6>تغییر اطلاعات مشتری در سیستم پاناتک</h6>
<el-divider></el-divider>
<CForm @submit.prevent="updatePanatechInfo">
<CInput
v-model="newPanatechInfo.panatech_businessCode"
label="شناسه پاناتک جدید مشتری"
:class="validation.panatech_businessCode && 'err'"
horizontal
:description="validation.panatech_businessCode && validation.panatech_businessCode.msg"
/>
<CInput
v-model="newPanatechInfo.panatech_businessID"
label="آیدی پاناتک جدید مشتری"
:class="validation.panatech_businessID && 'err'"
horizontal
:description="validation.panatech_businessID && validation.panatech_businessID.msg"
/>
<CButton color="success" type="submit">بروزرسانی</CButton>
</CForm>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>اطلاعات مشتری:</h6>
<el-divider></el-divider>
<CForm>
<CInput label="نام مشتری" horizontal disabled :value="user.first_name + ' ' + user.last_name" />
<CInput label="کد ملی" horizontal disabled :value="user.national_code" />
<CInput label="شماره تلفن" horizontal disabled :value="user.tel_number" />
<CInput label="شماره موبایل" horizontal disabled :value="user.mobile_number" />
<CInput label="ایمیل" horizontal disabled :value="user.email" />
<CInput label="نام فروشگاه" horizontal disabled :value="user.store_name" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>آدرس مشتری</h6>
<el-divider></el-divider>
<CForm>
<CInput label="استان" horizontal disabled :value="user.province_name" />
<CInput label="شهر" horizontal disabled :value="user.city_name" />
<CTextarea label="آدرس" horizontal disabled rows="5" :value="user.address" />
<CInput label="کد پستی" horizontal disabled :value="user.postal_code" />
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminCustomerDatailsPage',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const user = await $axios.get(`/api/admin/user/${params.customer}`)
return {
user: user.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده پروفایل مشتری',
user: null,
newVerityInfo: {
verity_businessID: '',
verity_businessCode: ''
},
newPanatechInfo: {
panatech_businessID: '',
panatech_businessCode: ''
},
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
updateVerityInfo() {
this.validation = {}
this.$confirm(
'با تغییر کد مشتری و آیدی مشتری تمامی اطلاعات مشتری در سمت پنل کاربری مشتری تغییر خواهد کرد',
'هشدار',
{
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
}
)
.then(() => {
this.$axios
.put(`/api/admin/user/changeVerityInfo/${this.user._id}`, this.newVerityInfo)
.then(response => {
this.$message({
type: 'success',
message: 'اطالاعات جدید در سیستم ثبت شد'
})
this.newVerityInfo = {
verity_businessID: '',
verity_businessCode: ''
}
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err)
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
updatePanatechInfo() {
this.validation = {}
this.$confirm(
'با تغییر کد مشتری و آیدی مشتری تمامی اطلاعات مشتری در سمت پنل کاربری مشتری تغییر خواهد کرد',
'هشدار',
{
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
}
)
.then(() => {
this.$axios
.put(`/api/admin/user/changePanatechInfo/${this.user._id}`, this.newPanatechInfo)
.then(response => {
this.$message({
type: 'success',
message: 'اطالاعات جدید در سیستم ثبت شد'
})
this.newPanatechInfo = {
panatech_businessID: '',
panatech_businessCode: ''
}
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err)
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+194
View File
@@ -0,0 +1,194 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="12">
<CButtonGroup>
<CButton color="primary" :class="filterType === 'all' && 'selected'" @click="filterType = 'all'"
>همه</CButton
>
<CButton color="warning" :class="filterType === 'new' && 'selected'" @click="filterType = 'new'"
>جدیدها</CButton
>
<CButton
color="warning"
:class="filterType === 'customers' && 'selected'"
@click="filterType = 'customers'"
>مشتریان</CButton
>
<CButton color="success" :class="filterType === 'agents' && 'selected'" @click="filterType = 'agents'"
>نمایندگان</CButton
>
</CButtonGroup>
</CCol>
<CCol sm="12">
<el-divider></el-divider>
</CCol>
<CCol sm="12">
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="نام - شماره موبایل - کد ملی - کد مشتری - آیدی مشتری - استان - شهر"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table
v-loading="fetching"
:data="filteredItems"
:row-class-name="({ row, rowIndex }) => !row.seenByAdmin && 'unread'"
style="width: 100%"
>
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="نام" width="">
<template slot-scope="scope">
{{ scope.row.first_name + ' ' + scope.row.last_name }}
</template>
</el-table-column>
<el-table-column prop="national_code" label="کد ملی" width=""> </el-table-column>
<el-table-column prop="mobile_number" label="شماره موبایل" width=""> </el-table-column>
<el-table-column prop="verity_businessCode" label="کد مشتری (وریتی)" width=""> </el-table-column>
<el-table-column prop="verity_businessID" label="آیدی (وریتی)" width=""> </el-table-column>
<el-table-column prop="panatech_businessCode" label="کد مشتری (پاناتک)" width=""> </el-table-column>
<el-table-column prop="panatech_businessID" label="آیدی (پاناتک)" width=""> </el-table-column>
<el-table-column prop="province_name" label="استان" width=""> </el-table-column>
<el-table-column prop="city_name" label="شهر" width=""> </el-table-column>
<el-table-column prop="city_name" label="تاریخ ثبت نام" width="">
<template slot-scope="scope">
<span>{{ $jDate(scope.row.created_at) }}</span>
</template>
</el-table-column>
<el-table-column label="ویرایش" width="65" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-customers-customer', params: { customer: scope.row._id } }"
>
<i class="fal fa-edit"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminCustomersList',
layout: 'admin',
data() {
return {
title: 'مشتریان',
list_title: 'لیست',
users: [],
fetching: false,
filterText: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
filteredItems() {
const filterUsersByType = this.users.filter(item => {
if (this.filterType === 'all') return item
else if (this.filterType === 'new' && !item.seenByAdmin) return item
else if (this.filterType === 'customers' && !item.isAgent) return item
else if (this.filterType === 'agents' && item.isAgent) return item
else return null
})
const filterText = this.filterText
if (!this.filterText.length) return filterUsersByType
else {
return filterUsersByType.filter(item => {
return (
item.first_name.includes(filterText) ||
item.last_name.includes(filterText) ||
item.mobile_number.includes(filterText) ||
item.national_code.includes(filterText) ||
item.verity_businessID?.includes(filterText) ||
item.verity_businessCode?.includes(filterText) ||
item.panatech_businessID?.includes(filterText) ||
item.panatech_businessCode?.includes(filterText) ||
item.province_name?.includes(filterText) ||
item.city_name?.includes(filterText) ||
(item.first_name + ' ' + item.last_name).includes(filterText)
)
})
}
},
filterType: {
get() {
return this.$route.query?.filter
},
set(val) {
this.$router.push({ name: 'admin-customers', query: { filter: val } })
}
}
},
async mounted() {
try {
this.fetching = true
const users = await this.$axios.get('/api/admin/users')
this.users = users.data
this.fetching = false
} catch (err) {
this.$fetchError()
}
}
}
</script>
<style scopped lang="scss">
.selected {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
z-index: 2;
}
.unread {
background: rgba(orange, 0.1) !important;
}
</style>
+90
View File
@@ -0,0 +1,90 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="dCategory._creator && dCategory._creator.first_name" type="primary">
<span>ایجاد یا اصلاح کننده: </span>
<span> {{ dCategory._creator.first_name + ' ' + dCategory._creator.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-download-categories' }"
>برگشت به صفحه قبل</CButton
>
<CButton size="sm" color="success" style="margin-right: 10px" @click="upload">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="dCategory.name"
label="نام"
horizontal
:description="validation.name ? validation.name.msg : null"
:class="validation.name ? 'err' : null"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminDownloadCategoryDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const dCategory = await $axios.get(`/api/public/dCategory/${params.item}`)
return {
dCategory: dCategory.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'ویرایش دسته بندی',
dCategory: null,
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.validation = {}
this.$axios
.put(`/api/admin/dCategory/${this.dCategory._id}`, this.dCategory)
.then(response => {
if (response.data) {
this.$message({
message: 'آیتم با موفقیت بروزرسانی شد.',
type: 'success'
})
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
}
}
}
</script>
+104
View File
@@ -0,0 +1,104 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{ name: 'admin-download-categories-new' }" class="mr-auto"
>افزودن</CButton
>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="dCategories" 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="105" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="warning"
variant="outline"
:to="`/admin/download-categories/${scope.row._id}`"
>
<i class="fal fa-pencil"></i>
</CButton>
<CButton color="danger" variant="outline" @click="del(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminDownloadCategoryList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const dCategories = await $axios.get(`/api/public/dCategory`)
return {
dCategories: dCategories.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'دسته بندی دانلود',
list_title: 'لیست',
dCategories: null
}
},
head() {
return {
title: this.title
}
},
computed: {},
methods: {
del(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/dCategory/${id}`)
.then(response => {
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
this.dCategories = this.dCategories.filter(item => item._id !== id)
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+79
View File
@@ -0,0 +1,79 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-download-categories' }"
>برگشت به صفحه قبل</CButton
>
<CButton size="sm" color="success" style="margin-right: 10px" @click="upload">ایجاد</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="formData.name"
label="نام"
horizontal
:description="validation.name ? validation.name.msg : null"
:class="validation.name ? 'err' : null"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminAddNewDownloadCategory',
layout: 'admin',
data() {
return {
title: 'افزودن دسته بندی دانلود',
formData: {
name: ''
},
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.validation = {}
this.$axios
.post(`/api/admin/dCategory`, this.formData)
.then(response => {
if (response.data) {
this.$message({
message: 'آیتم با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push({ name: 'admin-download-categories' })
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
}
}
}
</script>
+370
View File
@@ -0,0 +1,370 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="download._creator && download._creator.first_name" type="primary">
<span>ایجاد یا اصلاح کننده: </span>
<span> {{ download._creator.first_name + ' ' + download._creator.last_name }} </span>
</el-tag>
<CButton
size="sm"
color="primary"
class="mr-auto"
:to="{ name: 'admin-downloads-page', params: { page: $route.params.page } }"
>برگشت به صفحه قبل</CButton
>
<CButton size="sm" color="success" style="margin-right: 10px" :disabled="pending" @click="upload"
>بروزرسانی</CButton
>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CSelect
label="دسته بندی"
placeholder="دسته بندی را انتخاب کنید"
horizontal
:options="mappedCategories(dCategories)"
:value.sync="download.category"
:description="validation.category ? validation.category.msg : null"
:class="validation.category ? 'err' : null"
>
</CSelect>
<CInput
v-model="download.title"
label="عنوان"
horizontal
:description="validation.title ? validation.title.msg : null"
:class="validation.title ? 'err' : null"
/>
<CTextarea
v-model="download.short_description"
label="توضیح کوتاه"
horizontal
rows="3"
:description="validation.short_description ? validation.short_description.msg : null"
:class="validation.short_description ? 'err' : null"
/>
<CRow form class="form-group" :class="validation.description ? 'err' : null">
<CCol tag="label" sm="3" class="col-form-label">توضیحات</CCol>
<CCol sm="9">
<client-only>
<ckeditor v-model="download.description" :config="editorConfig"></ckeditor>
</client-only>
<small v-if="validation.description" class="form-text text-muted w-100">
{{ validation.description.msg }}
</small>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardBody>
<h1>تصویر:</h1>
<el-divider />
<CRow>
<CCol col="12" class="mb-3">
<img :src="download.image" alt="" style="width: 100%; max-width: 500px" />
</CCol>
<CCol col="1">
<span>کاور</span>
</CCol>
<CCol col="11">
<input ref="image" type="file" @change="imagePreview" />
</CCol>
<CCol col="11" class="mr-auto mt-3">
<small v-if="validation.image" class="form-text alert-danger w-100">
{{ validation.image.msg }}
</small>
<small v-else class="form-text text-muted w-100">
بهتر است تصویر با فرمت png و پسزمینه شفاف باشد.
</small>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardHeader>
<i class="far fa-plus"></i>
<strong>افزودن فایل</strong>
</CCardHeader>
<CCardBody>
<CForm>
<CSelect
label="سیستم عامل"
placeholder="سیستم عامل را انتخاب کنید"
horizontal
:options="mappedOS(appOS)"
:value.sync="app.os"
:description="validation.os ? validation.os.msg : null"
:class="validation.os ? 'err' : null"
>
</CSelect>
<CInput
v-model="app.name"
label="نام"
horizontal
:description="validation.name ? validation.name.msg : null"
:class="validation.name ? 'err' : null"
/>
<CRow>
<CCol col="3">
<span>فایل برنامه</span>
</CCol>
<CCol col="9">
<input ref="file" type="file" />
</CCol>
<CCol col="9" class="mr-auto mt-3">
<small v-if="validation.file" class="form-text alert-danger w-100">
{{ validation.file.msg }}
</small>
</CCol>
</CRow>
<CButton color="success" class="mt-3" :disabled="pending" @click.prevent="addApp">افزودن</CButton>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardHeader>
<i class="fas fa-list"></i>
<strong>لیست فایل ها</strong>
</CCardHeader>
<CCardBody>
<CListGroup>
<CListGroupItem
v-for="(item, index) in download.files"
:key="item._id"
target="_blank"
download
:href="item.file"
:color="index % 2 ? 'light' : 'dark'"
>
<CRow>
<CCol col="11">
{{ item.name }}
</CCol>
<CCol col="1" style="text-align: left">
<i class="fas fa-trash-alt delete-btn" @click.prevent="delApp(item._id)"></i>
</CCol>
</CRow>
</CListGroupItem>
</CListGroup>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import axiosUploadProcess from '@/mixins/axiosUploadProcess'
export default {
name: 'AddminDownloadDetails',
mixins: [axiosUploadProcess],
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const dCategories = await $axios.get(`/api/public/dCategory`)
const download = await $axios.get(`/api/public/downloads/${params.item}`)
return {
dCategories: dCategories.data,
download: download.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'ویراش فایل',
dCategories: null,
download: null,
editorConfig: {
language: 'fa',
extraPlugins: ['bidi', 'justify']
},
app: {
name: '',
os: '',
file: ''
},
appOS: ['windows', 'linux', 'mac', 'android', 'ios'],
validation: {},
uploading: false,
uploadProgress: null,
pending: false
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.pending = true
this.validation = {}
const data = new FormData()
data.append('title', this.download.title)
data.append('short_description', this.download.short_description)
data.append('description', this.download.description)
data.append('category', this.download.category)
if (this.$refs.image.files[0]) data.append('image', this.$refs.image.files[0])
this.$axios
.put(`/api/admin/downloads/${this.download._id}`, data, this.axiosConfig)
.then(response => {
if (response.data) {
this.pending = false
this.$message({
message: 'آیتم با موفقیت بروزرسانی شد.',
type: 'success'
})
this.download = response.data
}
})
.catch(error => {
this.pending = false
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
addApp() {
this.pending = true
this.validation = {}
const data = new FormData()
data.append('page_id', this.download._id)
data.append('name', this.app.name)
data.append('os', this.app.os)
data.append('file', this.$refs.file.files[0])
this.$axios
.post(`/api/admin/downloads/file`, data, this.axiosConfig)
.then(response => {
this.pending = false
if (response.data) {
this.$message({
message: 'آیتم با موفقیت افزوده شد.',
type: 'success'
})
this.app = {
name: '',
os: '',
file: ''
}
this.$refs.file.value = null
this.download.files = response.data
}
})
.catch(error => {
this.pending = false
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
delApp(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/downloads/file/${id}`)
.then(response => {
this.download.files = this.download.files.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
imagePreview(event) {
this.download.image = URL.createObjectURL(event.target.files[0])
},
mappedCategories(arr) {
return arr.map(item => {
return {
label: item.name,
value: item._id
}
})
},
mappedOS(arr) {
return arr.map(item => {
return {
label: item,
value: item
}
})
}
}
}
</script>
<style scoped lang="scss">
.delete-btn {
transition: 0.1s;
-webkit-transition: 0.1s;
-moz-transition: 0.1s;
-ms-transition: 0.1s;
-o-transition: 0.1s;
padding: 5px 10px;
display: inline-block;
border: 1px solid transparent;
border-radius: 5px;
&:hover {
color: red;
border-color: red;
}
}
</style>
+139
View File
@@ -0,0 +1,139 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{ name: 'admin-downloads-new' }" class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader :dir="paginate ? 'ltr' : 'rtl'" :style="{ textAlign: paginate ? 'center' : 'right' }">
<el-pagination
v-if="paginate"
background
layout="prev, pager, next"
:current-page="Number($route.params.page)"
:page-count="Number(downloads.totalPages)"
@current-change="pageNumber"
>
</el-pagination>
<slot v-else name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="downloads.docs" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="کاور" width="170">
<template slot-scope="scope">
<el-image style="width: 100%; height: 100%" :src="scope.row.image" fit="fit"> </el-image>
</template>
</el-table-column>
<el-table-column label="دسته بندی">
<template slot-scope="scope">
{{ categoryName(scope.row.category) }}
</template>
</el-table-column>
<el-table-column prop="title" label="عنوان" width=""> </el-table-column>
<el-table-column prop="short_description" label="توضیح کوتاه" width=""> </el-table-column>
<el-table-column label="ویرایش" width="105" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="warning"
variant="outline"
:to="`/admin/downloads/${$route.params.page}/${scope.row._id}`"
>
<i class="fal fa-pencil"></i>
</CButton>
<CButton color="danger" variant="outline" @click="del(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminDownloadsList',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const dCategories = await $axios.get(`/api/public/dCategory`)
const downloads = await $axios.get(`/api/public/downloads/page/all/${params.page}`)
return {
dCategories: dCategories.data,
downloads: downloads.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'دانلود ها',
list_title: 'لیست',
dCategories: null,
downloads: null
}
},
head() {
return {
title: this.title
}
},
computed: {
paginate() {
return this.downloads.totalPages > 1
}
},
methods: {
categoryName(id) {
return this.dCategories.filter(item => item._id === id)[0].name
},
pageNumber(val) {
this.$router.push({ name: 'admin-downloads-page', params: { page: val } })
},
del(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/downloads/${id}`)
.then(response => {
this.downloads.docs = this.downloads.docs.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+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-downloads-page', params: { page: 1 } }"
>برگشت به صفحه قبل</CButton
>
<CButton size="sm" color="success" style="margin-right: 10px" :disabled="pending" @click="upload">ایجاد</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardHeader>
<strong class="alert-success d-block"
>ابتدا نام، توضیحات، دسته بندی و تصویر را افزوده سپس در مرحله بعد فایل ها رو اضافه کنید.</strong
>
</CCardHeader>
<CCardBody>
<CForm>
<CSelect
label="دسته بندی"
placeholder="دسته بندی را انتخاب کنید"
horizontal
:options="mappedCategories(dCategories)"
:value.sync="formData.category"
:description="validation.category ? validation.category.msg : null"
:class="validation.category ? 'err' : null"
>
</CSelect>
<CInput
v-model="formData.title"
label="عنوان"
horizontal
:description="validation.title ? validation.title.msg : null"
:class="validation.title ? 'err' : null"
/>
<CTextarea
v-model="formData.short_description"
label="توضیح کوتاه"
horizontal
rows="3"
:description="validation.short_description ? validation.short_description.msg : null"
:class="validation.short_description ? 'err' : null"
/>
<CRow form class="form-group" :class="validation.description ? 'err' : null">
<CCol tag="label" sm="3" class="col-form-label">توضیحات</CCol>
<CCol sm="9">
<client-only>
<ckeditor v-model="formData.description" :config="editorConfig"></ckeditor>
</client-only>
<small v-if="validation.description" class="form-text text-muted w-100">
{{ validation.description.msg }}
</small>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardBody>
<h1>تصویر:</h1>
<el-divider />
<CRow>
<CCol col="12" class="mb-3">
<img :src="formData.image" alt="" style="width: 100%; max-width: 500px" />
</CCol>
<CCol col="1">
<span>کاور</span>
</CCol>
<CCol col="11">
<input ref="image" type="file" @change="imagePreview" />
</CCol>
<CCol col="11" class="mr-auto mt-3">
<small v-if="validation.image" class="form-text alert-danger w-100">
{{ validation.image.msg }}
</small>
<small v-else class="form-text text-muted w-100">
بهتر است تصویر با فرمت png و پسزمینه شفاف باشد.
</small>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import axiosUploadProcess from '@/mixins/axiosUploadProcess'
export default {
name: 'AddminAddNewDownload',
mixins: [axiosUploadProcess],
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const dCategories = await $axios.get(`/api/public/dCategory`)
return {
dCategories: dCategories.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'افزودن فایل',
dCategories: null,
formData: {
title: '',
short_description: '',
description: '',
image: '',
category: ''
},
editorConfig: {
language: 'fa',
extraPlugins: ['bidi', 'justify']
},
validation: {},
pending: false
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.pending = true
this.validation = {}
const data = new FormData()
data.append('title', this.formData.title)
data.append('short_description', this.formData.short_description)
data.append('description', this.formData.description)
data.append('category', this.formData.category)
data.append('image', this.$refs.image.files[0])
this.$axios
.post(`/api/admin/downloads`, data, this.axiosConfig)
.then(response => {
if (response.data) {
this.pending = false
this.$message({
message: 'آیتم با موفقیت ثبت شد،میتوانید فایل ها رو اضافه کنید.',
type: 'success'
})
this.$router.push({ name: 'admin-downloads-page-item', params: { page: 1, item: response.data._id } })
}
})
.catch(error => {
this.pending = false
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
imagePreview(event) {
this.formData.image = URL.createObjectURL(event.target.files[0])
},
mappedCategories(arr) {
return arr.map(item => {
return {
label: item.name,
value: item._id
}
})
}
}
}
</script>
+93
View File
@@ -0,0 +1,93 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-faq' }">برگشت به صفحه قبل</CButton>
<CButton size="sm" color="success" style="margin-right: 10px" @click="upload">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="faq.question"
label="سوال"
horizontal
:description="validation.question ? validation.question.msg : null"
:class="validation.question ? 'err' : null"
/>
<CTextarea
v-model="faq.answer"
label="پاسخ"
horizontal
rows="3"
:description="validation.answer ? validation.answer.msg : null"
:class="validation.answer ? 'err' : null"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminFAQDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const faq = await $axios.get(`/api/public/faq/${params.item}`)
return {
faq: faq.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'ویرایش سوال متداول',
faq: null,
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.validation = {}
this.$axios
.put(`/api/admin/faq/${this.faq._id}`, this.faq)
.then(response => {
if (response.data) {
this.$message({
message: 'آیتم با موفقیت بروزرسانی شد.',
type: 'success'
})
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
}
}
}
</script>
+97
View File
@@ -0,0 +1,97 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{ name: 'admin-faq-new' }" class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="faqs" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="question" label="سوال" width=""> </el-table-column>
<el-table-column label="ویرایش" width="105" align="left">
<template slot-scope="scope">
<CButton :key="scope.row._id" color="warning" variant="outline" :to="`/admin/faq/${scope.row._id}`">
<i class="fal fa-pencil"></i>
</CButton>
<CButton color="danger" variant="outline" @click="del(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminFAQList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const faqs = await $axios.get(`/api/public/faq`)
return {
faqs: faqs.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'سوالات متداول',
list_title: 'لیست',
faqs: null
}
},
head() {
return {
title: this.title
}
},
computed: {},
methods: {
del(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/faq/${id}`)
.then(response => {
this.faqs = this.faqs.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+87
View File
@@ -0,0 +1,87 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-faq' }">برگشت به صفحه قبل</CButton>
<CButton size="sm" color="success" style="margin-right: 10px" @click="upload">ایجاد</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="formData.question"
label="سوال"
horizontal
:description="validation.question ? validation.question.msg : null"
:class="validation.question ? 'err' : null"
/>
<CTextarea
v-model="formData.answer"
label="پاسخ"
horizontal
rows="3"
:description="validation.answer ? validation.answer.msg : null"
:class="validation.answer ? 'err' : null"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminAddNewFAQ',
layout: 'admin',
data() {
return {
title: 'افزودن سوال متداول',
formData: {
question: '',
answer: ''
},
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.validation = {}
this.$axios
.post(`/api/admin/faq`, this.formData)
.then(response => {
if (response.data) {
this.$message({
message: 'آیتم با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push({ name: 'admin-faq' })
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
}
}
}
</script>
+117
View File
@@ -0,0 +1,117 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="guaranteeReport._openedBy && guaranteeReport._openedBy.first_name" type="primary" class="ml-1">
<span>اولین مشاهده توسط: </span>
<span> {{ guaranteeReport._openedBy.first_name + ' ' + guaranteeReport._openedBy.last_name }} </span>
</el-tag>
<el-tag v-if="guaranteeReport._updatedBy && guaranteeReport._updatedBy.first_name" type="primary" class="ml-1">
<span>تغییر وضعیت توسط: </span>
<span> {{ guaranteeReport._updatedBy.first_name + ' ' + guaranteeReport._updatedBy.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol lg="12">
<CCard>
<CCardBody>
<el-collapse>
<el-collapse-item title="مشخصات نماینده">
<CForm>
<CInput label="نام و نام خانوادگی" horizontal disabled :value="guaranteeReport.agent_id.full_name" />
<CInput label="کد ملی" horizontal disabled :value="guaranteeReport.agent_id.national_code" />
<CInput label="تلفن همراه" horizontal disabled :value="guaranteeReport.agent_id.mobile_number" />
<CInput label="تلفن شرکت/تعمیرگاه" horizontal disabled :value="guaranteeReport.agent_id.tel_number" />
<CInput label="فکس شرکت/تعمیرگاه" horizontal disabled :value="guaranteeReport.agent_id.fax_number" />
<CInput label="استان" horizontal disabled :value="guaranteeReport.agent_id.province_name" />
<CInput label="شهر" horizontal disabled :value="guaranteeReport.agent_id.city_name" />
<CInput label="آدرس" horizontal disabled :value="guaranteeReport.agent_id.address" />
<CInput label="کد پستی" horizontal disabled :value="guaranteeReport.agent_id.postal_code" />
<CInput label="نام شرکت/تعمیرگاه" horizontal disabled :value="guaranteeReport.agent_id.store_name" />
</CForm>
<el-divider></el-divider>
<div style="text-align: center">
<nuxt-link :to="{ name: 'admin-agents-agent', params: { agent: guaranteeReport.user_id } }"
>مشاهده اکانت نماینده</nuxt-link
>
</div>
</el-collapse-item>
</el-collapse>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<CForm>
<CTextarea label="توضیحات فرم" horizontal disabled rows="5" :value="guaranteeReport.description" />
</CForm>
<h6>لیست گزارش ها:</h6>
<el-divider></el-divider>
<el-table :data="guaranteeReport.items" style="width: 100%" stripe>
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="customerName" label="نام مشتری" width="120px"></el-table-column>
<el-table-column prop="customerTel" label="تلفن مشتری" width="110px"></el-table-column>
<el-table-column prop="ItemName" label="نام کالا" width="300px"></el-table-column>
<el-table-column prop="SerialNo1" label="سریال کالا" width="150px"></el-table-column>
<el-table-column prop="productIssue" label="ایراد کالا" width="350px"></el-table-column>
<el-table-column prop="usedPieces" label="قطعات صرفی" width="350px"></el-table-column>
<el-table-column prop="ItemName" label="تاریخ دریافت" width="100px">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.recieveDate) }} </span>
</template>
</el-table-column>
<el-table-column prop="ItemName" label="تاریخ تحویل" width="100px">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.deliverDate) }} </span>
</template>
</el-table-column>
</el-table>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminGuaranteeReportDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const guaranteeReport = await $axios.get(`/api/admin/gr/${params.grId}`)
return {
guaranteeReport: guaranteeReport.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده فرم گزارش گارانتی',
guaranteeReport: null,
validation: {}
}
},
head() {
return {
title: this.title
}
}
}
</script>
+128
View File
@@ -0,0 +1,128 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="12">
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="کد نماینده - شماره موبایل - استان - شهر"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="filteredItems"
:row-class-name="({ row, rowIndex }) => !row.seen && 'unread'"
style="width: 100%"
>
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="trackingCode" label="کد پیگیری" width=""> </el-table-column>
<el-table-column prop="description" label="توضیحات" width=""> </el-table-column>
<el-table-column prop="agent_id.full_name" label="نام" width=""> </el-table-column>
<el-table-column prop="agent_id.mobile_number" label="شماره موبایل" width=""> </el-table-column>
<el-table-column prop="agent_id.agent_code" label="کد نماینده" width=""> </el-table-column>
<el-table-column prop="agent_id.province_name" label="استان" width=""> </el-table-column>
<el-table-column prop="agent_id.city_name" label="شهر" width=""> </el-table-column>
<el-table-column label="مشاهده" width="70" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-guarantee-reports-grId', params: { grId: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminGuaranteeReportsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const grList = await $axios.get('/api/admin/grList')
return {
grList: grList.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'لیست گزارش عملکرد گارانتی نمایندگان',
list_title: 'لیست',
grList: null,
filterText: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
filteredItems() {
const filterText = this.filterText.toLowerCase()
if (!filterText.length) return this.grList
else
return this.grList.filter(item => {
return (
item.agent_id.agent_code.toLowerCase().includes(filterText) ||
item.agent_id.full_name.toLowerCase().includes(filterText) ||
item.agent_id.mobile_number.toLowerCase().includes(filterText) ||
item.agent_id.province_name.toLowerCase().includes(filterText) ||
item.agent_id.city_name.toLowerCase().includes(filterText)
)
})
}
}
}
</script>
<style scopped lang="scss">
.unread {
background: rgba(orange, 0.1) !important;
}
</style>
+102
View File
@@ -0,0 +1,102 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="help._creator && help._creator.first_name" type="primary">
<span>ایجاد یا اصلاح کننده: </span>
<span> {{ help._creator.first_name + ' ' + help._creator.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin' }">برگشت به صفحه داشبورد</CButton>
<CButton size="sm" color="success" style="margin-right: 10px" :disabled="pending" @click="upload"
>بروزرسانی</CButton
>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CRow form class="form-group" :class="validation.description && 'err'">
<CCol tag="label" sm="12" class="col-form-label">صفحه آموزش ثبت گارانتی را انتخاب کنید</CCol>
<CCol sm="12">
<el-select v-model="help.helpId" filterable style="width: 100%">
<el-option v-for="item in learnings" :key="item._id" :label="item.title" :value="item._id" />
</el-select>
<small v-if="validation.helpId" class="form-text text-muted w-100">
{{ validation.helpId.msg }}
</small>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminHelp',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const help = await $axios.get(`/api/public/help`)
const learnings = await $axios.get(`/api/public/learning/page/all`)
return {
help: help.data || {
helpId: ''
},
learnings: learnings.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'راهنمای ثبت گارانتی',
help: null,
learnings: null,
validation: {},
pending: false
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.pending = true
this.validation = {}
this.$axios
.put(`/api/admin/help`, this.help)
.then(response => {
this.pending = false
if (response.data) {
this.$message({
message: 'صفحه با موفقیت بروزرسانی شد.',
type: 'success'
})
}
})
.catch(error => {
this.pending = false
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
}
}
}
</script>
+34
View File
@@ -0,0 +1,34 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCol sm="6">
<CCard>
<CCardHeader>
<strong>صفحه اصلی</strong>
</CCardHeader>
<CCardBody>
<h1>به پنل مدیریت خوش آمدید.</h1>
</CCardBody>
</CCard>
</CCol>
</div>
</template>
<script>
export default {
name: 'AdminDashboard',
layout: 'admin',
data() {
return {
title: 'صفحه اصلی'
}
},
head() {
return {
title: this.title
}
}
}
</script>
+191
View File
@@ -0,0 +1,191 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="learning._creator && learning._creator.first_name" type="primary">
<span>ایجاد یا اصلاح کننده: </span>
<span> {{ learning._creator.first_name + ' ' + learning._creator.last_name }} </span>
</el-tag>
<CButton
size="sm"
color="primary"
class="mr-auto"
:to="{ name: 'admin-learning-page', params: { page: $route.params.page } }"
>برگشت به صفحه قبل</CButton
>
<CButton size="sm" color="success" style="margin-right: 10px" :disabled="pending" @click="upload"
>بروزرسانی</CButton
>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="learning.title"
label="عنوان"
horizontal
:description="validation.title ? validation.title.msg : null"
:class="validation.title ? 'err' : null"
/>
<CTextarea
v-model="learning.short_description"
label="توضیح کوتاه"
horizontal
rows="4"
:description="validation.short_description ? validation.short_description.msg : null"
:class="validation.short_description ? 'err' : null"
/>
<CRow form class="form-group" :class="validation.description ? 'err' : null">
<CCol tag="label" sm="3" class="col-form-label">توضیحات</CCol>
<CCol sm="9">
<client-only>
<ckeditor v-model="learning.description" :config="editorConfig"></ckeditor>
</client-only>
<small v-if="validation.description" class="form-text text-muted w-100">
{{ validation.description.msg }}
</small>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardBody>
<h1>تصویر:</h1>
<el-divider />
<CRow>
<CCol col="12" class="mb-3">
<img :src="learning.cover" alt="" style="width: 100%; max-width: 500px" />
</CCol>
<CCol col="1">
<span>کاور</span>
</CCol>
<CCol col="11">
<input ref="cover" type="file" @change="imagePreview" />
</CCol>
<CCol col="11" class="mr-auto mt-3">
<small v-if="validation.cover" class="form-text alert-danger w-100">
{{ validation.cover.msg }}
</small>
</CCol>
</CRow>
<h1 class="mt-5">ویدیو:</h1>
<el-divider />
<CRow>
<CCol v-if="learning.video" col="12" class="mb-3">
<video :src="learning.video" controls autoplay muted style="width: 100%"></video>
</CCol>
<CCol col="1">
<span>ویدیو</span>
</CCol>
<CCol col="11">
<input ref="video" type="file" @change="videoPreview" />
</CCol>
<CCol col="11" class="mr-auto mt-3">
<small v-if="validation.video" class="form-text alert-danger w-100">
{{ validation.video.msg }}
</small>
<small v-else class="form-text text-muted w-100">
فایل ویدیو را انتخاب کنید.(ویدیو اجباری نیست)
<br />
فرمت های قابل قبول: mp4 wmv avi
</small>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import axiosUploadProcess from '@/mixins/axiosUploadProcess'
export default {
name: 'AddminLearningDetails',
mixins: [axiosUploadProcess],
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const learning = await $axios.get(`/api/public/learning/${params.item}`)
return {
learning: learning.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'ویرایش آموزش',
learning: null,
editorConfig: {
language: 'fa',
extraPlugins: ['bidi', 'justify']
},
validation: {},
pending: false
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.pending = true
this.validation = {}
const data = new FormData()
data.append('title', this.learning.title)
data.append('short_description', this.learning.short_description)
data.append('description', this.learning.description)
if (this.$refs.cover.files[0]) data.append('cover', this.$refs.cover.files[0])
if (this.$refs.video.files[0]) data.append('video', this.$refs.video.files[0])
this.$axios
.put(`/api/admin/learning/${this.learning._id}`, data, this.axiosConfig)
.then(response => {
this.pending = false
if (response.data) {
this.$message({
message: 'آیتم با موفقیت بروزرسانی شد.',
type: 'success'
})
this.$refs.cover.value = null
this.$refs.video.value = null
this.learning = response.data
}
})
.catch(error => {
this.pending = false
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
imagePreview(event) {
this.learning.cover = URL.createObjectURL(event.target.files[0])
},
videoPreview(event) {
this.learning.video = URL.createObjectURL(event.target.files[0])
}
}
}
</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-learning-new' }" class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader :dir="paginate ? 'ltr' : 'rtl'" :style="{ textAlign: paginate ? 'center' : 'right' }">
<el-pagination
v-if="paginate"
background
layout="prev, pager, next"
:current-page="Number($route.params.page)"
:page-count="Number(learning.totalPages)"
@current-change="pageNumber"
>
</el-pagination>
<slot v-else name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="learning.docs" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="کاور" width="170">
<template slot-scope="scope">
<el-image style="width: 100%; height: 100%" :src="scope.row.thumb" fit="fit"> </el-image>
</template>
</el-table-column>
<el-table-column prop="title" label="عنوان" width=""> </el-table-column>
<el-table-column prop="short_description" label="توضیح کوتاه" width=""> </el-table-column>
<el-table-column label="ویرایش" width="105" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="warning"
variant="outline"
:to="`/admin/learning/${$route.params.page}/${scope.row._id}`"
>
<i class="fal fa-pencil"></i>
</CButton>
<CButton color="danger" variant="outline" @click="del(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminLearningsList',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const learning = await $axios.get(`/api/public/learning/page/${params.page}`)
return {
learning: learning.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'آموزش ها',
list_title: 'لیست',
learning: null
}
},
head() {
return {
title: this.title
}
},
computed: {
paginate() {
return this.learning.totalPages > 1
}
},
methods: {
pageNumber(val) {
this.$router.push({ name: 'admin-learning-page', params: { page: val } })
},
del(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/learning/${id}`)
.then(response => {
this.learning.docs = this.learning.docs.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+175
View File
@@ -0,0 +1,175 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-learning-page', params: { page: 1 } }"
>برگشت به صفحه قبل</CButton
>
<CButton size="sm" color="success" style="margin-right: 10px" :disabled="pending" @click="upload">ایجاد</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="formData.title"
label="عنوان"
horizontal
:description="validation.title ? validation.title.msg : null"
:class="validation.title ? 'err' : null"
/>
<CTextarea
v-model="formData.short_description"
label="توضیح کوتاه"
horizontal
rows="4"
:description="validation.short_description ? validation.short_description.msg : null"
:class="validation.short_description ? 'err' : null"
/>
<CRow form class="form-group" :class="validation.description ? 'err' : null">
<CCol tag="label" sm="3" class="col-form-label">توضیحات</CCol>
<CCol sm="9">
<client-only>
<ckeditor v-model="formData.description" :config="editorConfig"></ckeditor>
</client-only>
<small v-if="validation.description" class="form-text text-muted w-100">
{{ validation.description.msg }}
</small>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardBody>
<h1>تصویر:</h1>
<el-divider />
<CRow>
<CCol col="12" class="mb-3">
<img :src="formData.cover" alt="" style="width: 100%; max-width: 500px" />
</CCol>
<CCol col="1">
<span>کاور</span>
</CCol>
<CCol col="11">
<input ref="cover" type="file" @change="imagePreview" />
</CCol>
<CCol col="11" class="mr-auto mt-3">
<small v-if="validation.cover" class="form-text alert-danger w-100">
{{ validation.cover.msg }}
</small>
</CCol>
</CRow>
<h1 class="mt-5">ویدیو:</h1>
<el-divider />
<CRow>
<CCol v-if="formData.video" col="12" class="mb-3">
<video :src="formData.video" controls autoplay muted style="width: 100%"></video>
</CCol>
<CCol col="1">
<span>ویدیو</span>
</CCol>
<CCol col="11">
<input ref="video" type="file" @change="videoPreview" />
</CCol>
<CCol col="11" class="mr-auto mt-3">
<small v-if="validation.video" class="form-text alert-danger w-100">
{{ validation.video.msg }}
</small>
<small v-else class="form-text text-muted w-100">
فایل ویدیو را انتخاب کنید.(ویدیو اجباری نیست)
<br />
فرمت های قابل قبول: mp4 wmv avi
</small>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import axiosUploadProcess from '@/mixins/axiosUploadProcess'
export default {
name: 'AddminAddNewLearnning',
mixins: [axiosUploadProcess],
layout: 'admin',
data() {
return {
title: 'افزودن آموزش',
formData: {
title: '',
short_description: '',
description: '',
cover: '',
video: ''
},
editorConfig: {
language: 'fa',
extraPlugins: ['bidi', 'justify']
},
validation: {},
pending: false
}
},
head() {
return {
title: this.title
}
},
methods: {
upload() {
this.pending = true
this.validation = {}
const data = new FormData()
data.append('title', this.formData.title)
data.append('short_description', this.formData.short_description)
data.append('description', this.formData.description)
data.append('cover', this.$refs.cover.files[0])
if (this.$refs.video.files[0]) data.append('video', this.$refs.video.files[0])
this.$axios
.post(`/api/admin/learning`, data, this.axiosConfig)
.then(response => {
this.pending = false
if (response.data) {
this.$message({
message: 'آیتم با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push({ name: 'admin-learning-page', params: { page: 1 } })
}
})
.catch(error => {
this.pending = false
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
imagePreview(event) {
this.formData.cover = URL.createObjectURL(event.target.files[0])
},
videoPreview(event) {
this.formData.video = URL.createObjectURL(event.target.files[0])
}
}
}
</script>
+324
View File
@@ -0,0 +1,324 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-lottery' }">برگشت به صفحه قبل</CButton>
<CButton v-if="$route.params.lottery === 'new'" size="sm" color="success" style="margin-right: 10px" @click="add"
>افزودن</CButton
>
<CButton
v-if="$route.params.lottery !== 'new' && !lottery.expired"
size="sm"
color="success"
style="margin-right: 10px"
@click="update"
>بروزرسانی</CButton
>
</CustomSubHeader>
<CRow>
<CCol xl="12">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="lottery.title"
label="عنوان قرعه کشی"
horizontal
:description="validation.title ? validation.title.msg : null"
:disabled="lottery.expired"
:class="validation.title ? 'err' : null"
/>
<CInput
v-model="lottery.winnersCount"
label="تعداد شانس برنده شدن"
horizontal
:disabled="lottery.expired"
:description="validation.winnersCount ? validation.winnersCount.msg : null"
:class="validation.winnersCount ? 'err' : null"
/>
</CForm>
<el-divider></el-divider>
<h6>تاریخ اتمام قرعه کشی</h6>
<persian-date-picker
v-model="expireDate"
display-format="jYYYY-jMM-jDD"
:min="today"
format="x"
:disabled="lottery.expired"
placeholder="تاریخ را انتخاب کنید"
color="#065495"
/>
<p v-if="validation.expireDate" class="text-danger">{{ validation.expireDate.msg }}</p>
</CCardBody>
</CCard>
</CCol>
<CCol xl="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<h6>عکس بکگراند صفحه شرکت در قرعه کشی</h6>
<el-divider></el-divider>
<CRow>
<CCol col="12">
<el-alert v-if="!lottery.expired" type="warning" class="mb-3">
توجه داشته باشید طول و عرض صفحه قرعه کشی به اندازه ی طول و عرض عکسی که آپلود میکنید نمایش داده
میشود. ابعاد توصیه شده 400*700 پیکسل میباشد.
</el-alert>
</CCol>
<CCol col="12" class="mb-3">
<img :src="lottery.entryBgImg" alt="" style="width: 100%" />
</CCol>
<template v-if="!lottery.expired">
<CCol col="auto">
<span>بکگراند</span>
</CCol>
<CCol col="auto">
<input ref="entryBgImg" type="file" @change="imagePreview1" />
</CCol>
<CCol col="12" class="mt-3">
<small v-if="validation.entryBgImg" class="form-text alert-danger w-100">
{{ validation.entryBgImg.msg }}
</small>
</CCol>
</template>
</CRow>
</CCol>
<CCol>
<h6>عکس بکگراند صفحه نتایج قرعه کشی</h6>
<el-divider></el-divider>
<CRow>
<CCol col="12">
<el-alert v-if="!lottery.expired" type="warning" class="mb-3">
توجه داشته باشید طول و عرض صفحه نتایج قرعه کشی به اندازه ی طول و عرض عکسی که آپلود میکنید نمایش
داده میشود. ابعاد توصیه شده 400*700 پیکسل میباشد.
</el-alert>
</CCol>
<CCol col="12" class="mb-3">
<img :src="lottery.resultBgImg" alt="" style="width: 100%" />
</CCol>
<template v-if="!lottery.expired">
<CCol col="auto">
<span>بکگراند</span>
</CCol>
<CCol col="auto">
<input ref="resultBgImg" type="file" @change="imagePreview2" />
</CCol>
<CCol col="12" class="mt-3">
<small v-if="validation.resultBgImg" class="form-text alert-danger w-100">
{{ validation.resultBgImg.msg }}
</small>
</CCol>
</template>
</CRow>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<CCol v-if="lottery.expired" xl="12">
<CCard>
<CCardBody>
<h3>لیست برندگان قرعه کشی</h3>
<el-divider></el-divider>
<el-table :data="lottery.winnersList" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="fullName" label="نام و نام خانوادگی" width=""> </el-table-column>
<el-table-column prop="mobile" label="شماره تلفن همراه" width="">
<template slot-scope="scope">
<a :href="'tel:' + scope.row.mobile" style="display: inline-block; direction: ltr">{{
scope.row.mobile
}}</a>
</template>
</el-table-column>
<el-table-column prop="serial" label="شماره سریال گارانتی" width=""> </el-table-column>
<el-table-column prop="enrollCode" label="کد پیگیری قرعه کشی" width=""> </el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
<CCol v-if="$route.params.lottery !== 'new'" xl="12">
<CCard>
<CCardBody>
<h3 style="color: #000">
<span>لیست شرکت کنندگان: </span>
<span>(</span>
<span> {{ lottery.participants.length }} </span>
<span>شرکت کننده</span>
<span>)</span>
</h3>
<el-divider></el-divider>
<el-table :data="lottery.participants" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="fullName" label="نام و نام خانوادگی" width=""> </el-table-column>
<el-table-column prop="mobile" label="شماره تلفن همراه" width="">
<template slot-scope="scope">
<a :href="'tel:' + scope.row.mobile" style="display: inline-block; direction: ltr">{{
scope.row.mobile
}}</a>
</template>
</el-table-column>
<el-table-column prop="serial" label="شماره سریال گارانتی" width=""> </el-table-column>
<el-table-column prop="enrollCode" label="کد پیگیری قرعه کشی" width=""> </el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminLotteryDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
if (params.lottery !== 'new') {
const lottery = await $axios.get(`/api/admin/lottery/${params.lottery}`)
return {
lottery: lottery.data
}
} else {
return {
lottery: {
entryBgImg: '',
resultBgImg: '',
title: '',
resultTxt: '',
winnersCount: 1,
expireDate: Date.now()
}
}
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
lottery: null,
validation: {}
}
},
head() {
return {
title: this.title
}
},
computed: {
title() {
if (this.$route.params.lottery === 'new') {
return 'افزودن قرعه کشی'
} else if (this.$route.params.lottery !== 'new' && this.lottery.expired) {
return 'مشاهده نتیجه قرعه کشی'
} else {
return 'ویرایش قرعه کشی'
}
},
today() {
return Date.now().toString()
},
expireDate: {
get() {
return this.lottery.expireDate.toString()
},
set(val) {
this.lottery.expireDate = val
}
}
},
methods: {
add() {
this.validation = {}
const data = new FormData()
data.append('title', this.lottery.title)
data.append('winnersCount', this.lottery.winnersCount)
data.append('resultTxt', this.lottery.resultTxt)
data.append('expireDate', this.lottery.expireDate)
if (this.$refs.entryBgImg.files[0]) data.append('entryBgImg', this.$refs.entryBgImg.files[0])
if (this.$refs.resultBgImg.files[0]) data.append('resultBgImg', this.$refs.resultBgImg.files[0])
this.$axios
.post(`/api/admin/lottery`, data)
.then(response => {
if (response.data) {
this.$message({
message: 'قرعه کشی با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push({ name: 'admin-lottery' })
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
update() {
this.validation = {}
const data = new FormData()
data.append('title', this.lottery.title)
data.append('winnersCount', this.lottery.winnersCount)
data.append('expireDate', this.lottery.expireDate)
if (this.$refs.entryBgImg.files[0]) data.append('entryBgImg', this.$refs.entryBgImg.files[0])
if (this.$refs.resultBgImg.files[0]) data.append('resultBgImg', this.$refs.resultBgImg.files[0])
this.$axios
.put(`/api/admin/lottery/${this.lottery._id}`, data)
.then(response => {
if (response.data) {
this.$message({
message: 'قرعه کشی با موفقیت بروزرسانی شد.',
type: 'success'
})
this.$nuxt.refresh()
this.$refs.entryBgImg.value = null
this.$refs.resultBgImg.value = null
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
imagePreview1(event) {
this.lottery.entryBgImg = URL.createObjectURL(event.target.files[0])
},
imagePreview2(event) {
this.lottery.resultBgImg = URL.createObjectURL(event.target.files[0])
}
}
}
</script>
+148
View File
@@ -0,0 +1,148 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton
size="sm"
color="success"
:to="{ name: 'admin-lottery-lottery', params: { lottery: 'new' } }"
class="mr-auto"
>افزودن</CButton
>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<el-input v-model="search" size="mini" clearable placeholder="کد پیگیری برنده را وارد کنید" />
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="filteredLotteries" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="title" label="عنوان قرعه کشی" width=""> </el-table-column>
<el-table-column prop="winnersCount" label="تعداد شانس برنده شدن" width=""> </el-table-column>
<el-table-column label="تاریخ ایجاد" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.created_at) }} </span>
</template>
</el-table-column>
<el-table-column label="تاریخ پایان" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.expireDate) }} </span>
</template>
</el-table-column>
<el-table-column label="تعداد شرکت کنندگان" width="">
<template slot-scope="scope">
<span> {{ scope.row.participants.length }} </span>
</template>
</el-table-column>
<el-table-column prop="expired" label="وضعیت قرعه کشی" width="">
<template slot-scope="scope">
<el-tag v-if="scope.row.expired" type="info">بسته شده</el-tag>
<el-tag v-else type="success">باز</el-tag>
</template>
</el-table-column>
<el-table-column label="ویرایش" width="105" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
:color="scope.row.expired ? 'success' : 'warning'"
variant="outline"
:to="{ name: 'admin-lottery-lottery', params: { lottery: scope.row._id } }"
>
<i v-if="scope.row.expired" class="fal fa-eye"></i>
<i v-else class="fal fa-pencil"></i>
</CButton>
<CButton color="danger" variant="outline" @click="del(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminLotteryList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const lotteries = await $axios.get(`/api/admin/lotteries`)
return {
lotteries: lotteries.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'لیست قرعه کشی ها',
list_title: 'لیست',
lotteries: null,
search: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
filteredLotteries() {
if (this.search.length) {
const filteredArray = []
for (const lottery of this.lotteries) {
for (const winner of lottery.winnersList) {
if (winner.enrollCode.toLowerCase() === this.search.toLowerCase()) filteredArray.push(lottery)
}
}
return filteredArray
} else return this.lotteries
}
},
methods: {
del(id) {
this.$confirm('این قرعه کشی حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/lottery/${id}`)
.then(response => {
this.lotteries = this.lotteries.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'قرعه کشی حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+147
View File
@@ -0,0 +1,147 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
<CButton size="sm" color="success" class="mr-1" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol sm="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<h6>موقعیت و ابعاد دکمه در صفحه</h6>
<el-divider></el-divider>
<el-switch v-model="lotteryPopUp.visible" style="direction: ltr" active-text="نمایش دکمه روی صفحه" />
<el-divider></el-divider>
<CForm>
<CInput
v-model="lotteryPopUp.x"
label="موقعیت افقی از سمت چپ صفحه (به پیکسل)"
horizontal
:class="validation.x && 'err'"
:description="validation.x && validation.x.msg"
/>
<CInput
v-model="lotteryPopUp.y"
label="موقعیت عمودی از سمت پایین صفحه (به پیکسل)"
horizontal
:class="validation.y && 'err'"
:description="validation.y && validation.y.msg"
/>
</CForm>
</CCol>
<CCol>
<h6>تغییر عکس بکگراند دکمه</h6>
<el-divider></el-divider>
<CRow>
<CCol col="12">
<el-alert type="warning" class="mb-3">
توجه داشته باشید طول و عرض دکمه به اندازه ی طول و عرض عکسی که آپلود میکنید نمایش داده میشود. ابعاد
توصیه شده 100*100 پیکسل میباشد.
</el-alert>
</CCol>
<CCol col="12" class="mb-3">
<img :src="lotteryPopUp.bgImg" alt="" :style="imgStyle" />
</CCol>
<CCol col="auto">
<span>بکگراند</span>
</CCol>
<CCol col="auto">
<input ref="image" type="file" @change="imagePreview" />
</CCol>
<CCol col="12" class="mt-3">
<small v-if="validation.bgImg" class="form-text alert-danger w-100">
{{ validation.bgImg.msg }}
</small>
<small v-else class="form-text text-muted w-100">
بهتر است تصویر با فرمت png و پسزمینه شفاف باشد.
</small>
</CCol>
</CRow>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminLotterPopUp',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const lotteryPopUp = await $axios.get(`/api/public/lotteryPopup`)
return {
lotteryPopUp: lotteryPopUp.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'تغییر وضعیت ظاهری دکمه قرعه کشی',
lotteryPopUp: null,
validation: {}
}
},
head() {
return {
title: this.title
}
},
computed: {
imgStyle() {
return {
width: this.lotteryPopUp.w,
height: this.lotteryPopUp.h
}
}
},
methods: {
update() {
this.validation = {}
const popup = this.lotteryPopUp
const data = new FormData()
data.append('visible', popup.visible)
data.append('x', popup.x)
data.append('y', popup.y)
if (this.$refs.image.files[0]) data.append('bgImg', this.$refs.image.files[0])
this.$axios
.put('/api/admin/lotteryPopUp', data)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$refs.image.value = null
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.status === 422) {
this.validation = err.response.data.validation
this.$message({
type: 'warning',
message: 'پارامترها را بررسی و دوباره تلاش کنید'
})
} else
this.$message({
type: 'error',
message: 'مشکلی در ثبت اطلاعات پیش آمده'
})
})
},
imagePreview(event) {
this.lotteryPopUp.bgImg = URL.createObjectURL(event.target.files[0])
}
}
}
</script>
+239
View File
@@ -0,0 +1,239 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="oldPieceRequest._openedBy && oldPieceRequest._openedBy.first_name" type="primary" class="ml-1">
<span>اولین مشاهده توسط: </span>
<span> {{ oldPieceRequest._openedBy.first_name + ' ' + oldPieceRequest._openedBy.last_name }} </span>
</el-tag>
<el-tag v-if="oldPieceRequest._updatedBy && oldPieceRequest._updatedBy.first_name" type="primary" class="ml-1">
<span>تغییر وضعیت توسط: </span>
<span> {{ oldPieceRequest._updatedBy.first_name + ' ' + oldPieceRequest._updatedBy.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol v-if="!oldPieceRequest.archived && oldPieceRequest.status !== 'rejected'" lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol lg="6">
<h6>تغییر وضعیت فرم</h6>
<el-divider></el-divider>
<CButtonGroup>
<!-- <CButton
:color="oldPieceRequest.status === 'ongoing' ? 'warning' : 'light'"
@click="updateStatus('ongoing')"
>
در دست اقدام
</CButton> -->
<CButton
:color="oldPieceRequest.status === 'waiting' ? 'warning' : 'light'"
@click="updateStatus('waiting')"
>
در انتظار قطعه
</CButton>
<el-popover
v-model="deliverPopover"
placement="bottom"
width="160"
:disabled="oldPieceRequest.status === 'delivered'"
@click="deliveryPopover = true"
>
<el-input v-model="deliveryCode" placeholder="کد ارسال مرسوله"></el-input>
<div class="mt-1" style="text-align: center">
<el-button
size="mini"
type="text"
class="agentsStatus-popover-insideBtn"
@click="updateStatus('delivered')"
>ارسال</el-button
>
</div>
<CButton slot="reference" :color="oldPieceRequest.status === 'delivered' ? 'success' : 'light'">
تحویل شده
</CButton>
</el-popover>
</CButtonGroup>
<div v-if="oldPieceRequest.status === 'delivered'" class="mt-3">
<p>
<span>کد ارسال مرسوله: </span>
<b>{{ oldPieceRequest.deliveryCode || '-' }} </b>
</p>
</div>
</CCol>
<CCol lg="6">
<h6>تاریخچه وضعیت های فرم</h6>
<el-divider></el-divider>
<el-table :data="oldPieceRequest.statusHistory" style="width: 100%">
<el-table-column prop="name" label="وضعیت">
<template slot-scope="scope">
<span v-if="scope.row.status === 'temp'">پیشنویس</span>
<span v-if="scope.row.status === 'sent'">ارسال</span>
<span v-if="scope.row.status === 'ongoing'">در دست اقدام</span>
<span v-if="scope.row.status === 'waiting'">در انتظار قطعه</span>
<span v-if="scope.row.status === 'delivered'">تحویل شده</span>
</template>
</el-table-column>
<el-table-column prop="date" label="تاریخ">
<template slot-scope="scope">
<span style="display: inline-block; direction: ltr">{{ $jDateTime(scope.row.date) }}</span>
</template>
</el-table-column>
</el-table>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<el-collapse>
<el-collapse-item title="مشخصات نماینده">
<CForm>
<CInput label="نام و نام خانوادگی" horizontal disabled :value="oldPieceRequest.agent_id.full_name" />
<CInput label="کد ملی" horizontal disabled :value="oldPieceRequest.agent_id.national_code" />
<CInput label="تلفن همراه" horizontal disabled :value="oldPieceRequest.agent_id.mobile_number" />
<CInput label="تلفن شرکت/تعمیرگاه" horizontal disabled :value="oldPieceRequest.agent_id.tel_number" />
<CInput label="فکس شرکت/تعمیرگاه" horizontal disabled :value="oldPieceRequest.agent_id.fax_number" />
<CInput label="استان" horizontal disabled :value="oldPieceRequest.agent_id.province_name" />
<CInput label="شهر" horizontal disabled :value="oldPieceRequest.agent_id.city_name" />
<CInput label="آدرس" horizontal disabled :value="oldPieceRequest.agent_id.address" />
<CInput label="کد پستی" horizontal disabled :value="oldPieceRequest.agent_id.postal_code" />
<CInput label="نام شرکت/تعمیرگاه" horizontal disabled :value="oldPieceRequest.agent_id.store_name" />
</CForm>
<el-divider></el-divider>
<div style="text-align: center">
<nuxt-link :to="{ name: 'admin-agents-agent', params: { agent: oldPieceRequest.agent_id._id } }"
>مشاهده اکانت نماینده</nuxt-link
>
</div>
</el-collapse-item>
</el-collapse>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<CForm>
<CTextarea label="توضیحات فرم" horizontal disabled rows="5" :value="oldPieceRequest.description" />
</CForm>
<h6>لیست قطعات داغی درخواستی:</h6>
<el-divider></el-divider>
<el-table :data="oldPieceRequest.items" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="تاریخ پذیرش" width="">
<template slot-scope="scope">
<a :href="scope.row.url" target="_blank" :download="scope.row.name">{{ scope.row.name }}</a>
</template>
</el-table-column>
<el-table-column prop="ItemName" label="نام کالا" width=""></el-table-column>
<el-table-column label="سریال گارانتی" width="">
<template slot-scope="scope">
<span> {{ scope.row.SerialNo1 || '-' }} </span>
</template>
</el-table-column>
<el-table-column prop="pieceName" label="نام قطعه" width=""></el-table-column>
<el-table-column prop="pieceCode" label="کد قطعه" width=""></el-table-column>
</el-table>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminOldPieceRequestDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const oldPieceRequest = await $axios.get(`/api/admin/opr/${params.oprId}`)
return {
oldPieceRequest: oldPieceRequest.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده درخواست قطعه داغی',
oldPieceRequest: null,
deliverPopover: false,
deliveryCode: '',
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
updateStatus(status) {
if (status === this.oldPieceRequest.status) return
if (this.oldPieceRequest.status === 'delivered') return
const title = 'هشدار'
function getMsg() {
const msg1 = 'با تغییر وضعیت فرم به در انتظار قطعه بلافاصله پیامک اطلاع رسانی برای نماینده ارسال خواهد شد'
const msg2 =
'با تغییر وضعیت فرم به تحویل شده بلافاصله پیامک اطلاع رسانی برای نماینده ارسال خواهد شد. توجه داشته باشید بعدا نمیتوانید کد ارسال مرسوله را تغییر دهید.'
if (status === 'ongoing') return msg1
else return msg2
}
this.$confirm(getMsg(), title, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.put(`/api/admin/oprStatus/${this.oldPieceRequest._id}`, { status, deliveryCode: this.deliveryCode })
.then(response => {
this.$message({
type: 'success',
message: response.data.message
})
this.deliveryCode = ''
this.$nuxt.refresh()
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+219
View File
@@ -0,0 +1,219 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="12">
<CButtonGroup>
<CButton
:color="filterType === 'all' ? 'primary' : 'light'"
:class="filterType === 'all' && 'selected'"
@click="filterType = 'all'"
>
<span>همه</span>
<span> ({{ oprList.length }}) </span>
</CButton>
<CButton
:color="filterType === 'sent' ? 'primary' : 'light'"
:class="filterType === 'sent' && 'selected'"
@click="filterType = 'sent'"
>
<span>جدید</span>
<span> ({{ getListCountByStatus('sent') }}) </span>
</CButton>
<CButton
:color="filterType === 'ongoing' ? 'primary' : 'light'"
:class="filterType === 'ongoing' && 'selected'"
@click="filterType = 'ongoing'"
>
<span>در دست اقدام</span>
<span> ({{ getListCountByStatus('ongoing') }}) </span>
</CButton>
<CButton
:color="filterType === 'waiting' ? 'primary' : 'light'"
:class="filterType === 'waiting' && 'selected'"
@click="filterType = 'waiting'"
>
<span>در انتظار قطعه</span>
<span> ({{ getListCountByStatus('waiting') }} )</span>
</CButton>
<CButton
:color="filterType === 'delivered' ? 'primary' : 'light'"
:class="filterType === 'delivered' && 'selected'"
@click="filterType = 'delivered'"
>
<span>تحویل شده</span>
<span> ({{ getListCountByStatus('delivered') }}) </span>
</CButton>
</CButtonGroup>
</CCol>
<CCol sm="12">
<el-divider></el-divider>
</CCol>
<CCol sm="12">
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="کد پیگیری - کد نماینده - شماره موبایل نماینده - کد ملی نماینده - استان - شهر"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="filteredItems"
style="width: 100%"
:row-class-name="({ row, rowIndex }) => row.status === 'sent' && 'unread'"
>
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="تاریخ ثبت درخواست" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.sendDate) }} </span>
</template>
</el-table-column>
<el-table-column prop="trackingCode" label="کد پیگیری" width=""> </el-table-column>
<el-table-column prop="agent_id.province_name" label="استان" width=""> </el-table-column>
<el-table-column prop="agent_id.city_name" label="شهر" width=""> </el-table-column>
<el-table-column prop="agent_id.agent_code" label="کد نماینده" width=""> </el-table-column>
<el-table-column label="وضعیت" width="" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 'sent'" type="info">جدید</el-tag>
<el-tag v-if="scope.row.status === 'ongoing'" type="primary">در دست اقدام</el-tag>
<el-tag v-if="scope.row.status === 'waiting'" type="warning">در انتظار قطعه</el-tag>
<el-tag v-if="scope.row.status === 'delivered'" type="success">تحویل شده</el-tag>
</template>
</el-table-column>
<el-table-column label="بررسی" width="65" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-op-requests-oprId', params: { oprId: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminOldPieceRequestsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const oprList = await $axios.get('/api/admin/oprList')
return {
oprList: oprList.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'درخواست های قطعه داغی',
list_title: 'لیست',
oprList: null,
filterText: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
filteredItems() {
const filterData = this.oprList.filter(item =>
this.filterType === 'all' ? item : item.status === this.filterType
)
const filterText = this.filterText
if (!this.filterText.length) return filterData
else
return filterData.filter(item => {
return (
item.trackingCode.includes(filterText) ||
item.agent_id.agent_code.includes(filterText) ||
item.agent_id.full_name.includes(filterText) ||
item.agent_id.mobile_number.includes(filterText) ||
item.agent_id.national_code.includes(filterText) ||
item.agent_id.province_name.includes(filterText) ||
item.agent_id.city_name.includes(filterText)
)
})
},
filterType: {
get() {
return this.$route.query.status
},
set(val) {
this.$router.push({ name: 'admin-op-requests', query: { status: val } })
}
}
},
methods: {
getListCountByStatus(status) {
return this.oprList.filter(item => item.status === status).length
}
}
}
</script>
<style lang="scss" scopped>
.selected {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
z-index: 2;
span {
color: #fff;
}
}
.unread {
background: rgba(orange, 0.1) !important;
}
</style>
+248
View File
@@ -0,0 +1,248 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="pieceRequest._openedBy && pieceRequest._openedBy.first_name" type="primary" class="ml-1">
<span>اولین مشاهده توسط: </span>
<span> {{ pieceRequest._openedBy.first_name + ' ' + pieceRequest._openedBy.last_name }} </span>
</el-tag>
<el-tag v-if="pieceRequest._updatedBy && pieceRequest._updatedBy.first_name" type="primary" class="ml-1">
<span>تغییر وضعیت توسط: </span>
<span> {{ pieceRequest._updatedBy.first_name + ' ' + pieceRequest._updatedBy.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol v-if="!pieceRequest.archived && pieceRequest.status !== 'rejected'" lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol lg="6">
<h6>تغییر وضعیت فرم</h6>
<el-divider></el-divider>
<CButtonGroup>
<!-- <CButton
:color="pieceRequest.status === 'ongoing' ? 'warning' : 'light'"
@click="updateStatus('ongoing')"
>
در دست اقدام
</CButton> -->
<CButton
:color="pieceRequest.status === 'waiting' ? 'warning' : 'light'"
@click="updateStatus('waiting')"
>
در انتظار قطعه
</CButton>
<el-popover
v-model="deliverPopover"
placement="bottom"
width="160"
:disabled="pieceRequest.status === 'delivered'"
@click="deliveryPopover = true"
>
<el-input v-model="deliveryCode" placeholder="کد ارسال مرسوله"></el-input>
<div class="mt-1" style="text-align: center">
<el-button
size="mini"
type="text"
class="agentsStatus-popover-insideBtn"
@click="updateStatus('delivered')"
>ارسال</el-button
>
</div>
<CButton slot="reference" :color="pieceRequest.status === 'delivered' ? 'success' : 'light'">
تحویل شده
</CButton>
</el-popover>
</CButtonGroup>
<div v-if="pieceRequest.status === 'delivered'" class="mt-3">
<p>
<span>کد ارسال مرسوله: </span>
<b>{{ pieceRequest.deliveryCode || '-' }} </b>
</p>
</div>
</CCol>
<CCol lg="6">
<h6>تاریخچه وضعیت های فرم</h6>
<el-divider></el-divider>
<el-table :data="pieceRequest.statusHistory" style="width: 100%">
<el-table-column prop="name" label="وضعیت">
<template slot-scope="scope">
<span v-if="scope.row.status === 'temp'">پیشنویس</span>
<span v-if="scope.row.status === 'sent'">ارسال</span>
<span v-if="scope.row.status === 'ongoing'">در دست اقدام</span>
<span v-if="scope.row.status === 'waiting'">در انتظار قطعه</span>
<span v-if="scope.row.status === 'delivered'">تحویل شده</span>
</template>
</el-table-column>
<el-table-column prop="date" label="تاریخ">
<template slot-scope="scope">
<span style="display: inline-block; direction: ltr">{{ $jDateTime(scope.row.date) }}</span>
</template>
</el-table-column>
</el-table>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<el-collapse>
<el-collapse-item title="مشخصات نماینده">
<CForm>
<CInput label="نام و نام خانوادگی" horizontal disabled :value="pieceRequest.agent_id.full_name" />
<CInput label="کد ملی" horizontal disabled :value="pieceRequest.agent_id.national_code" />
<CInput label="تلفن همراه" horizontal disabled :value="pieceRequest.agent_id.mobile_number" />
<CInput label="تلفن شرکت/تعمیرگاه" horizontal disabled :value="pieceRequest.agent_id.tel_number" />
<CInput label="فکس شرکت/تعمیرگاه" horizontal disabled :value="pieceRequest.agent_id.fax_number" />
<CInput label="استان" horizontal disabled :value="pieceRequest.agent_id.province_name" />
<CInput label="شهر" horizontal disabled :value="pieceRequest.agent_id.city_name" />
<CInput label="آدرس" horizontal disabled :value="pieceRequest.agent_id.address" />
<CInput label="کد پستی" horizontal disabled :value="pieceRequest.agent_id.postal_code" />
<CInput label="نام شرکت/تعمیرگاه" horizontal disabled :value="pieceRequest.agent_id.store_name" />
</CForm>
<el-divider></el-divider>
<div style="text-align: center">
<nuxt-link :to="{ name: 'admin-agents-agent', params: { agent: pieceRequest.agent_id._id } }"
>مشاهده اکانت نماینده</nuxt-link
>
</div>
</el-collapse-item>
</el-collapse>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<CForm>
<CTextarea label="توضیحات فرم" horizontal disabled rows="5" :value="pieceRequest.description" />
</CForm>
<h6>لیست قطعات درخواستی:</h6>
<el-divider></el-divider>
<el-table :data="pieceRequest.items" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="تاریخ پذیرش" width="">
<template slot-scope="scope">
<a :href="scope.row.url" target="_blank" :download="scope.row.name">{{ scope.row.name }}</a>
</template>
</el-table-column>
<el-table-column prop="ItemName" label="نام کالا" width=""></el-table-column>
<el-table-column label="سریال گارانتی" width="">
<template slot-scope="scope">
<span> {{ scope.row.SerialNo1 || '-' }} </span>
</template>
</el-table-column>
<el-table-column label="وضعیت گارانتی" width="">
<template slot-scope="scope">
<span v-if="scope.row.gStatus">دارد</span>
<span v-else>ندارد</span>
</template>
</el-table-column>
<el-table-column prop="pieceName" label="نام قطعه" width=""></el-table-column>
<el-table-column prop="pieceCode" label="کد قطعه" width=""></el-table-column>
<el-table-column prop="pieceQuantity" label="تعداد" width=""></el-table-column>
</el-table>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminPieceRequestDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const pieceRequest = await $axios.get(`/api/admin/pr/${params.prId}`)
return {
pieceRequest: pieceRequest.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده درخواست قطعه',
pieceRequest: null,
deliverPopover: false,
deliveryCode: '',
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
updateStatus(status) {
if (status === this.pieceRequest.status) return
if (this.pieceRequest.status === 'delivered') return
const title = 'هشدار'
function getMsg() {
const msg1 = 'با تغییر وضعیت فرم به در انتظار قطعه بلافاصله پیامک اطلاع رسانی برای نماینده ارسال خواهد شد'
const msg2 =
'با تغییر وضعیت فرم به تحویل شده بلافاصله پیامک اطلاع رسانی برای نماینده ارسال خواهد شد. توجه داشته باشید بعدا نمیتوانید کد ارسال مرسوله را تغییر دهید.'
if (status === 'ongoing') return msg1
else return msg2
}
this.$confirm(getMsg(), title, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.put(`/api/admin/prStatus/${this.pieceRequest._id}`, { status, deliveryCode: this.deliveryCode })
.then(response => {
this.$message({
type: 'success',
message: response.data.message
})
this.deliveryCode = ''
this.$nuxt.refresh()
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+219
View File
@@ -0,0 +1,219 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="12">
<CButtonGroup>
<CButton
:color="filterType === 'all' ? 'primary' : 'light'"
:class="filterType === 'all' && 'selected'"
@click="filterType = 'all'"
>
<span>همه</span>
<span> ({{ prList.length }}) </span>
</CButton>
<CButton
:color="filterType === 'sent' ? 'primary' : 'light'"
:class="filterType === 'sent' && 'selected'"
@click="filterType = 'sent'"
>
<span>جدید</span>
<span> ({{ getListCountByStatus('sent') }}) </span>
</CButton>
<CButton
:color="filterType === 'ongoing' ? 'primary' : 'light'"
:class="filterType === 'ongoing' && 'selected'"
@click="filterType = 'ongoing'"
>
<span>در دست اقدام</span>
<span> ({{ getListCountByStatus('ongoing') }}) </span>
</CButton>
<CButton
:color="filterType === 'waiting' ? 'primary' : 'light'"
:class="filterType === 'waiting' && 'selected'"
@click="filterType = 'waiting'"
>
<span>در انتظار قطعه</span>
<span> ({{ getListCountByStatus('waiting') }} )</span>
</CButton>
<CButton
:color="filterType === 'delivered' ? 'primary' : 'light'"
:class="filterType === 'delivered' && 'selected'"
@click="filterType = 'delivered'"
>
<span>تحویل شده</span>
<span> ({{ getListCountByStatus('delivered') }}) </span>
</CButton>
</CButtonGroup>
</CCol>
<CCol sm="12">
<el-divider></el-divider>
</CCol>
<CCol sm="12">
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="کد پیگیری - کد نماینده - شماره موبایل نماینده - کد ملی نماینده - استان - شهر"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="filteredItems"
style="width: 100%"
:row-class-name="({ row, rowIndex }) => row.status === 'sent' && 'unread'"
>
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="تاریخ ثبت درخواست" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.sendDate) }} </span>
</template>
</el-table-column>
<el-table-column prop="trackingCode" label="کد پیگیری" width=""> </el-table-column>
<el-table-column prop="agent_id.province_name" label="استان" width=""> </el-table-column>
<el-table-column prop="agent_id.city_name" label="شهر" width=""> </el-table-column>
<el-table-column prop="agent_id.agent_code" label="کد نماینده" width=""> </el-table-column>
<el-table-column label="وضعیت" width="" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 'sent'" type="info">جدید</el-tag>
<el-tag v-if="scope.row.status === 'ongoing'" type="primary">در دست اقدام</el-tag>
<el-tag v-if="scope.row.status === 'waiting'" type="warning">در انتظار قطعه</el-tag>
<el-tag v-if="scope.row.status === 'delivered'" type="success">تحویل شده</el-tag>
</template>
</el-table-column>
<el-table-column label="بررسی" width="65" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-piece-requests-prId', params: { prId: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminPieceRequestsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const prList = await $axios.get('/api/admin/prList')
return {
prList: prList.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'درخواست های قطعه',
list_title: 'لیست',
prList: null,
filterText: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
filteredItems() {
const filterData = this.prList.filter(item =>
this.filterType === 'all' ? item : item.status === this.filterType
)
const filterText = this.filterText
if (!this.filterText.length) return filterData
else
return filterData.filter(item => {
return (
item.trackingCode.includes(filterText) ||
item.agent_id.agent_code.includes(filterText) ||
item.agent_id.full_name.includes(filterText) ||
item.agent_id.mobile_number.includes(filterText) ||
item.agent_id.national_code.includes(filterText) ||
item.agent_id.province_name.includes(filterText) ||
item.agent_id.city_name.includes(filterText)
)
})
},
filterType: {
get() {
return this.$route.query.status
},
set(val) {
this.$router.push({ name: 'admin-piece-requests', query: { status: val } })
}
}
},
methods: {
getListCountByStatus(status) {
return this.prList.filter(item => item.status === status).length
}
}
}
</script>
<style lang="scss" scopped>
.selected {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
z-index: 2;
span {
color: #fff;
}
}
.unread {
background: rgba(orange, 0.1) !important;
}
</style>
+131
View File
@@ -0,0 +1,131 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-pieces' }">برگشت به صفحه قبل</CButton>
<CButton v-if="$route.params.piece === 'new'" size="sm" color="success" style="margin-right: 10px" @click="add"
>افزودن</CButton
>
<CButton v-else size="sm" color="success" style="margin-right: 10px" @click="update">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="piece.name"
label="نام قطعه"
horizontal
:description="validation.name ? validation.name.msg : null"
:class="validation.name ? 'err' : null"
/>
<CInput
v-model="piece.code"
label="کد قطعه"
horizontal
:description="validation.code ? validation.code.msg : null"
:class="validation.code ? 'err' : null"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminPieceDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
if (params.piece === 'new') {
return {
piece: {
name: '',
code: ''
}
}
} else {
const piece = await $axios.get(`/api/admin/pieces/${params.piece}`)
return {
piece: piece.data
}
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: this.$route.params.piece === 'new' ? 'افزودن قطعه' : 'ویرایش قطعه',
piece: null,
validation: {}
}
},
head() {
return {
title: this.title
}
},
methods: {
add() {
this.validation = {}
this.$axios
.post(`/api/admin/piece`, this.piece)
.then(response => {
if (response.data) {
this.$message({
message: 'قطعه با موفقیت ثبت شد',
type: 'success'
})
this.$router.push({ name: 'admin-pieces' })
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
update() {
this.validation = {}
this.$axios
.put(`/api/admin/piece/${this.piece._id}`, this.piece)
.then(response => {
if (response.data) {
this.$message({
message: 'قطعه با موفقیت بروزرسانی شد',
type: 'success'
})
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
}
}
}
</script>
+106
View File
@@ -0,0 +1,106 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{ name: 'admin-pieces-piece', params: { piece: 'new' } }" class="mr-auto"
>افزودن</CButton
>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="pieces" 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 prop="code" label="کد قطعه" width=""> </el-table-column>
<el-table-column label="ویرایش" width="105" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="warning"
variant="outline"
:to="{ name: 'admin-pieces-piece', params: { piece: scope.row._id } }"
>
<i class="fal fa-pencil"></i>
</CButton>
<CButton color="danger" variant="outline" @click="del(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminPiecesList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const pieces = await $axios.get(`/api/admin/pieces`)
return {
pieces: pieces.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'لیست قطعات',
list_title: 'لیست',
pieces: null
}
},
head() {
return {
title: this.title
}
},
computed: {},
methods: {
del(id) {
this.$confirm('این قطعه حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/piece/${id}`)
.then(response => {
this.pieces = this.pieces.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'قطعه حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
@@ -0,0 +1,400 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol v-if="!representation.archived && representation.status !== 'rejected'" lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol v-if="!representation.archived" lg="6">
<h6>تغییر وضعیت فرم</h6>
<el-divider></el-divider>
<CButtonGroup>
<!-- <CButton :color="filterType === 'registered' ? 'primary' : 'light'">
ثبت شده
</CButton>
<CButton di :color="filterType === 'ongoing' ? 'primary' : 'light'">
در دست اقدام
</CButton> -->
<CButton
:color="representation.status === 'verification' ? 'warning' : 'light'"
@click="updateStatus('verification')"
>
بررسی مدارک
</CButton>
<CButton
:color="representation.status === 'accepted' ? 'success' : 'light'"
@click="updateStatus('accepted')"
>
تایید شده
</CButton>
<CButton
:color="representation.status === 'rejected' ? 'danger' : 'light'"
@click="updateStatus('rejected')"
>
رد شده
</CButton>
</CButtonGroup>
</CCol>
<CCol v-if="representation.status !== 'rejected'" lg="6">
<h6>تغییر وضعیت آپلود مدارک</h6>
<el-divider></el-divider>
<CButtonGroup>
<CButton :color="representation.upload ? 'primary' : 'light'" @click="updateStatus('uploadOn')">
دسترسی آپلود
</CButton>
<CButton :color="!representation.upload ? 'primary' : 'light'" @click="updateStatus('uploadOff')">
عدم دسترسی آپلود
</CButton>
</CButtonGroup>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>مشخصات فردی متقاضی:</h6>
<el-divider></el-divider>
<nuxt-link :to="{ name: 'admin-customers-customer', params: { customer: representation.user_id } }"
>مشاهده اکانت متقاضی</nuxt-link
>
<el-divider></el-divider>
<CForm>
<CInput label="نام مشتری" horizontal disabled :value="representation.full_name" />
<CInput label="کد ملی" horizontal disabled :value="representation.national_code" />
<CInput label="شماره شناسنامه" horizontal disabled :value="representation.id_number" />
<CInput label="محل صدور" horizontal disabled :value="representation.place_of_issue" />
<CInput label="تاریخ تولد" horizontal disabled :value="representation.birth_date" />
<CInput label="نام پدر" horizontal disabled :value="representation.fathers_name" />
<CInput label="میزان تحصیلات" horizontal disabled :value="representation.education_level" />
<CInput label="وضعیت نظام وظیفه" horizontal disabled :value="representation.military_status" />
<CTextarea
label="گواهینامه های تخصصی اخذ شده"
horizontal
disabled
rows="5"
:value="representation.certificates"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>اطلاعات تماس:</h6>
<el-divider></el-divider>
<CForm>
<CInput label="استان" horizontal disabled :value="representation.province_name" />
<CInput label="شهر" horizontal disabled :value="representation.city_name" />
<CInput label="نام شرکت/تعمیرگاه" horizontal disabled :value="representation.store_name" />
<CInput label="کد پستی" horizontal disabled :value="representation.postal_code" />
<CInput label="تلفن همراه" horizontal disabled :value="representation.mobile_number" />
<CInput label="تلفن شرکت/تعمیرگاه" horizontal disabled :value="representation.tel_number" />
<CInput label="فکس شرکت/تعمیرگاه" horizontal disabled :value="representation.fax_number" />
<CInput label="کد اقتصادی" horizontal disabled :value="representation.economic_code" />
<CInput label="ایمیل" horizontal disabled :value="representation.email" />
<CTextarea label="آدرس" horizontal disabled rows="5" :value="representation.address" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>مشخصات مکان نماینده:</h6>
<el-divider></el-divider>
<CForm>
<CInput label="جواز کسب" horizontal disabled :value="business_license" />
<CInput label="نوع مالکیت" horizontal disabled :value="ownership_type" />
<CInput label="متراژ کل (متر)" horizontal disabled :value="representation.total_area" />
<CInput label="متراژ محل تعمیرات (متر)" horizontal disabled :value="representation.repair_area" />
<CInput label="متراژ انبار (متر)" horizontal disabled :value="representation.stock_area" />
<CInput
label="طبقه محل مراجعه مشتریان"
horizontal
disabled
:value="representation.customer_reference_floor"
/>
<CInput label="موقعیت مکانی" horizontal disabled :value="place_location" />
<CInput label="موقعیت جغرافیایی" horizontal disabled :value="geo_location" />
<CInput label="تعداد و ابعاد تابلو" horizontal disabled :value="representation.banner_info" />
<CInput
label="تعداد تکنسین های تعمیرگاه"
horizontal
disabled
:value="representation.repair_technicians"
/>
<CInput label="تعداد استادکار تعمیرگاه" horizontal disabled :value="representation.repair_masters" />
<CInput label="تعداد کارکنان اداری" horizontal disabled :value="representation.office_workers" />
<CInput label="تعداد پیک موتوری" horizontal disabled :value="representation.bike_deliveries" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>آشنایی با آسان سرویس:</h6>
<el-divider></el-divider>
<CForm>
<CInput label="نحوه آشنایی با شرکت" horizontal disabled :value="know_asanServ_from" />
<CTextarea
label="در صورتیکه معرف دارید مشخصات ایشان را ذکر کنید"
horizontal
disabled
rows="5"
:value="representation.introducer_info"
/>
<CInput
label="میزان آشنایی با محصولات آسان سرویس"
horizontal
disabled
:value="asanServ_products_knowledge"
/>
<CInput
label="آیا در زمینه فروش لوازم جانبی موبایل و کامپیوتر فعالیت دارید؟"
horizontal
disabled
:value="computer_saling_exp"
/>
<CTextarea
label="در صورت فعالیت فروش، نام شرکت و نوع محصول را نام ببرید"
horizontal
disabled
rows="5"
:value="representation.computer_saling_description"
/>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>سابقه فعالیت:</h6>
<el-divider></el-divider>
<CForm>
<CInput
label="سابقه فعالیت در تعمیر ابزار جانبی موبایل و کامپیوتر (سال)"
horizontal
disabled
:value="representation.computer_repair_exp"
/>
<CInput
label="سابقه فعالیت در تعمیر لوزام صوتی و تصویری (سال)"
horizontal
disabled
:value="representation.multimedia_repair_exp"
/>
<CInput label="سابقه در محل کسب (سال)" horizontal disabled :value="representation.business_exp" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="6">
<CCard>
<CCardBody>
<h6>سایر توضیحات:</h6>
<el-divider></el-divider>
<CForm>
<CTextarea label="سایر توضیحات" horizontal disabled rows="5" :value="representation.more_descriptions" />
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol lg="12">
<CCard>
<CCardBody>
<h6>نمایندگی نشان تجاری دیگر:</h6>
<el-divider></el-divider>
<el-table :data="representation.other_representations" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="trademark" label="نشان تجاری" width=""> </el-table-column>
<el-table-column prop="company_name" label="نام شرکت" width=""> </el-table-column>
<el-table-column prop="cooperation_history" label="سابقه همکاری (سال)" width=""> </el-table-column>
<el-table-column prop="cooperation_start_year" label="سال شروع همکاری" width=""> </el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
<CCol v-for="item in agentAssetCategories" :key="item.fieldName" lg="12">
<CCard>
<CCardBody>
<CRow>
<CCol>
<h6>
{{ item.title }}
(عکس های آپلود شده)
</h6>
<el-divider></el-divider>
<el-image
v-for="image in representation[item.fieldName] || []"
:key="image._id"
style="width: 100px; height: 100px"
:src="image.url"
:preview-src-list="getImagePreviewList(representation[item.fieldName] || [])"
fit="cover"
class="ml-2"
>
</el-image>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'AddminRepresentationDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const representation = await $axios.get(`/api/admin/representation/${params.representation}`)
return {
representation: representation.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده درخواست نمایندگی',
representation: null,
validation: {}
}
},
head() {
return {
title: this.title
}
},
computed: {
...mapGetters({
agentAssetCategories: 'front/agentAssetCategories'
}),
business_license() {
if (this.representation.business_license) return 'دارد'
else return 'ندارد'
},
ownership_type() {
if (this.representation.ownership_type === 'owner') return 'مالک'
else if (this.representation.ownership_type === 'rent') return 'استیجاری'
else return 'سرقفلی'
},
place_location() {
if (this.representation.place_location === 'tech_passage') return 'مرکز صنف موبایل و کامپیوتر'
else return 'سایر'
},
geo_location() {
if (this.representation.geo_location === 'main_street') return 'خیابان اصلی'
else if (this.representation.geo_location === 'side_street') return 'خیابان فرعی'
else if (this.representation.geo_location === 'alley') return 'کوچه'
else if (this.representation.geo_location === 'inside_passage') return 'داخل پاساژ'
else return 'بر پاساژ'
},
know_asanServ_from() {
if (this.representation.know_asanServ_from === 'company_agents') return 'نماینده فروش'
else if (this.representation.know_asanServ_from === 'website') return 'وب سایت'
else if (this.representation.know_asanServ_from === 'company_workers') return 'پرسنل سازمان'
else if (this.representation.know_asanServ_from === 'exhibition') return 'نمایشگاه'
else if (this.representation.know_asanServ_from === 'introduced') return 'معرفی'
else return 'سایر'
},
asanServ_products_knowledge() {
if (this.representation.asanServ_products_knowledge === 4) return 'زیاد'
else if (this.representation.asanServ_products_knowledge === 3) return 'نسبتاً خوب'
else if (this.representation.asanServ_products_knowledge === 2) return 'متوسط'
else if (this.representation.asanServ_products_knowledge === 1) return 'کم'
else return 'خیلی کم'
},
computer_saling_exp() {
if (this.representation.computer_saling_exp) return 'دارد'
else return 'ندارد'
}
},
methods: {
updateStatus(status) {
if (status === this.representation.status) return
const title = 'هشدار'
function getMsg() {
const msg1 = 'با تغییر وضعیت فرم به بررسی مدارک بلافاصله پیامک اطلاع رسانی برای متقاضی ارسال خواهد شد'
const msg2 =
'با تغییر وضعیت به رد شده یا تایید شده دیگر امکان تغییر وضعیت نخواهید داشت و پیامک تغییر وضعیت بلافاصله برای متقاضی ارسال خواهد شد، ادامه میدهید؟'
const msg3 = 'پیامک ایجاد دسرترسی آپلود برای متقاضی ارسال خواهد شد، ادامه میدهید؟'
const msg4 = 'با برداشتن دسترسی آپلود پیامکی برای متقاضی ارسال نخواهد شد'
if (status === 'verification') return msg1
else if (status === 'rejected' || status === 'accepted') return msg2
else if (status === 'uploadOn') return msg3
else return msg4
}
this.$confirm(getMsg(), title, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.put(`/api/admin/representationStatus/${this.representation._id}`, { status })
.then(response => {
this.$message({
type: 'success',
message: response.data.message
})
this.$nuxt.refresh()
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
getImagePreviewList(images) {
return images.map(item => item.url)
}
}
}
</script>
+232
View File
@@ -0,0 +1,232 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol sm="12">
<CButtonGroup>
<CButton
:color="filterType === 'all' ? 'primary' : 'light'"
:class="filterType === 'all' && 'selected'"
@click="filterType = 'all'"
>
<span>همه</span>
<span> ({{ representations.length }}) </span>
</CButton>
<CButton
:color="filterType === 'registered' ? 'primary' : 'light'"
:class="filterType === 'registered' && 'selected'"
@click="filterType = 'registered'"
>
<span>جدید</span>
<span> ({{ getListCountByStatus('registered') }}) </span>
</CButton>
<CButton
:color="filterType === 'ongoing' ? 'primary' : 'light'"
:class="filterType === 'ongoing' && 'selected'"
@click="filterType = 'ongoing'"
>
<span>در دست اقدام</span>
<span> ({{ getListCountByStatus('ongoing') }}) </span>
</CButton>
<CButton
:color="filterType === 'verification' ? 'primary' : 'light'"
:class="filterType === 'verification' && 'selected'"
@click="filterType = 'verification'"
>
<span>بررسی مدارک</span>
<span> ({{ getListCountByStatus('verification') }} )</span>
</CButton>
<CButton
:color="filterType === 'accepted' ? 'primary' : 'light'"
:class="filterType === 'accepted' && 'selected'"
@click="filterType = 'accepted'"
>
<span>تایید شده</span>
<span> ({{ getListCountByStatus('accepted') }}) </span>
</CButton>
<CButton
:color="filterType === 'rejected' ? 'primary' : 'light'"
:class="filterType === 'rejected' && 'selected'"
@click="filterType = 'rejected'"
>
<span>رد شده</span>
<span> ({{ getListCountByStatus('rejected') }}) </span>
</CButton>
</CButtonGroup>
</CCol>
<CCol sm="12">
<el-divider></el-divider>
</CCol>
<CCol sm="12">
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="کد پیگیری - شماره موبایل - کد ملی - استان - شهر"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table
:data="filteredItems"
style="width: 100%"
:row-class-name="({ row, rowIndex }) => row.status === 'registered' && 'unread'"
>
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="full_name" label="نام" width=""> </el-table-column>
<el-table-column prop="national_code" label="کد ملی" width=""> </el-table-column>
<el-table-column prop="mobile_number" label="شماره موبایل" width=""> </el-table-column>
<el-table-column prop="representation_code" label="کد پیگیری" width=""> </el-table-column>
<el-table-column prop="province_name" label="استان" width=""> </el-table-column>
<el-table-column prop="city_name" label="شهر" width=""> </el-table-column>
<el-table-column label="تاریخ ثبت درخواست" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.created_at) }} </span>
</template>
</el-table-column>
<el-table-column label="وضعیت" width="">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 'registered'" type="info">ثبت شده</el-tag>
<el-tag v-if="scope.row.status === 'ongoing'" type="primary">در دست اقدام</el-tag>
<el-tag v-if="scope.row.status === 'verification'" type="warning">بررسی مدارک</el-tag>
<el-tag v-if="scope.row.status === 'accepted'" type="success">تایید شده</el-tag>
<el-tag v-if="scope.row.status === 'rejected'" type="danger">رد شده</el-tag>
</template>
</el-table-column>
<el-table-column label="بررسی" width="65" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-representations-representation', params: { representation: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminRepresentationsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const representations = await $axios.get('/api/admin/representations')
return {
representations: representations.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'درخواست های نمایندگی',
list_title: 'لیست',
representations: null,
filterText: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
filteredItems() {
const filterData = this.representations.filter(item =>
this.filterType === 'all' ? item : item.status === this.filterType
)
const filterText = this.filterText.toLowerCase()
if (!filterText.length) return filterData
else
return filterData.filter(item => {
return (
item.representation_code.toLowerCase().includes(filterText) ||
item.full_name.toLowerCase().includes(filterText) ||
item.mobile_number.toLowerCase().includes(filterText) ||
item.national_code.toLowerCase().includes(filterText) ||
item.province_name.toLowerCase().includes(filterText) ||
item.city_name.toLowerCase().includes(filterText)
)
})
},
filterType: {
get() {
return this.$route.query.status
},
set(val) {
this.$router.push({ name: 'admin-representations', query: { status: val } })
}
}
},
methods: {
getListCountByStatus(status) {
return this.representations.filter(item => item.status === status).length
}
}
}
</script>
<style lang="scss" scopped>
.selected {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
z-index: 2;
span {
color: #fff;
}
}
.unread {
background: rgba(orange, 0.1) !important;
}
</style>
+163
View File
@@ -0,0 +1,163 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<h3>افزودن فایل اکسل</h3>
<el-divider></el-divider>
<input ref="file" type="file" class="d-block" />
<p v-if="validation.file" class="text-danger mt-3">{{ validation.file.msg }}</p>
<el-button type="success" class="mt-3" size="small" style="color: #fff" @click="post">افزودن</el-button>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardBody>
<h3>لیست فایل های افزوده شده</h3>
<el-divider></el-divider>
<el-table :data="files" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="نام فایل" width="">
<template slot-scope="scope">
<a
download
target="_blank"
title="برای دانلود کلیک کنید"
:href="scope.row.url + scope.row.name"
style="color: blue; display: block; direction: ltr !important; text-align: right"
>
{{ scope.row.name }}
</a>
</template>
</el-table-column>
<el-table-column label="حذف" width="60" align="left">
<template slot-scope="scope">
<CButton :key="scope.row._id" color="danger" variant="outline" @click="del(scope.row.name)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminGuaranteeSerials',
layout: 'admin',
async asyncData({ $axios, error, query }) {
try {
const type = query?.type
if (!type) throw new Error('invalid type')
const files = await $axios.get('/api/admin/serialExels', {
params: { type }
})
return {
files: files.data
}
} catch (e) {
error({ status: 500, message: 'there is a problem here' })
}
},
data() {
return {
files: null,
validation: {}
}
},
head() {
return {
title: this.title
}
},
computed: {
type() {
return this.$route.query?.type
},
title() {
if (this.type === 'guaranteeSerial') return 'فایل اکسل شماره سریال گارانتی'
else return 'فایل اکسل شماره سریال کالا'
}
},
watch: {
type(newVal, oldVal) {
this.$nuxt.refresh()
}
},
methods: {
post() {
this.validation = {}
const data = new FormData()
data.append('type', this.type)
data.append('file', this.$refs.file.files[0])
this.$axios
.post('/api/admin/addExel', data)
.then(res => {
console.log('🚀 ~ file: index.vue ~ line 108 ~ post ~ res', res)
this.$message({
type: 'success',
message: 'فایل با موفقیت ارسال شد'
})
this.$refs.file.value = null
this.$nuxt.refresh()
})
.catch(err => {
if (err.response.data.status === 401) {
return this.$message({
type: 'warning',
message: 'لطفا دوباره وارد حساب خود شوید'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err)
})
},
del(name) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/removeExel/${name}`, {
params: {
type: this.type
}
})
.then(response => {
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
this.files = this.files.filter(item => item.name !== name)
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+333
View File
@@ -0,0 +1,333 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="!isNew && sms._creator.first_name" type="primary" class="ml-1">
<span>ایجاد کننده: </span>
<span> {{ sms._creator.first_name + ' ' + sms._creator.last_name }} </span>
</el-tag>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol sm="12">
<CCard>
<CCardBody>
<h6>متن پیامک:</h6>
<el-divider></el-divider>
<CForm>
<CTextarea
v-model="sms.message"
label="متن"
horizontal
rows="5"
:class="validation.message && 'err'"
:disabled="!isNew"
:description="validation.message && validation.message.msg"
/>
<CInput
v-if="!isNew"
label="تاریخ ارسال"
horizontal
:value="$jDateTime(sms.create_at)"
:disabled="true"
/>
</CForm>
<div v-if="isNew" class="recievers mt-5" style="text-align: center">
<h4>
<span>تعداد مخاطبین انتخاب شده:</span>
<b>{{ contacts.length }}</b>
</h4>
<p v-if="searchInput.length" style="color: orange; font-size: 12">
*برای مشاهده نتایج دقیق فیلد "جستجو" را خالی کنید. چنانچه فیلد جستجو پر باشد فقط برای کسانی که در لیست
فیلتر شده اند و نامشان انتخاب شده پیامک خواهد رفت.
</p>
<p v-if="validation.recievers && validation.recievers.msg" style="color: red">
{{ validation.recievers.msg }}
</p>
<div class="btnRow mt-3">
<el-button class="btn btn-primary custom-el-button" :loading="posting" @click="post">ارسال</el-button>
</div>
</div>
</CCardBody>
</CCard>
</CCol>
<CCol v-if="isNew" sm="12">
<CCard>
<CCardBody>
<h6 class="mb-2">انتخاب مخاطبین:</h6>
<div class="mb-2">
<CButtonGroup>
<CButton
:color="userType === 'all' ? 'primary' : 'light'"
:class="userType === 'all' && 'selected'"
@click="userType = 'all'"
>
<span>همه</span>
</CButton>
<CButton
:color="userType === 'customers' ? 'primary' : 'light'"
:class="userType === 'customers' && 'selected'"
@click="userType = 'customers'"
>
<span>مشتریان</span>
</CButton>
<CButton
:color="userType === 'agents' ? 'primary' : 'light'"
:class="userType === 'agents' && 'selected'"
@click="userType = 'agents'"
>
<span>نمایندگان</span>
</CButton>
</CButtonGroup>
</div>
<el-input
v-model="searchInput"
clearable
placeholder="جستجو با نام و نام خانوادگی - کد مشتری - کد ملی - شماره همراه"
/>
<el-divider></el-divider>
<div>
<el-checkbox key="checkAll_checkbox1" v-model="selectAll" label="انتخاب همه" />
</div>
<el-divider></el-divider>
<el-table :data="filteredItems" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="نام" width="">
<template slot-scope="scope">
{{ scope.row.first_name + ' ' + scope.row.last_name }}
</template>
</el-table-column>
<el-table-column prop="national_code" label="کد ملی" width=""> </el-table-column>
<el-table-column prop="mobile_number" label="شماره موبایل" width=""> </el-table-column>
<el-table-column prop="verity_businessCode" label="کد مشتری (وریتی)" width=""> </el-table-column>
<el-table-column prop="panatech_businessCode" label="کد مشتری (پاناتک)" width=""> </el-table-column>
<el-table-column label="وضعیت حساب" width="">
<template slot-scope="scope">
<el-tag v-if="scope.row.isAgent" type="success">نماینده</el-tag>
<el-tag v-else type="warning">مشتری</el-tag>
</template>
</el-table-column>
<el-table-column v-if="!selectAll" label="انتخاب" width="65" align="center">
<template slot-scope="scope">
<el-checkbox :key="scope.row._id + 'singleCheckBox'" v-model="scope.row.checked" />
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
<CCol v-else sm="12">
<CCard>
<CCardBody>
<h6 class="mb-2">لیست مخاطبین:</h6>
<el-divider></el-divider>
<el-table :data="sms.recievers" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="نام" width="">
<template slot-scope="scope">
{{ scope.row.user_id.first_name + ' ' + scope.row.user_id.last_name }}
</template>
</el-table-column>
<el-table-column prop="user_id.mobile_number" label="کد ملی" width=""> </el-table-column>
<el-table-column prop="mobile_number" label="شماره موبایل" width=""> </el-table-column>
<el-table-column prop="user_id.verity_businessCode" label="کد مشتری (وریتی)" width=""> </el-table-column>
<el-table-column prop="user_id.panatech_businessCode" label="کد مشتری (پاناتک)" width="">
</el-table-column>
<el-table-column label="مشاهده اکانت کاربر" width="140" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-customers-customer', params: { customer: scope.row.user_id._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AdminSMSBroadcastDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
if (params.item !== 'new') {
const sms = await $axios.get(`/api/admin/smsBroadcasts/${params.item}`)
return {
sms: sms.data
}
} else {
const users = await $axios.get(`/api/admin/usersForSMS`)
return {
sms: {
message: '',
recieveres: []
},
users: users.data
}
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
sms: null,
users: null,
posting: false,
selectAll: false,
userType: 'all',
searchInput: '',
validation: {}
}
},
head() {
return {
title: this.title
}
},
computed: {
title() {
if (this.isNew) return 'ارسال پیامک گروهی برای کاربران'
else return 'مشاهده پیامک ارسال شده'
},
isNew() {
return this.$route.params.item === 'new'
},
contacts() {
if (this.selectAll) return this.filteredItems
else return this.filteredItems.filter(item => item.checked)
},
filteredItems() {
const filterUsersByType = this.users.filter(item => {
if (this.userType === 'all') return item
else if (this.userType === 'customers' && !item.isAgent) return item
else if (this.userType === 'agents' && item.isAgent) return item
else return null
})
const searchInput = this.searchInput
if (!this.searchInput.length) return filterUsersByType
else {
return filterUsersByType.filter(item => {
return (
item.first_name.includes(searchInput) ||
item.last_name.includes(searchInput) ||
item.mobile_number.includes(searchInput) ||
item.national_code.includes(searchInput) ||
item.verity_businessCode?.includes(searchInput) ||
item.panatech_businessCode?.includes(searchInput) ||
(item.first_name + ' ' + item.last_name).includes(searchInput)
)
})
}
}
},
watch: {
userType(newVal, oldVal) {}
},
methods: {
async post() {
try {
if (!this.isNew) return
if (this.posting) {
return this.$message({
type: 'warning',
message: 'لطفا منتظر بمانید'
})
}
// get user confirmations
const title1 = ' هشدار - مرحله اول'
const title2 = ' هشدار - مرحله دوم'
const msg1 = 'لیست مخاطبان و متن پیام را چند بار قبل از ارسال بررسی کنید!'
const msg2 = 'پس از ارسال امکان انصراف یا بازگشت نخواهد بود!!!'
/// first step
await this.$confirm(msg1, title1, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
/// second step
await this.$confirm(msg2, title2, {
confirmButtonText: 'ارسال',
cancelButtonText: 'لغو',
type: 'warning'
})
this.posting = true
this.validation = {}
// create recieveres array
const recievers = []
for await (const contact of this.contacts) {
recievers.push({ user_id: contact._id, mobile_number: contact.mobile_number })
}
// send request
const smsBroadcast = await this.$axios.post('/api/admin/broadcastSMS', {
message: this.sms.message,
recievers
})
// handle request response
this.posting = false
this.$message({
type: 'success',
message: smsBroadcast.data.message
})
this.$router.push({ name: 'admin-sms' })
} catch (err) {
this.posting = false
if (err.response?.status === 422) {
this.$message({
type: 'warning',
message: 'پارامتر ها رو بررسی کنید'
})
this.validation = err.response.data.validation
}
if (err.response?.status === 401)
this.$message({
type: 'error',
message: 'دوباره وارد سیستم شوید'
})
}
}
}
}
</script>
+92
View File
@@ -0,0 +1,92 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" class="mr-auto" :to="{ name: 'admin-sms-item', params: { item: 'new' } }"
>افزودن</CButton
>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="filteredItems" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="message" label="متن" width="">
<template slot-scope="scope">
<span class="singleLineTxt" :title="scope.row.message"> {{ scope.row.message }} </span>
</template>
</el-table-column>
<el-table-column prop="recievers" label="تعداد مخاطبین" width="">
<template slot-scope="scope">
<span> {{ scope.row.recievers.length }} </span>
</template>
</el-table-column>
<el-table-column prop="caption" label="تاریخ ایجاد" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.created_at) }} </span>
</template>
</el-table-column>
<el-table-column label="ویرایش" width="75" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-sms-item', params: { item: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminSMSBroadcastList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const smsBroadcasts = await $axios.get('/api/admin/smsBroadcasts')
return {
smsBroadcasts: smsBroadcasts.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
list_title: 'لیست',
smsBroadcasts: null
}
},
head() {
return {
title: this.title
}
},
computed: {
title() {
return 'لیست پیامک های ارسال شده'
},
filteredItems() {
return this.smsBroadcasts
}
}
}
</script>
+62
View File
@@ -0,0 +1,62 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" :to="{ name: 'admin-surveys' }">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="12">
<CCard>
<CCardBody>
<CForm>
<CInput v-if="survey.code" :value="survey.code" label="شماره پذیرش دایم" disabled />
<CInput
v-for="item in surveyOptions"
:key="item.fieldName"
:value="surveyOptionsValues.get(survey[item.fieldName])"
:label="item.title"
disabled
/>
<CTextarea :value="survey.description" :rows="5" label="نظرات ، پیشنهادات و انتقادات" disabled />
</CForm>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'AdminSurveyDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const survey = await $axios.$get(`/api/admin/surveys/${params.survey}`)
return {
survey
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'مشاهده جزعیات نظرسنجی',
survey: null
}
},
head() {
return {
title: this.title
}
},
computed: {
...mapGetters({
surveyOptions: 'front/surveyOptions',
surveyOptionsValues: 'front/surveyOptionsValues'
})
}
}
</script>
+113
View File
@@ -0,0 +1,113 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
</CustomSubHeader>
<CCard>
<CCardBody>
<div>
<h3>میزان رضایت کلی مشتریان در تمام نظرات ثبت شده:</h3>
<ul class="mt-4">
<li v-for="item in surveyOptions" :key="item.fieldName + '_Option'">
<p>
<span>{{ item.title }}</span>
<b>%{{ getPercentage(item.fieldName) }}</b>
</p>
</li>
</ul>
</div>
</CCardBody>
</CCard>
<CCard>
<CCardBody>
<el-table :data="surveys" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="title" label="کاربر" width="">
<template slot-scope="scope">
<nuxt-link :to="{ name: 'admin-customers-customer', params: { customer: scope.row.user._id } }">
{{ scope.row.user.first_name + ' ' + scope.row.user.last_name }}
</nuxt-link>
</template>
</el-table-column>
<el-table-column prop="code" label="کد پذیرش دایم" width="" align="center">
<template slot-scope="scope">
<span>{{ scope.row.code || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="تاریخ ایجاد" width="">
<template slot-scope="scope">
<span> {{ $jDate(scope.row.created_at) }} </span>
</template>
</el-table-column>
<el-table-column label="مشاهده" width="70" align="center">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-surveys-survey', params: { survey: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'AdminSurveysList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const surveys = await $axios.$get(`/api/admin/surveys`)
return {
surveys
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'لیست نظرسنجی ها',
list_title: 'لیست',
surveys: null,
search: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
...mapGetters({
surveyOptions: 'front/surveyOptions',
surveyOptionsValues: 'front/surveyOptionsValues'
})
},
methods: {
getPercentage(fieldName) {
let totalData = 0
let userChoice = 0
this.surveys.forEach(item => {
totalData += 5
userChoice += item[fieldName]
})
return Math.round((userChoice * 100) / totalData)
}
}
}
</script>
+162
View File
@@ -0,0 +1,162 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol lg="12">
<CForm>
<CInput
label="نام مشتری"
horizontal
disabled
:value="conversation.user_id.first_name + ' ' + conversation.user_id.last_name"
/>
<CInput label="شناسه وریتی مشتری" horizontal disabled :value="conversation.user_id.verity_businessCode" />
<CInput
label="شناسه پاناتک مشتری"
horizontal
disabled
:value="conversation.user_id.panatech_businessCode"
/>
<CInput label="شماره پذیرش مربوطه" horizontal disabled :value="conversation.transaction_id || '-'" />
<CTextarea label="عنوان تیکت" horizontal disabled rows="5" :value="conversation.title" />
</CForm>
<div class="messenger">
<h3 class="messenger-title">پیام ها:</h3>
<div class="messenger-body">
<div class="messages" :class="!conversation.messages.length ? 'no-msg' : null">
<!-- no-msg -->
<p v-if="!conversation.messages.length">هیچ پیامی وجود ندارد.</p>
<!-- user -->
<div
v-for="item in conversation.messages"
:key="item._id"
class="message user"
:class="[!item.isUser ? 'user' : 'asan-admin', !item.read && item.isUser ? 'unread' : null]"
>
<div class="txt">
<img v-if="item.image" :src="item.image" alt="" />
<p>{{ item.message }}</p>
<p class="date">
<span>{{ $jDateTime(item.created_at) }}</span>
<span v-if="item.user_id.first_name">
({{ item.user_id.first_name + ' ' + item.user_id.last_name }})
</span>
</p>
</div>
<user-icon />
</div>
</div>
<div class="newMsg">
<div class="relativePos">
<input v-model="message" type="text" placeholder="پیام خود را بنویسید" />
<label for="file"></label>
<input id="file" ref="attachment" type="file" @change="preview" />
<img v-if="attachment" :src="attachment" alt="" />
<i v-if="attachment" id="clearFile" class="fas fa-times-circle" @click="clearFile"></i>
<button class="btn btn-primary" :disabled="!message && !attachment" @click="sendMessage">
ارسال
</button>
<div class="validationMsg">
<p v-if="validation.message">{{ validation.message.msg }}</p>
<p v-if="validation.image">{{ validation.image.msg }}</p>
</div>
</div>
</div>
</div>
</div>
</CCol>
</CRow>
</CCardBody>
</CCard>
</div>
</template>
<script>
import axiosUploadProcess from '@/mixins/axiosUploadProcess'
export default {
name: 'AddminTicketDetails',
mixins: [axiosUploadProcess],
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const conversation = await $axios.get(`/api/admin/ticket/${params.ticket}`)
return {
conversation: conversation.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'تیکت',
list_title: 'لیست',
conversation: null,
message: '',
attachment: '',
validation: {}
}
},
head() {
return {
title: this.title
}
},
computed: {},
methods: {
preview(event) {
this.attachment = URL.createObjectURL(event.target.files[0])
},
clearFile() {
this.attachment = null
this.$refs.attachment.value = null
},
sendMessage() {
this.validation = {}
const data = new FormData()
data.append('message', this.message)
if (this.$refs.attachment.files[0]) data.append('image', this.$refs.attachment.files[0])
this.$axios
.post(`/api/admin/addMessageToTicket/${this.conversation._id}`, data, this.axiosConfig)
.then(res => {
this.$message({
type: 'success',
message: 'پیام با موفقیت ارسال شد.'
})
this.attachment = ''
this.message = ''
this.$refs.attachment.value = null
this.conversation = res.data
setTimeout(() => {
window.scrollTo(0, document.body.scrollHeight)
}, 100)
})
.catch(err => {
if (err.response.data.status === 401) {
return this.$message({
type: 'warning',
message: 'لطفا دوباره وارد حساب خود شوید'
})
}
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err)
})
}
}
}
</script>
+146
View File
@@ -0,0 +1,146 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{ name: 'admin-add-tickets' }" class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fas fa-filter"></i>
<b>فیلتر ها</b>
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol>
<h4>جستجو در لیست:</h4>
<el-input
v-model="filterText"
clearable
placeholder="عنوان - کد مشتری - شماره سفارش"
style="display: inline-block; max-width: 500px; margin-top: 8px"
></el-input>
</CCol>
</CRow>
</CCardBody>
</CCard>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="filteredItems" :row-class-name="hasUnread" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="title" label="عنوان" width="">
<template slot-scope="scope">
<span :title="scope.row.title" class="singleLineTxt"> {{ scope.row.title }} </span>
</template>
</el-table-column>
<el-table-column prop="user_id.verity_businessCode" label="کد مشتری (وریتی)" width=""> </el-table-column>
<el-table-column prop="user_id.panatech_businessCode" label="کد مشتری (پاناتک)" width=""> </el-table-column>
<el-table-column prop="transaction_id" label="شماره سفارش" width="">
<template slot-scope="scope">
{{ scope.row.transaction_id || '-' }}
</template>
</el-table-column>
<el-table-column prop="created_at" label="تاریخ ایجاد مکالمه" width="">
<template slot-scope="scope">
{{ $jDate(scope.row.created_at) }}
</template>
</el-table-column>
<el-table-column label="مشاهده" width="75" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-tickets-ticket', params: { ticket: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminTicketsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const tickets = await $axios.get(`/api/admin/tickets`)
return {
tickets: tickets.data
}
} catch (err) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'تیکت ها',
list_title: 'لیست',
tickets: null,
filterText: ''
}
},
head() {
return {
title: this.title
}
},
computed: {
filteredItems() {
const filterText = this.filterText
return this.tickets.filter(item => {
return (
item.title.includes(filterText) ||
item.user_id.first_name.includes(filterText) ||
item.user_id.last_name.includes(filterText) ||
item.user_id.verity_businessCode?.includes(filterText) ||
item.user_id.panatech_businessCode?.includes(filterText) ||
(item.user_id.first_name + ' ' + item.user_id.last_name).includes(filterText)
)
})
}
},
methods: {
hasUnread({ row, rowIndex }) {
return row.messages.filter(item => !item.read && item.isUser).length ? 'unreadMsgInCv' : null
}
}
}
</script>
<style lang="scss">
.unreadMsgInCv {
background: rgba(orange, 0.1) !important;
}
.selected {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
z-index: 2;
}
</style>
+100
View File
@@ -0,0 +1,100 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="primary" class="mr-auto" @click="$router.go(-1)">برگشت به صفحه قبل</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<CRow>
<CCol lg="6">
<CForm>
<CInput label="شماره پذیرش" horizontal disabled :value="transaction.TransNumber" />
<CInput
label="نام مشتری"
horizontal
disabled
:value="transaction.user_id.first_name + ' ' + transaction.user_id.last_name"
/>
<CInput label="شناسه مشتری" horizontal disabled :value="transaction.user_id.arpa_businessCode" />
<CInput label="نام تحویل گیرنده" horizontal disabled :value="transaction.TransCCustom1" />
<CInput label="شماره تحویل گیرنده" horizontal disabled :value="transaction.cTel1" />
<CInput label="آدرس تحویل" horizontal disabled :value="transaction.cAddress1" />
</CForm>
</CCol>
</CRow>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AdminTransactionDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const transaction = await $axios.get(`/api/admin/transaction/${params.item}`)
return {
transaction: transaction.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
title: 'فرم های گارانتی',
list_title: 'لیست',
transaction: null,
message: '',
attachment: ''
}
},
head() {
return {
title: this.title
}
},
computed: {},
methods: {
preview(event) {
this.attachment = URL.createObjectURL(event.target.files[0])
},
clearFile() {
this.attachment = null
this.$refs.attachment.value = null
},
sendMessage() {
const data = new FormData()
data.append('message', this.message)
data.append('transaction_id', this.transaction._id)
if (this.$refs.attachment.files[0]) data.append('image', this.$refs.attachment.files[0])
this.$axios
.post('/api/admin/addTicket', data)
.then(res => {
this.$message({
type: 'success',
message: 'پیام با موفقیت ارسال شد.'
})
this.attachment = ''
this.message = ''
this.$refs.attachment.value = null
this.transaction.tickets.push(res.data)
})
.catch(e => {
console.log(e)
})
}
}
}
</script>
+92
View File
@@ -0,0 +1,92 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton size="sm" color="success" :to="{ name: 'admin-warranty-terms-new' }" class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<!-- <CCardHeader-->
<!-- :dir="paginate ? 'ltr' : 'rtl'"-->
<!-- :style="{textAlign: paginate ? 'center' : 'right'}">-->
<!-- <el-pagination-->
<!-- background-->
<!-- layout="prev, pager, next"-->
<!-- v-if="paginate"-->
<!-- @current-change="pageNumber"-->
<!-- :current-page="Number($route.params.page)"-->
<!-- :page-count="Number(warranties.totalPages)"-->
<!-- >-->
<!-- </el-pagination>-->
<!-- <slot name="header" v-else>-->
<!-- <CIcon name="cil-grid"/>-->
<!-- {{ list_title }}-->
<!-- </slot>-->
<!-- </CCardHeader>-->
<CCardHeader>
<slot name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="transactions" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="Description" label="پیام" width=""> </el-table-column>
<el-table-column prop="TransNumber" label="شماره سفارش" width=""> </el-table-column>
<el-table-column label="مشاهده" width="75" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="success"
variant="outline"
:to="{ name: 'admin-transactions-item', params: { item: scope.row._id } }"
>
<i class="fal fa-eye"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminTransactionsList',
layout: 'admin',
async asyncData({ $axios, error }) {
try {
const transactions = await $axios.get(`/api/admin/transactions`)
return {
transactions: transactions.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'فرم های گارانتی',
list_title: 'لیست',
transactions: null
}
},
head() {
return {
title: this.title
}
},
computed: {},
methods: {}
}
</script>
+175
View File
@@ -0,0 +1,175 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<el-tag v-if="warranty._creator && warranty._creator.first_name" type="primary">
<span>ایجاد یا اصلاح کننده: </span>
<span> {{ warranty._creator.first_name + ' ' + warranty._creator.last_name }} </span>
</el-tag>
<CButton
size="sm"
color="primary"
class="mr-auto"
:to="{ name: 'admin-warranty-terms-page', params: { page: $route.params.page } }"
>برگشت به صفحه قبل</CButton
>
<CButton size="sm" color="success" style="margin-right: 10px" @click="upload">بروزرسانی</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="warranty.title"
label="عنوان"
horizontal
:description="validation.title ? validation.title.msg : null"
:class="validation.title ? 'err' : null"
/>
<CTextarea
v-model="warranty.short_description"
label="توضیح کوتاه"
horizontal
rows="3"
:description="validation.short_description ? validation.short_description.msg : null"
:class="validation.short_description ? 'err' : null"
/>
<CRow form class="form-group" :class="validation.description ? 'err' : null">
<CCol tag="label" sm="3" class="col-form-label">توضیحات</CCol>
<CCol sm="9">
<client-only>
<ckeditor v-model="warranty.description" :config="editorConfig"></ckeditor>
</client-only>
<small v-if="validation.description" class="form-text text-muted w-100">
{{ validation.description.msg }}
</small>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardBody>
<h1>تصویر:</h1>
<el-divider />
<CRow>
<CCol col="12" class="mb-3">
<img :src="warranty.image" alt="" style="width: 100%; max-width: 500px" />
</CCol>
<CCol col="1">
<span>کاور</span>
</CCol>
<CCol col="11">
<input ref="image" type="file" @change="preview" />
</CCol>
<CCol col="11" class="mr-auto mt-3">
<small v-if="validation.image" class="form-text alert-danger w-100">
{{ validation.image.msg }}
</small>
<small v-else class="form-text text-muted w-100"> عکس باید با نسبت 1:1 باشد. </small>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminWarrantyTermDetails',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const warranty = await $axios.get(`/api/public/warranty/${params.item}`)
return {
warranty: warranty.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
warranty: null,
editorConfig: {
language: 'fa',
extraPlugins: ['bidi', 'justify']
},
validation: {},
uploading: false,
uploadProgress: null
}
},
head() {
return {
title: this.title
}
},
computed: {
title() {
if (!this.uploading) {
return 'ویرایش شرایط گارانتی'
} else {
return this.uploadProgress
}
}
},
methods: {
upload() {
this.validation = {}
const data = new FormData()
data.append('title', this.warranty.title)
data.append('short_description', this.warranty.short_description)
data.append('description', this.warranty.description)
if (this.$refs.image.files[0]) data.append('image', this.$refs.image.files[0])
const axiosConfig = {
onUploadProgress: progressEvent => {
this.uploading = true
this.uploadProgress = 'درحال آپلود ' + Math.floor((progressEvent.loaded / progressEvent.total) * 100) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
this.uploading = false
}
}
}
this.$axios
.put(`/api/admin/warranty/${this.warranty._id}`, data, axiosConfig)
.then(response => {
if (response.data) {
this.$message({
message: 'آیتم با موفقیت بروزرسانی شد.',
type: 'success'
})
this.$refs.image.value = null
this.warranty = response.data
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
preview(event) {
this.warranty.image = URL.createObjectURL(event.target.files[0])
}
}
}
</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-warranty-terms-new' }" class="mr-auto">افزودن</CButton>
</CustomSubHeader>
<CCard>
<CCardHeader :dir="paginate ? 'ltr' : 'rtl'" :style="{ textAlign: paginate ? 'center' : 'right' }">
<el-pagination
v-if="paginate"
background
layout="prev, pager, next"
:current-page="Number($route.params.page)"
:page-count="Number(warranties.totalPages)"
@current-change="pageNumber"
>
</el-pagination>
<slot v-else name="header">
<CIcon name="cil-grid" />
{{ list_title }}
</slot>
</CCardHeader>
<CCardBody>
<el-table :data="warranties.docs" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="تصویر" width="170">
<template slot-scope="scope">
<el-image style="width: 100%; height: 100%" :src="scope.row.image" fit="fit"> </el-image>
</template>
</el-table-column>
<el-table-column prop="title" label="عنوان" width=""> </el-table-column>
<el-table-column prop="short_description" label="توضیح کوتاه" width=""> </el-table-column>
<el-table-column label="ویرایش" width="105" align="left">
<template slot-scope="scope">
<CButton
:key="scope.row._id"
color="warning"
variant="outline"
:to="`/admin/warranty-terms/${$route.params.page}/${scope.row._id}`"
>
<i class="fal fa-pencil"></i>
</CButton>
<CButton color="danger" variant="outline" @click="del(scope.row._id)">
<i class="fal fa-trash-alt"></i>
</CButton>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
</div>
</template>
<script>
export default {
name: 'AddminWarrantyTermsList',
layout: 'admin',
async asyncData({ $axios, params, error }) {
try {
const warranties = await $axios.get(`/api/public/warranty/page/${params.page}`)
return {
warranties: warranties.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
title: 'شرایط گارانتی',
list_title: 'لیست',
warranties: null
}
},
head() {
return {
title: this.title
}
},
computed: {
paginate() {
return this.warranties.totalPages > 1
}
},
methods: {
pageNumber(val) {
this.$router.push({ name: 'admin-warranty-terms-page', params: { page: val } })
},
del(id) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/admin/warranty/${id}`)
.then(response => {
this.warranties.docs = this.warranties.docs.filter(item => item._id !== id)
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+164
View File
@@ -0,0 +1,164 @@
<template>
<div>
<CustomSubHeader>
<CBreadcrumb class="border-0 mb-0">{{ title }}</CBreadcrumb>
<CButton
size="sm"
color="primary"
class="mr-auto"
:to="{ name: 'admin-warranty-terms-page', params: { page: 1 } }"
>برگشت به صفحه قبل</CButton
>
<CButton size="sm" color="success" style="margin-right: 10px" @click="upload">ایجاد</CButton>
</CustomSubHeader>
<CRow>
<CCol xl="6">
<CCard>
<CCardBody>
<CForm>
<CInput
v-model="formData.title"
label="عنوان"
horizontal
:description="validation.title ? validation.title.msg : null"
:class="validation.title ? 'err' : null"
/>
<CTextarea
v-model="formData.short_description"
label="توضیح کوتاه"
horizontal
rows="3"
:description="validation.short_description ? validation.short_description.msg : null"
:class="validation.short_description ? 'err' : null"
/>
<CRow form class="form-group" :class="validation.description ? 'err' : null">
<CCol tag="label" sm="3" class="col-form-label">توضیحات</CCol>
<CCol sm="9">
<client-only>
<ckeditor v-model="formData.description" :config="editorConfig"></ckeditor>
</client-only>
<small v-if="validation.description" class="form-text text-muted w-100">
{{ validation.description.msg }}
</small>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
</CCol>
<CCol xl="6">
<CCard>
<CCardBody>
<h1>تصویر:</h1>
<el-divider />
<CRow>
<CCol col="12" class="mb-3">
<img :src="formData.image" alt="" style="width: 100%; max-width: 500px" />
</CCol>
<CCol col="1">
<span>کاور</span>
</CCol>
<CCol col="11">
<input ref="image" type="file" @change="preview" />
</CCol>
<CCol col="11" class="mr-auto mt-3">
<small v-if="validation.image" class="form-text alert-danger w-100">
{{ validation.image.msg }}
</small>
<small v-else class="form-text text-muted w-100"> عکس باید با نسبت 1:1 باشد. </small>
</CCol>
</CRow>
</CCardBody>
</CCard>
</CCol>
</CRow>
</div>
</template>
<script>
export default {
name: 'AddminAddNewWarrantyTerm',
layout: 'admin',
data() {
return {
formData: {
title: '',
short_description: '',
description: '',
image: ''
},
editorConfig: {
language: 'fa',
extraPlugins: ['bidi', 'justify']
},
validation: {},
uploading: false,
uploadProgress: null
}
},
head() {
return {
title: this.title
}
},
computed: {
title() {
if (!this.uploading) {
return 'افزودن شرایط گارانتی'
} else {
return this.uploadProgress
}
}
},
methods: {
upload() {
this.validation = {}
const data = new FormData()
data.append('title', this.formData.title)
data.append('short_description', this.formData.short_description)
data.append('description', this.formData.description)
data.append('image', this.$refs.image.files[0])
const axiosConfig = {
onUploadProgress: progressEvent => {
this.uploading = true
this.uploadProgress = 'درحال آپلود ' + Math.floor((progressEvent.loaded / progressEvent.total) * 100) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
this.uploading = false
}
}
}
this.$axios
.post(`/api/admin/warranty`, data, axiosConfig)
.then(response => {
if (response.data) {
this.$message({
message: 'آیتم با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push({ name: 'admin-warranty-terms-page', params: { page: 1 } })
}
})
.catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه'
})
}
})
},
preview(event) {
this.formData.image = URL.createObjectURL(event.target.files[0])
}
}
}
</script>