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
+97
View File
@@ -0,0 +1,97 @@
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE / Editor
.idea
.vscode
# Service worker
sw.*
# one signal
OneSignalSDK*
# macOS
.DS_Store
# Vim swap files
*.swp
# static folder
static/
+22
View File
@@ -0,0 +1,22 @@
module.exports = {
root: true,
env: {
browser: true,
node: true,
jquery: true
},
parserOptions: {
parser: '@babel/eslint-parser',
requireConfigFile: false
},
extends: ['@nuxtjs', 'plugin:nuxt/recommended', 'prettier'],
plugins: [],
// add your custom rules here
rules: {
'no-console': 'off',
camelcase: 'off',
'no-async-promise-executor': 'off',
'vue/no-v-html': 'off',
'vue/prop-name-casing': 'off'
}
}
+95
View File
@@ -0,0 +1,95 @@
/static/uploads/
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE / Editor
.idea
# Service worker
sw.*
# one signal
OneSignalSDK*
# macOS
.DS_Store
# Vim swap files
*.swp
+99
View File
@@ -0,0 +1,99 @@
###
# Place your Prettier ignore content here
###
# .gitignore content is duplicated here due to https://github.com/prettier/prettier/issues/8506
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE / Editor
.idea
# Service worker
sw.*
# macOS
.DS_Store
# Vim swap files
*.swp
# static assets
static/
+8
View File
@@ -0,0 +1,8 @@
{
"trailingComma": "none",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"printWidth": 120,
"arrowParens": "avoid"
}
+15
View File
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
}
]
}
+16
View File
@@ -0,0 +1,16 @@
{
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/Thumbs.db": true,
"node_modules": true,
"**/.vscode": true,
"**/.nuxt": false,
".vscode": true
},
"explorerExclude.backup": null,
"prettier.arrowParens": "avoid"
}
+10
View File
@@ -0,0 +1,10 @@
{
"name": "AsanService",
"host": "asan-service.com",
"protocol": "ftp",
"port": 21,
"username": "asanserv",
"password": "6}Y5[G}Zc#we",
"remotePath": "/nuxt",
"uploadOnSave": false
}
+23 -1
View File
@@ -1 +1,23 @@
# asan-service
# Asan-Service
## Project bulit with Nodejs version:
v14.18.3
## Build Setup
```bash
# install dependencies
$ npm i
# to run project in development mode
$ npm run dev
$ npm run server
# build for production and launch server
$ npm run build
$ npm run start
# generate static project
$ npm run generate
```
@@ -0,0 +1,19 @@
<template>
<div class="pwa_dialog">
<div class="dialog-wrapper">
<div class="txt">
<p>با نصب برنامه تحت وب آسان سرویس سریع تر به پنل کاربری خود دسترسی داشته باشید!</p>
</div>
<div class="btns">
<button id="installPWA" class="btn btn-secondary secondary-reverse">نصب کن</button>
<button id="closePwaDialog" class="btn btn-secondary cancel">فعلا نه!</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'PwaDialog'
}
</script>
+23
View File
@@ -0,0 +1,23 @@
<template>
<div class="hero">
<div class="bg">
<div class="container">
<h2>{{ title }}</h2>
<slot></slot>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'HeroComponent',
props: {
title: {
required: true,
type: String,
default: ''
}
}
}
</script>
@@ -0,0 +1,118 @@
<template>
<div class="lottery">
<div
v-if="!lotteryPopUpBtn || lotteryPopUpBtn.visible"
class="lottery-popup-button"
:style="[buttonStyle, { transform: btnScale }]"
@click="showPopup"
></div>
<div class="lottery-popup">
<div class="relatevePos">
<div class="bg" @click="closePopup"></div>
<div class="content" :style="[popUpStyle]">
<div class="relativePos">
<i class="closeBtn far fa-times-circle" @click="closePopup"></i>
<div class="btnBox" @click="closePopup">
<nuxt-link
v-if="lastLottery && lastLottery.expired"
:to="{ name: 'lottery', query: { mode: 'result' } }"
class="btn btn-primary"
>مشاهده نتایج قرعه کشی</nuxt-link
>
<nuxt-link v-else :to="{ name: 'lottery', query: { mode: 'enroll' } }" class="btn btn-primary"
>شرکت در قرعه کشی</nuxt-link
>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'LotteryPopUp',
data() {
return {
lotteryPopUpBtn: null,
lastLottery: null,
btnScale: 'scale(0)',
isPopupOpen: false
}
},
computed: {
buttonStyle() {
const btn = this.lotteryPopUpBtn
const data = {
bottom: btn?.y.toString().concat('px') || 0,
left: btn?.x.toString().concat('px') || 0,
width: btn?.w.toString().concat('px') || 0,
height: btn?.h.toString().concat('px') || 0
}
if (btn) data.backgroundImage = `url(${btn?.bgImg})`
return data
},
popUpStyle() {
const popup = this.lastLottery
const data = {}
if (popup) {
if (!popup.expired) {
data.backgroundImage = `url(${popup?.entryBgImg})`
data.width = popup.entryWidth.toString().concat('px')
data.height = popup.entryHeight.toString().concat('px')
} else {
data.backgroundImage = `url(${popup?.resultBgImg})`
data.width = popup.resultWidth.toString().concat('px')
data.height = popup.resultHeight.toString().concat('px')
}
}
return data
}
},
watch: {
buttonStyle(neVal, oldVal) {
setTimeout(() => (this.btnScale = 'scale(1)'), 1 * 1000)
}
},
async mounted() {
// attach esc key to window
$(document).keyup(e => {
if (e.key === 'Escape' && this.isPopupOpen) this.closePopup()
})
// fetch data
try {
const lotteryPopUpBtn = await this.$axios.get('/api/public/lotteryPopUp')
if (lotteryPopUpBtn.data.visible) {
const lastLottery = await this.$axios.get('/api/public/lastLottery')
this.lastLottery = lastLottery.data
}
setTimeout(() => (this.lotteryPopUpBtn = lotteryPopUpBtn.data), 2 * 1000)
} catch (e) {
console.log('LotteryPopUp button fetch problem ---- ', e.response.data)
}
},
methods: {
showPopup() {
this.$gsap
.timeline({
onComplete: () => (this.isPopupOpen = true)
})
.to($('.lottery-popup'), { autoAlpha: 1, duration: 0.04 })
.to($('.lottery-popup .content'), { opacity: 1, scale: 1, duration: 0.2, ease: 'power3.out' })
},
closePopup() {
this.$gsap
.timeline({
onComplete: () => (this.isPopupOpen = false)
})
.to($('.lottery-popup .content'), { opacity: 0, scale: 0, duration: 0.1 })
.to($('.lottery-popup'), { autoAlpha: 0, duration: 0.04 })
}
}
}
</script>
@@ -0,0 +1,3 @@
<template>
<p class="notice">*برای مشاهده ادامه جدول افقی اسکرول کنید.</p>
</template>
+21
View File
@@ -0,0 +1,21 @@
<template>
<CSubheader
class="custom-subheader px-3"
:class="[sidebarShow ? null : 'sideBarClose', sidebarMinimize ? 'sideBarMinimized' : 'sideBarFull']"
>
<slot />
</CSubheader>
</template>
<script>
export default {
computed: {
sidebarShow() {
return this.$store.state.admin.sidebarShow
},
sidebarMinimize() {
return this.$store.state.admin.sidebarMinimize
}
}
}
</script>
+21
View File
@@ -0,0 +1,21 @@
import Vue from 'vue'
Vue.component('RenderString', {
props: {
// eslint-disable-next-line vue/require-prop-types
string: {
required: true
}
},
render(h) {
const render = {
template: '<div>' + this.string + '</div>',
methods: {
markComplete() {
console.log('the method called')
}
}
}
return h(render)
}
})
+14
View File
@@ -0,0 +1,14 @@
<template>
<CFooter :fixed="false">
<div class="mfs-auto">
<span class="mr-1" target="_blank">Powered by</span>
<a href="https://negarehagency.com/" target="_blank" class="copy-right">Negareh Agency</a>
</div>
</CFooter>
</template>
<script>
export default {
name: 'TheFooter'
}
</script>
+42
View File
@@ -0,0 +1,42 @@
<template>
<CHeader fixed with-subheader light>
<CToggler in-header class="ml-3 d-lg-none" @click="$store.commit('admin/toggleSidebarMobile')" />
<CToggler in-header class="ml-3 d-md-down-none" @click="$store.commit('admin/toggleSidebarDesktop')" />
<!-- <CHeaderBrand class="mx-auto d-lg-none" to="/">-->
<!-- <CIcon name="logo" height="48" alt="Logo"/>-->
<!-- </CHeaderBrand>-->
<!-- <CHeaderNav class="d-md-down-none mr-auto">-->
<!-- <CHeaderNavItem class="px-3">-->
<!-- <CHeaderNavLink :to="{name: 'admin'}">-->
<!-- صفحه اصلی-->
<!-- </CHeaderNavLink>-->
<!-- </CHeaderNavItem>-->
<!-- </CHeaderNav>-->
<CHeaderNav class="mr-4 mr-auto">
<TheHeaderDropdownAccnt />
</CHeaderNav>
</CHeader>
</template>
<script>
export default {
name: 'TheHeader',
data() {
return {
breadcrumb: [
{
text: 'صفحه اصلی',
to: '/admin'
},
{
text: 'لیست دانلود ها',
to: { name: 'admin-downloads' }
},
{
text: 'This is a span'
}
]
}
}
}
</script>
@@ -0,0 +1,64 @@
<template>
<CDropdown in-nav class="c-header-nav-items" placement="bottom-end" add-menu-classes="pt-0">
<template #toggler>
<CHeaderNavLink>
<div class="c-avatar">
<img src="/img/avatars/avatar.png" class="c-avatar-img" alt="" title="حساب کاربری" />
</div>
</CHeaderNavLink>
</template>
<CDropdownHeader tag="div" class="text-center" color="light">
<strong v-if="$auth.loggedIn">{{ $auth.user.first_name }}</strong>
</CDropdownHeader>
<!-- <CDropdownItem :to="{name: 'admin-users'}">-->
<!-- <CIcon name="cil-user"/>-->
<!-- <span>پروفایل</span>-->
<!-- </CDropdownItem>-->
<CDropdownItem @click="logOut">
<CIcon name="cil-lock-locked" />
<span>خروج از حساب</span>
</CDropdownItem>
</CDropdown>
</template>
<script>
export default {
name: 'TheHeaderDropdownAccnt',
data() {
return {
itemsCount: 42
}
},
methods: {
logOut() {
this.$confirm('میخواهید از حساب کاربری خارج شوید؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(async () => {
try {
await this.$auth.logout()
window.location.href = '/'
} catch (e) {
console.log(e.response.data)
}
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
<style scoped>
.c-icon {
margin-right: 0.3rem;
}
</style>
+331
View File
@@ -0,0 +1,331 @@
<template>
<CSidebar
fixed
:minimize="minimize"
:show="show"
@update:show="value => $store.commit('admin/set', ['sidebarShow', value])"
>
<CSidebarBrand class="d-md-down-none">
<a href="/" target="_blank">
<logo class="c-sidebar-brand-full" size="custom-size" :height="40" name="logo" />
<img
src="assets/img/favicon_white.png"
alt="logo"
class="c-sidebar-brand-minimized"
size="custom-size"
:height="35"
name="logo"
/>
</a>
</CSidebarBrand>
<!-- <CRenderFunction flat :content-to-render="$options.nav"/>-->
<!-- sidebar content -->
<CSidebarNav>
<CSidebarNavItem name="صفحه اصلی" :to="{ name: 'admin' }" icon="cil-speedometer" />
<CSidebarNavDropdown
:show="getDropdownState('adminS_WebsiteM_Dropdown')"
name="مدیریت وبسایت"
font-icon="fas fa-folder"
@update:show="val => setDropdownState('adminS_WebsiteM_Dropdown', val)"
>
<CSidebarNavItem
v-if="hasPermission('downloads')"
name="لیست دانلود ها"
:to="{ name: 'admin-downloads-page', params: { page: 1 } }"
font-icon="fal fa-arrow-alt-to-bottom"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('download-categories')"
name="دسته بندی دانلود"
:to="{ name: 'admin-download-categories' }"
font-icon="fal fa-arrow-alt-to-bottom"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('learning')"
name="آموزش ها"
:to="{ name: 'admin-learning-page', params: { page: 1 } }"
icon="cil-chart-pie"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('warranty-terms')"
name="شرایط گارانتی"
:to="{ name: 'admin-warranty-terms-page', params: { page: 1 } }"
font-icon="fal fa-file-alt"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('faq')"
name="سوالات متداول"
:to="{ name: 'admin-faq' }"
font-icon="fal fa-file-alt"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('help')"
name="راهنمای ثبت گارانتی"
:to="{ name: 'admin-help' }"
font-icon="fal fa-file-alt"
exact
/>
</CSidebarNavDropdown>
<CSidebarNavDropdown
v-if="hasPermission('downloads')"
:show="getDropdownState('adminS_CustomerM_Dropdown')"
name="مدیریت مشتریان"
font-icon="fas fa-folder"
@update:show="val => setDropdownState('adminS_CustomerM_Dropdown', val)"
>
<CSidebarNavItem
v-if="hasPermission('contact-us')"
name="پیام های صفحه تماس با ما"
:to="{ name: 'admin-contact-us' }"
font-icon="fal fa-envelope"
:exact="false"
:badge="unreadCuMsgs ? { text: unreadCuMsgs, color: 'danger' } : null"
/>
<CSidebarNavItem
v-if="hasPermission('customers')"
name="لیست مشتریان"
:to="{ name: 'admin-customers', query: { filter: 'all' } }"
font-icon="fal fa-list"
:exact="false"
:badge="newCustomers ? { text: newCustomers, color: 'danger' } : null"
/>
<CSidebarNavItem
v-if="hasPermission('tickets')"
name="تیکت های مشتریان"
:to="{ name: 'admin-tickets' }"
font-icon="fal fa-comment-alt-dots"
:exact="false"
:badge="unreadTickets ? { text: unreadTickets, color: 'danger' } : null"
/>
<CSidebarNavItem
v-if="hasPermission('tickets')"
name="ایجاد تیکت برای مشتری"
:to="{ name: 'admin-add-tickets' }"
font-icon="fal fa-plus"
exact
/>
</CSidebarNavDropdown>
<CSidebarNavDropdown
:show="getDropdownState('adminS_AgentM_Dropdown')"
name="مدیریت نمایندگان"
font-icon="fas fa-folder"
@update:show="val => setDropdownState('adminS_AgentM_Dropdown', val)"
>
<CSidebarNavItem
v-if="hasPermission('representations')"
name="درخواست های نمایندگی"
:to="{ name: 'admin-representations', query: { status: 'registered' } }"
font-icon="fas fa-handshake"
:exact="false"
:badge="newRepresentations ? { text: newRepresentations, color: 'danger' } : null"
/>
<CSidebarNavItem
v-if="hasPermission('agents')"
name="لیست نمایندگان"
:to="{ name: 'admin-agents', query: { agent: true } }"
font-icon="fas fa-list"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('agents')"
name="نمایندگان صلب امتیاز شده"
:to="{ name: 'admin-agents', query: { revoked: true } }"
font-icon="fas fa-list"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('agentsInbox')"
name="صندوق ورودی نمایندگان"
:to="{ name: 'admin-agentsInbox', query: { status: 'all' } }"
font-icon="fas fa-inbox"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('piece-requests')"
name="درخواست های قطعه"
:to="{ name: 'admin-piece-requests', query: { status: 'sent' } }"
font-icon="fas fa-wrench"
:exact="false"
:badge="newPieceRequests ? { text: newPieceRequests, color: 'danger' } : null"
/>
<CSidebarNavItem
v-if="hasPermission('op-requests')"
name="درخواست های قطعه داغی"
:to="{ name: 'admin-op-requests', query: { status: 'sent' } }"
font-icon="fas fa-backpack"
:exact="false"
:badge="newOldPieceRequests ? { text: newOldPieceRequests, color: 'danger' } : null"
/>
<CSidebarNavItem
v-if="hasPermission('buffer-requests')"
name="درخواست های کالای بافر"
:to="{ name: 'admin-buffer-requests', query: { status: 'sent' } }"
font-icon="fab fa-buffer"
:exact="false"
:badge="newBufferRequests ? { text: newBufferRequests, color: 'danger' } : null"
/>
<CSidebarNavItem
v-if="hasPermission('guarantee-reports')"
name="فرم های عملکرد گارانتی"
:to="{ name: 'admin-guarantee-reports' }"
font-icon="fas fa-file-chart-line"
:exact="false"
:badge="newGuaranteeReports ? { text: newGuaranteeReports, color: 'danger' } : null"
/>
<CSidebarNavItem
v-if="hasPermission('agentReports')"
name="گزارشات"
:to="{ name: 'admin-agentReports' }"
font-icon="fas fa-file-chart-pie"
:exact="false"
/>
</CSidebarNavDropdown>
<CSidebarNavDropdown
v-if="hasPermission('admins')"
:show="getDropdownState('adminS_AdminsM_Dropdown')"
name="مدیریت ادمین ها"
font-icon="fas fa-folder"
@update:show="val => setDropdownState('adminS_AdminsM_Dropdown', val)"
>
<CSidebarNavItem
v-if="hasPermission('admins')"
name="افزودن ادمین"
:to="{ name: 'admin-admins-admin', params: { admin: 'new' } }"
font-icon="fal fa-user"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('admins')"
name="لیست ادمین ها"
:to="{ name: 'admin-admins' }"
font-icon="fal fa-list"
:exact="false"
/>
</CSidebarNavDropdown>
<CSidebarNavDropdown
:show="getDropdownState('adminS_AppM_Dropdown')"
name="مدیریت اپلیکیشن"
font-icon="fas fa-folder"
@update:show="val => setDropdownState('adminS_AppM_Dropdown', val)"
>
<CSidebarNavItem
v-if="hasPermission('announcements')"
name="اعلانات مشتریان"
:to="{ name: 'admin-announcements', query: { user: true } }"
font-icon="fal fa-bell"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('announcements')"
name="اطلاعیه های نمایندگان"
:to="{ name: 'admin-announcements', query: { agent: true } }"
font-icon="fal fa-bullhorn"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('sms')"
name="ارسال پیامک"
:to="{ name: 'admin-sms' }"
font-icon="fas fa-sms"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('serials-exel')"
name="فایل اکسل شماره سریال گارانتی"
:to="{ name: 'admin-serials-exel', query: { type: 'guaranteeSerial' } }"
font-icon="fal fa-file-excel"
exact
/>
<CSidebarNavItem
v-if="hasPermission('serials-exel')"
name="فایل اکسل شماره سریال کالا"
:to="{ name: 'admin-serials-exel', query: { type: 'orginality' } }"
font-icon="fal fa-file-excel"
exact
/>
<CSidebarNavItem
v-if="hasPermission('lotteryPopUp')"
name="دکمه قرعه کشی"
:to="{ name: 'admin-lotteryPopUp' }"
font-icon="fal fa-hand-pointer"
exact
/>
<CSidebarNavItem
v-if="hasPermission('lottery')"
name="قرعه کشی"
:to="{ name: 'admin-lottery' }"
font-icon="fal fa-calendar-check"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('surveys')"
name="نظرسنجی"
:to="{ name: 'admin-surveys' }"
font-icon="fal fa-chart-bar"
:exact="false"
/>
<CSidebarNavItem
v-if="hasPermission('pieces')"
name="لیست قطعات"
:to="{ name: 'admin-pieces' }"
font-icon="fas fa-wrench"
:exact="false"
/>
</CSidebarNavDropdown>
</CSidebarNav>
<!-- sidebar content -->
<CSidebarMinimizer
class="d-md-down-none"
@click.native="$store.commit('admin/set', ['sidebarMinimize', !minimize])"
/>
</CSidebar>
</template>
<script>
// import nav from './_nav'
import { mapState } from 'vuex'
export default {
name: 'TheSidebar',
// nav,
computed: {
...mapState({
show: state => state.admin.sidebarShow,
minimize: state => state.admin.sidebarMinimize,
unreadCuMsgs: state => state.admin.unreadCuMsgs,
unreadTickets: state => state.admin.unreadTickets,
newCustomers: state => state.admin.newCustomers,
newRepresentations: state => state.admin.newRepresentations,
newPieceRequests: state => state.admin.newPieceRequests,
newOldPieceRequests: state => state.admin.newOldPieceRequests,
newBufferRequests: state => state.admin.newBufferRequests,
newGuaranteeReports: state => state.admin.newGuaranteeReports
})
},
methods: {
hasPermission(permission) {
if (this.$auth.loggedIn) return this.$auth.user.permissions.includes(permission)
else return false
},
setDropdownState(id, state) {
localStorage.setItem(id, state)
},
getDropdownState(id) {
return localStorage.getItem(id) === 'true'
}
}
}
</script>
+66
View File
@@ -0,0 +1,66 @@
export default [
{
_name: 'CSidebarNav',
_children: [
{
_name: 'CSidebarNavItem',
name: 'صفحه اصلی',
to: { name: 'admin' },
icon: 'cil-speedometer'
},
// {
// _name: 'CSidebarNavTitle',
// _children: ['مدیریت صفحات داینامیک']
// },
{
_name: 'CSidebarNavDropdown',
name: 'دانلود ها',
// route: {name: 'admin-download'},
fontIcon: 'fal fa-arrow-alt-to-bottom',
items: [
{
name: 'لیست',
to: { name: 'admin-downloads-page', params: { page: 1 } },
exact: false
},
{
name: 'دسته بندی ها',
to: { name: 'admin-download-categories' }
}
]
},
{
_name: 'CSidebarNavItem',
name: 'آموزش ها',
to: { name: 'admin-learning-page', params: { page: 1 } },
exact: false,
icon: 'cil-chart-pie'
},
{
_name: 'CSidebarNavItem',
name: 'شرایط گارانتی',
to: { name: 'admin-warranty-terms-page', params: { page: 1 } },
exact: false,
fontIcon: 'fal fa-file-alt'
},
{
_name: 'CSidebarNavItem',
name: 'سوالات متداول',
to: { name: 'admin-FAQ' },
exact: false,
fontIcon: 'fal fa-graduation-cap'
},
{
_name: 'CSidebarNavItem',
name: 'پیام های صفحه تماس با ما',
to: { name: 'admin-contact-us' },
exact: false,
badge: {
color: 'primary'
// text: this.computed.unreadMessages
},
fontIcon: 'fal fa-id-card-alt'
}
]
}
]
@@ -0,0 +1,20 @@
<template>
<CChartBar :datasets="defaultDatasets" labels="months" />
</template>
<script>
export default {
name: 'CChartBarExample',
computed: {
defaultDatasets() {
return [
{
label: 'GitHub Commits',
backgroundColor: '#f87979',
data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
}
]
}
}
}
</script>
@@ -0,0 +1,78 @@
/* eslint-disable vue/require-default-prop */
<template>
<CChartBar :datasets="computedDatasets" :options="computedOptions" :labels="labels" />
</template>
<script>
import CoreUtils from '~/mixins/CoreUtils'
export default {
name: 'CChartBarSimple',
mixins: [CoreUtils],
props: {
// eslint-disable-next-line vue/require-default-prop
datasets: Array,
// eslint-disable-next-line vue/require-default-prop
labels: [Array, String],
// eslint-disable-next-line vue/require-default-prop
options: Object,
// eslint-disable-next-line vue/require-default-prop
plugins: Array,
backgroundColor: {
type: String,
default: 'rgba(0,0,0,.2)'
},
// eslint-disable-next-line vue/require-default-prop
pointHoverBackgroundColor: String,
dataPoints: {
type: Array,
default: () => [10, 22, 34, 46, 58, 70, 46, 23, 45, 78, 34, 12]
},
label: {
type: String,
default: 'Sales'
},
pointed: Boolean
},
computed: {
defaultDatasets() {
return [
{
data: this.dataPoints,
backgroundColor: this.getColor(this.backgroundColor),
pointHoverBackgroundColor: this.getColor(this.pointHoverBackgroundColor),
label: this.label,
barPercentage: 0.5,
categoryPercentage: 1
}
]
},
defaultOptions() {
return {
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [
{
display: false
}
],
yAxes: [
{
display: false
}
]
}
}
},
computedDatasets() {
return this.deepObjectsMerge(this.defaultDatasets, this.datasets || {})
},
computedOptions() {
return this.deepObjectsMerge(this.defaultOptions, this.options || {})
}
}
}
</script>
@@ -0,0 +1,19 @@
<template>
<CChartDoughnut :datasets="defaultDatasets" :labels="['VueJs', 'EmberJs', 'ReactJs', 'AngularJs']" />
</template>
<script>
export default {
name: 'CChartDoughnutExample',
computed: {
defaultDatasets() {
return [
{
backgroundColor: ['#41B883', '#E46651', '#00D8FF', '#DD1B16'],
data: [40, 20, 80, 10]
}
]
}
}
}
</script>
@@ -0,0 +1,25 @@
<template>
<CChartLine :datasets="defaultDatasets" labels="months" />
</template>
<script>
export default {
name: 'CChartLineExample',
computed: {
defaultDatasets() {
return [
{
label: 'Data One',
backgroundColor: 'rgb(228,102,81,0.9)',
data: [30, 39, 10, 50, 30, 70, 35]
},
{
label: 'Data Two',
backgroundColor: 'rgb(0,216,255,0.9)',
data: [39, 80, 40, 35, 40, 20, 45]
}
]
}
}
}
</script>
@@ -0,0 +1,145 @@
/* eslint-disable vue/require-default-prop */
<template>
<CChartLine :datasets="computedDatasets" :options="computedOptions" :labels="labels" />
</template>
<script>
import CoreUtils from '~/mixins/CoreUtils'
export default {
name: 'CChartLineSimple',
mixins: [CoreUtils],
props: {
// eslint-disable-next-line vue/require-default-prop
datasets: Array,
// eslint-disable-next-line vue/require-default-prop
labels: [Array, String],
// eslint-disable-next-line vue/require-default-prop
options: Object,
// eslint-disable-next-line vue/require-default-prop
plugins: Array,
borderColor: {
type: String,
default: 'rgba(255,255,255,.55)'
},
backgroundColor: {
type: String,
default: 'transparent'
},
dataPoints: {
type: Array,
default: () => [10, 22, 34, 46, 58, 70, 46, 23, 45, 78, 34, 12]
},
label: {
type: String,
default: 'Sales'
},
pointed: Boolean,
// eslint-disable-next-line vue/require-default-prop
pointHoverBackgroundColor: String
},
computed: {
pointHoverColor() {
if (this.pointHoverBackgroundColor) {
return this.pointHoverBackgroundColor
} else if (this.backgroundColor !== 'transparent') {
return this.backgroundColor
}
return this.borderColor
},
defaultDatasets() {
return [
{
data: this.dataPoints,
borderColor: this.getColor(this.borderColor),
backgroundColor: this.getColor(this.backgroundColor),
pointBackgroundColor: this.getColor(this.pointHoverColor),
pointHoverBackgroundColor: this.getColor(this.pointHoverColor),
label: this.label
}
]
},
pointedOptions() {
return {
scales: {
xAxes: [
{
offset: true,
gridLines: {
color: 'transparent',
zeroLineColor: 'transparent'
},
ticks: {
fontSize: 2,
fontColor: 'transparent'
}
}
],
yAxes: [
{
display: false,
ticks: {
display: false,
min: Math.min.apply(Math, this.dataPoints) - 5,
max: Math.max.apply(Math, this.dataPoints) + 5
}
}
]
},
elements: {
line: {
borderWidth: 1
},
point: {
radius: 4,
hitRadius: 10,
hoverRadius: 4
}
}
}
},
straightOptions() {
return {
scales: {
xAxes: [
{
display: false
}
],
yAxes: [
{
display: false
}
]
},
elements: {
line: {
borderWidth: 2
},
point: {
radius: 0,
hitRadius: 10,
hoverRadius: 4
}
}
}
},
defaultOptions() {
const options = this.pointed ? this.pointedOptions : this.straightOptions
return Object.assign({}, options, {
maintainAspectRatio: false,
legend: {
display: false
}
})
},
computedDatasets() {
return this.deepObjectsMerge(this.defaultDatasets, this.datasets || {})
},
computedOptions() {
return this.deepObjectsMerge(this.defaultOptions, this.options || {})
}
}
}
</script>
@@ -0,0 +1,19 @@
<template>
<CChartPie :datasets="defaultDatasets" :labels="['VueJs', 'EmberJs', 'ReactJs', 'AngularJs']" />
</template>
<script>
export default {
name: 'CChartPieExample',
computed: {
defaultDatasets() {
return [
{
backgroundColor: ['#41B883', '#E46651', '#00D8FF', '#DD1B16'],
data: [40, 20, 80, 10]
}
]
}
}
}
</script>
@@ -0,0 +1,42 @@
<template>
<CChartPolarArea
:datasets="defaultDatasets"
:options="defaultOptions"
:labels="['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running']"
/>
</template>
<script>
export default {
name: 'CChartPolarAreaExample',
computed: {
defaultDatasets() {
return [
{
label: 'My First dataset',
backgroundColor: 'rgba(179,181,198,0.2)',
pointBackgroundColor: 'rgba(179,181,198,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: 'rgba(179,181,198,1)',
pointHoverBorderColor: 'rgba(179,181,198,1)',
data: [65, 59, 90, 81, 56, 55, 40]
},
{
label: 'My Second dataset',
backgroundColor: 'rgba(255,99,132,0.2)',
pointBackgroundColor: 'rgba(255,99,132,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: 'rgba(255,99,132,1)',
pointHoverBorderColor: 'rgba(255,99,132,1)',
data: [28, 48, 40, 19, 96, 27, 100]
}
]
},
defaultOptions() {
return {
aspectRatio: 1.5
}
}
}
}
</script>
@@ -0,0 +1,46 @@
<template>
<CChartRadar
:datasets="defaultDatasets"
:options="defaultOptions"
:labels="['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running']"
/>
</template>
<script>
export default {
name: 'CChartRadarExample',
computed: {
defaultDatasets() {
return [
{
label: '2019',
backgroundColor: 'rgba(179,181,198,0.2)',
borderColor: 'rgba(179,181,198,1)',
pointBackgroundColor: 'rgba(179,181,198,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(179,181,198,1)',
tooltipLabelColor: 'rgba(179,181,198,1)',
data: [65, 59, 90, 81, 56, 55, 40]
},
{
label: '2020',
backgroundColor: 'rgba(255,99,132,0.2)',
borderColor: 'rgba(255,99,132,1)',
pointBackgroundColor: 'rgba(255,99,132,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(255,99,132,1)',
tooltipLabelColor: 'rgba(255,99,132,1)',
data: [28, 48, 40, 19, 96, 27, 100]
}
]
},
defaultOptions() {
return {
aspectRatio: 1.5
}
}
}
}
</script>
@@ -0,0 +1,135 @@
<template>
<CChartLine
:datasets="defaultDatasets"
:options="defaultOptions"
:labels="[
'Mo',
'Tu',
'We',
'Th',
'Fr',
'Sa',
'Su',
'Mo',
'Tu',
'We',
'Th',
'Fr',
'Sa',
'Su',
'Mo',
'Tu',
'We',
'Th',
'Fr',
'Sa',
'Su',
'Mo',
'Tu',
'We',
'Th',
'Fr',
'Sa',
'Su'
]"
/>
</template>
<script>
// import { CChartLine } from '@coreui/vue-chartjs'
// import { getStyle, hexToRgba } from '@coreui/utils/src'
import CoreUtils from '~/mixins/CoreUtils'
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
export default {
name: 'MainChartExample',
mixins: [CoreUtils],
layout: 'admin',
computed: {
defaultDatasets() {
const brandSuccess = this.getStyle('success2') || '#4dbd74'
const brandInfo = this.getStyle('info') || '#20a8d8'
const brandDanger = this.getStyle('danger') || '#f86c6b'
const elements = 27
const data1 = []
const data2 = []
const data3 = []
for (let i = 0; i <= elements; i++) {
data1.push(random(50, 200))
data2.push(random(80, 100))
data3.push(65)
}
return [
{
label: 'My First dataset',
backgroundColor: this.hexToRgba(brandInfo, 10),
borderColor: brandInfo,
pointHoverBackgroundColor: brandInfo,
borderWidth: 2,
data: data1
},
{
label: 'My Second dataset',
backgroundColor: 'transparent',
borderColor: brandSuccess,
pointHoverBackgroundColor: brandSuccess,
borderWidth: 2,
data: data2
},
{
label: 'My Third dataset',
backgroundColor: 'transparent',
borderColor: brandDanger,
pointHoverBackgroundColor: brandDanger,
borderWidth: 1,
borderDash: [8, 5],
data: data3
}
]
},
defaultOptions() {
return {
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [
{
gridLines: {
drawOnChartArea: false
}
}
],
yAxes: [
{
ticks: {
beginAtZero: true,
maxTicksLimit: 5,
stepSize: Math.ceil(250 / 5),
max: 250
},
gridLines: {
display: true
}
}
]
},
elements: {
point: {
radius: 0,
hitRadius: 10,
hoverRadius: 4,
hoverBorderWidth: 3
}
}
}
}
}
}
</script>
+118
View File
@@ -0,0 +1,118 @@
<template>
<CRow>
<template v-if="!noCharts">
<CCol md="3" sm="6">
<CWidgetBrand color="facebook" right-header="89k" right-footer="friends" left-header="459" left-footer="feeds">
<CIcon name="cib-facebook" height="52" class="my-4" />
<CChartLineSimple
class="c-chart-brand"
background-color="rgba(255,255,255,.1)"
:data-points="[65, 59, 84, 84, 51, 55, 40]"
label="Friends"
labels="months"
/>
</CWidgetBrand>
</CCol>
<CCol md="3" sm="6">
<CWidgetBrand
color="twitter"
right-header="973k"
right-footer="followers"
left-header="1.792"
left-footer="tweets"
>
<CIcon name="cib-twitter" height="52" class="my-4" />
<CChartLineSimple
class="c-chart-brand"
background-color="rgba(255,255,255,.1)"
:data-points="[1, 13, 9, 17, 34, 41, 38]"
label="Followers"
labels="months"
/>
</CWidgetBrand>
</CCol>
<CCol md="3" sm="6">
<CWidgetBrand
color="linkedin"
right-header="500+"
right-footer="contracts"
left-header="292"
left-footer="feeds"
>
<CIcon name="cib-linkedin" height="52" class="my-4" />
<CChartLineSimple
class="c-chart-brand"
background-color="rgba(255,255,255,.1)"
:data-points="[78, 81, 80, 45, 34, 12, 40]"
label="Contracts"
labels="months"
/>
</CWidgetBrand>
</CCol>
<CCol md="3" sm="6">
<CWidgetBrand right-header="12" right-footer="events" left-header="4" left-footer="meetings" color="warning">
<CIcon name="cil-calendar" height="52" class="my-4" />
<CChartLineSimple
class="c-chart-brand"
background-color="rgba(255,255,255,.1)"
:data-points="[35, 23, 56, 22, 97, 23, 64]"
label="Followers"
labels="months"
/>
</CWidgetBrand>
</CCol>
</template>
<template v-else>
<CCol md="3" sm="6">
<CWidgetBrand color="facebook" right-header="89k" right-footer="friends" left-header="459" left-footer="feeds">
<CIcon name="cib-facebook" height="56" class="my-4" />
</CWidgetBrand>
</CCol>
<CCol md="3" sm="6">
<CWidgetBrand
color="twitter"
right-header="973k"
right-footer="followers"
left-header="1.792"
left-footer="tweets"
>
<CIcon name="cib-twitter" height="56" class="my-4" />
</CWidgetBrand>
</CCol>
<CCol md="3" sm="6">
<CWidgetBrand
color="linkedin"
right-header="500+"
right-footer="contracts"
left-header="292"
left-footer="feeds"
>
<CIcon name="cib-linkedin" height="56" class="my-4" />
</CWidgetBrand>
</CCol>
<CCol md="3" sm="6">
<CWidgetBrand right-header="12" right-footer="events" left-header="4" left-footer="meetings" color="warning">
<CIcon name="cil-calendar" height="56" class="my-4" />
</CWidgetBrand>
</CCol>
</template>
</CRow>
</template>
<script>
export default {
name: 'WidgetsBrand',
layout: 'admin',
props: {
noCharts: Boolean
}
}
</script>
<style scoped>
.c-chart-brand {
position: absolute;
width: 100%;
height: 100px;
}
</style>
@@ -0,0 +1,115 @@
<template>
<CRow>
<CCol sm="6" lg="3">
<CWidgetDropdown color="primary" header="9.823" text="Members online">
<template #default>
<CDropdown color="transparent p-0" placement="bottom-end">
<template #toggler-content>
<CIcon name="cil-settings" />
</template>
<CDropdownItem>Action</CDropdownItem>
<CDropdownItem>Another action</CDropdownItem>
<CDropdownItem>Something else here...</CDropdownItem>
<CDropdownItem disabled>Disabled action</CDropdownItem>
</CDropdown>
</template>
<template #footer>
<CChartLineSimple
pointed
class="mt-3 mx-3"
style="height: 70px"
:data-points="[65, 59, 84, 84, 51, 55, 40]"
point-hover-background-color="primary"
label="Members"
labels="months"
/>
</template>
</CWidgetDropdown>
</CCol>
<CCol sm="6" lg="3">
<CWidgetDropdown color="info" header="9.823" text="Members online">
<template #default>
<CDropdown color="transparent p-0" placement="bottom-end" :caret="false">
<template #toggler-content>
<CIcon name="cil-location-pin" />
</template>
<CDropdownItem>Action</CDropdownItem>
<CDropdownItem>Another action</CDropdownItem>
<CDropdownItem>Something else here...</CDropdownItem>
<CDropdownItem disabled>Disabled action</CDropdownItem>
</CDropdown>
</template>
<template #footer>
<CChartLineSimple
pointed
class="mt-3 mx-3"
style="height: 70px"
:data-points="[1, 18, 9, 17, 34, 22, 11]"
point-hover-background-color="info"
:options="{ elements: { line: { tension: 0.00001 } } }"
label="Members"
labels="months"
/>
</template>
</CWidgetDropdown>
</CCol>
<CCol sm="6" lg="3">
<CWidgetDropdown color="warning" header="9.823" text="Members online">
<template #default>
<CDropdown color="transparent p-0" placement="bottom-end">
<template #toggler-content>
<CIcon name="cil-settings" />
</template>
<CDropdownItem>Action</CDropdownItem>
<CDropdownItem>Another action</CDropdownItem>
<CDropdownItem>Something else here...</CDropdownItem>
<CDropdownItem disabled>Disabled action</CDropdownItem>
</CDropdown>
</template>
<template #footer>
<CChartLineSimple
class="mt-3"
style="height: 70px"
background-color="rgba(255,255,255,.2)"
:data-points="[78, 81, 80, 45, 34, 12, 40]"
:options="{ elements: { line: { borderWidth: 2.5 } } }"
point-hover-background-color="warning"
label="Members"
labels="months"
/>
</template>
</CWidgetDropdown>
</CCol>
<CCol sm="6" lg="3">
<CWidgetDropdown color="danger" header="9.823" text="Members online">
<template #default>
<CDropdown color="transparent p-0" placement="bottom-end">
<template #toggler-content>
<CIcon name="cil-settings" />
</template>
<CDropdownItem>Action</CDropdownItem>
<CDropdownItem>Another action</CDropdownItem>
<CDropdownItem>Something else here...</CDropdownItem>
<CDropdownItem disabled>Disabled action</CDropdownItem>
</CDropdown>
</template>
<template #footer>
<CChartBarSimple
class="mt-3 mx-3"
style="height: 70px"
background-color="rgb(250, 152, 152)"
label="Members"
labels="months"
/>
</template>
</CWidgetDropdown>
</CCol>
</CRow>
</template>
<script>
export default {
name: 'WidgetsDropdown',
layout: 'admin'
}
</script>
+97
View File
@@ -0,0 +1,97 @@
<template>
<el-dialog :title="title" :visible.sync="showModal">
<div class="agentDetailsModal">
<el-form label-position="top" :model="agent">
<el-form-item label="نوع نماینده">
<el-input v-if="agent.representation_type === 'both'" disabled value="نماینده هر دو نوع لوازم"/>
<el-input v-if="agent.representation_type === 'verity'" disabled value="نماینده لوازم جانبی کامپیوتر و موبایل"/>
<el-input v-if="agent.representation_type === 'panatech'" disabled value="نماینده لوازم صوتی تصویری خودرو"/>
</el-form-item>
<el-form-item label="نام فروشگاه">
<el-input disabled :value="agent.store_name"></el-input>
</el-form-item>
<el-form-item label="کد نماینده">
<el-input disabled :value="agent.agent_code"></el-input>
</el-form-item>
<el-form-item label="نام و نام خانوادگی">
<el-input disabled :value="agent.full_name"></el-input>
</el-form-item>
<el-form-item label="شماره تلفن ثابت">
<el-input disabled :value="agent.tel_number"></el-input>
</el-form-item>
<el-form-item label="شماره فکس">
<el-input disabled :value="agent.fax_number || '-'"></el-input>
</el-form-item>
<el-form-item label="شماره موبایل">
<el-input disabled :value="agent.mobile_number"></el-input>
</el-form-item>
<el-form-item label="ایمیل">
<el-input disabled :value="agent.email"></el-input>
</el-form-item>
<el-form-item label="استان">
<el-input disabled :value="agent.province_name"></el-input>
</el-form-item>
<el-form-item label="شهر">
<el-input disabled :value="agent.city_name"></el-input>
</el-form-item>
<el-form-item label="آدرس" :title="agent.address">
<el-input disabled :value="agent.address"></el-input>
</el-form-item>
<el-form-item label="کد پستی">
<el-input disabled :value="agent.postal_code"></el-input>
</el-form-item>
</el-form>
<div class="btnRow" style="text-align: center">
<a class="btn btn-primary mb-1" :href="`tel: ${agent.mobile_number}`">تماس به همراه</a>
<a class="btn btn-primary mb-1" :href="`tel: ${agent.tel_number}`">تماس به تلفن ثابت</a>
<a class="btn btn-primary mb-1" :href="`mailto: ${agent.email}`">ایمیل</a>
<el-button class="btn btn-primary mb-1" @click="showModal = false">بستن</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'AgentDetailsModal',
props: {
show: {
type: Boolean,
default: false
},
agent: {
requred: true,
type: Object,
default: null
}
},
data() {
return {}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
title() {
return 'اطلاعات تماس نماینده'
}
}
}
</script>
+136
View File
@@ -0,0 +1,136 @@
<template>
<el-dialog title="پیگیری وضعیت درخواست" :visible.sync="showModal">
<div v-if="!$auth.loggedIn || !$auth.hasScope('user')" class="panel not-logged-in">
<h3>
<span> برای بررسی درخواست نمایندگی باید </span>
<nuxt-link :to="{ name: 'auth-login-register', query: { path: 'representation' } }">وارد حساب کاربری</nuxt-link>
<span>خود شوید.</span>
</h3>
</div>
<div v-else class="checkUploadModalContent">
<div class="repCheckBox">
<form class="form form_3" @submit.prevent="checkRepCode">
<div class="formRow" :class="validation.representation_code && 'err'">
<input
id="repCodeInput"
v-model="repCodeInput"
type="text"
placeholder="کد پیگیری درخواست خود را وارد کنید"
/>
<p v-if="validation.representation_code">{{ validation.representation_code.msg }}</p>
</div>
<div class="formRow">
<button type="submit" class="btn btn-primary">بررسی</button>
</div>
</form>
</div>
<div class="resultBox">
<div class="repInfo" :class="repInfo.status">
<p>
<span>تاریخ ثبت درخواست:</span>
<b> {{ $jDate(repInfo.created_at) }} </b>
</p>
<p>
<span>وضعیت درخواست: </span>
<b v-if="repInfo.status === 'registered'"> ثبت شده در سیستم </b>
<b v-if="repInfo.status === 'ongoing'"> در دست اقدام </b>
<b v-if="repInfo.status === 'verification'"> احراز هویت و بررسی مدارک </b>
<b v-if="repInfo.status === 'accepted'"> تایید شده </b>
<b v-if="repInfo.status === 'rejected'"> رد شده </b>
</p>
<p v-if="repInfo.status !== 'rejected'">
<span>دسترسی برای آپلود مدارک: </span>
<b v-if="repInfo.upload"> دارید </b>
<b v-else> ندارید </b>
</p>
</div>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'CheckRepAndUploadDocs',
props: {
show: {
type: Boolean,
default: false
}
},
data() {
return {
checkingRepCode: false,
repCodeInput: '',
repInfo: {},
validation: {}
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
}
},
watch: {
showModal(newVal, oldVal) {
if (newVal) setTimeout(() => $('#repCodeInput').focus(), 300)
}
},
methods: {
showResult() {
const _DU = 0.3
this.$gsap
.timeline({ onCompleted: () => console.log('hiiiiiiiiiiii') })
.to(
$('.checkUploadModalContent'),
{ height: $('.checkUploadModalContent .resultBox').height() + 32, duration: _DU },
0
)
.set($('.checkUploadModalContent .repCheckBox'), { position: 'absolute', left: 0, top: 0 }, 0)
.to($('.checkUploadModalContent .repCheckBox'), { top: '-100%', opacity: 0, duration: _DU }, 0)
.to($('.checkUploadModalContent .resultBox'), { top: 0, opacity: 1, duration: _DU }, 0.05)
.set($('.checkUploadModalContent .resultBox'), { position: 'static' })
.set($('.checkUploadModalContent'), { height: 'auto' })
},
checkRepCode() {
this.validation = {}
this.$axios
.post('/api/user/checkRepresentation', { representation_code: this.repCodeInput?.trim() })
.then(res => {
this.repInfo = res.data
setTimeout(() => this.showResult(), 300)
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
else {
const title = 'خطا'
this.$alert(err.response.data.message, title, {
confirmButtonText: 'بستن'
})
}
})
}
}
}
</script>
@@ -0,0 +1,97 @@
<template>
<div class="panel upload-assets">
<div class="title">
<h3>
<span>درخواست نمایندگی شما با کد</span>
<b>{{ user.representation_code }}</b>
<span>ثبت شده است.</span>
</h3>
</div>
<el-skeleton v-if="loading" class="mt-5" :rows="6" />
<template v-else>
<template v-if="lastRepresentation.upload">
<div class="level-description">
<h3>مرحله دوم ثبت درخواست:</h3>
<p>اطلاعات شما تا این مرجله در سیستم ثبت شده است، لطفا از طریق این صفحه اقدام به بارگذاری مدارک خود کنید.</p>
<p>
تا زمانی که درخواست شما تعیین وضعیت نشده است در هر زمانی میتوانید با مراجعه به همین صفحه مدارک بیشتری
بارگذاری کنید یا مدارک قبلی را ویرایش کنید.
</p>
</div>
<div class="upload-description">
<h3>نکاتی درباره بارگذاری مدارک:</h3>
<ul>
<li>
<span>در هر بخش تصاویر مدارک مربوطه را بارگذاری نمایید.</span>
</li>
<li>
<span>فیلدهای بارگذاری عکس در این صفحه هیچ کدام اجباری نیست.</span>
</li>
<li>
<span>فرمت مجاز تصاور jpeg میباشد.</span>
</li>
<li>
<span>نهایت حجم مجاز برای هر تصویر 2 مگابایت میباشد.</span>
</li>
</ul>
</div>
<div class="upload">
<section v-for="item in agentAssetCategories" :key="item.title">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
<RepresentationImageUploader
:name="item.fieldName"
:files-list="lastRepresentation[item.fieldName] || []"
:representation_code="lastRepresentation.representation_code"
/>
</section>
</div>
</template>
<div v-else class="mt-5" style="text-align: center; color: red">
<h1>شما دسترسی آپلود مدارک ندارید</h1>
</div>
</template>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'EnrollRepresentationAssets',
data() {
return {
lastRepresentation: {},
loading: true
}
},
head() {
return {
title: 'آسان سرویس | آپلود مدارک'
}
},
computed: {
...mapGetters({
agentAssetCategories: 'front/agentAssetCategories'
}),
user() {
return this.$auth.user
},
userFullName() {
return this.user.first_name + ' ' + this.user.last_name
}
},
async mounted() {
try {
const lastRep = await this.$axios.$get(`/api/user/representation/${this.user.representation_code}`)
this.lastRepresentation = lastRep
} catch (err) {
console.log('err', err)
}
this.loading = false
}
}
</script>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,116 @@
<template>
<div>
<el-upload
:action="uploadUrl"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-success="handleAvatarSuccess"
:before-upload="validateFile"
:headers="requestHeaders"
:file-list="files"
:before-remove="beforeRemove"
:disabled="disabled"
multiple
>
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible" append-to-body>
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
export default {
name: 'RepresentationImageUploader',
props: {
name: {
type: String,
required: true,
default: ''
},
filesList: {
type: Array,
required: true,
default: () => []
},
representation_code: {
type: String,
required: true,
default: ''
},
disabled: {
type: Boolean,
required: false,
default: false
},
isAdmin: {
type: Boolean,
required: false,
default: false
}
},
data() {
return {
dialogImageUrl: '',
dialogVisible: false,
requestHeaders: {
authorization: this.$auth?.$storage?._state?.['_token.local'] || ''
}
}
},
computed: {
files() {
return this.filesList.map(item => {
return { id: item._id, name: item.name, url: item.url }
})
},
uploadUrl() {
const adminUrl = `/api/admin/representationImages/admin/${this.representation_code}?name=${this.name}`
const userUrl = `/api/user/representationImages/${this.representation_code}?name=${this.name}`
return this.isAdmin ? adminUrl : userUrl
}
},
methods: {
handleAvatarSuccess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw)
},
validateFile(file) {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('فقط فرمت jpg قایل قبول است')
}
if (!isLt2M) {
this.$message.error('تصویر نباید بیشتر از 2 مگابایت باشد')
}
return isJPG && isLt2M
},
handleRemove(file, fileList) {
if (!file.raw) {
const adminUrl = `/api/admin/representationImages/admin/${this.representation_code}/${file.id}?name=${this.name}`
const userUrl = `/api/user/representationImages/${this.representation_code}/${file.id}?name=${this.name}`
this.$axios.delete(this.isAdmin ? adminUrl : userUrl)
}
},
beforeRemove(file) {
if (file.raw && !this.validateFile(file.raw)) {
return true
}
const title = 'هشدار'
const msg = 'شما در حال حذف این فایل هستید، ادامه میدهید؟'
return this.$confirm(msg, title, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
}
}
}
</script>
+244
View File
@@ -0,0 +1,244 @@
<template>
<footer class="site--footer">
<div class="container">
<div class="row">
<section class="col-12 r1">
<a :href="`tel: ${config.supportTel}`">
<span>شماره تماس پشتیبانی: </span>
<b> {{ config.supportTel }} </b>
</a>
<i class="d-none d-md-inline-block"> | </i>
<br class="d-md-none" />
<a :href="`mailto: ${config.supportEmail}`">
<span>ایمیل پشتیبانی: </span>
<b> {{ config.supportEmail }} </b>
</a>
</section>
<section class="col-12 r2">
<ul>
<li>
<img src="/assets/img/footer/guarantee.svg" alt="icon" />
<p>ضمانت بلند مدت</p>
</li>
<li>
<img src="/assets/img/footer/service.svg" alt="icon" />
<p>خدمات با کیفیت</p>
</li>
<li>
<img src="/assets/img/footer/repair.svg" alt="icon" />
<p>نیروی حرفه ای</p>
</li>
<li>
<img src="/assets/img/footer/learning.svg" alt="icon" />
<p>آموزش کاربردی</p>
</li>
<li>
<img src="/assets/img/footer/software.svg" alt="icon" />
<p>نرم افزار به روز</p>
</li>
<li>
<img src="/assets/img/footer/support.svg" alt="icon" />
<p>پشتیبانی آنلاین</p>
</li>
</ul>
</section>
<div class="col-12">
<el-divider></el-divider>
</div>
<section class="col-12 r3">
<nav class="row">
<div class="col-12 col-sm-4 mb-5 mb-sm-0 r3-1">
<h3>صفحات اصلی</h3>
<ul>
<li>
<nuxt-link :to="{ name: 'learning', query: { page: 1 } }">آموزش</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'download', query: { category: 'all', page: 1 } }">دانلود</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'agents' }">لیست نمایندگان</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'representation' }">اخذ نمایندگی</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'contact' }">ارتباط با ما</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'about' }">درباره ما</nuxt-link>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 mb-5 mb-sm-0 r3-2">
<h3>خدمات مشتریان</h3>
<ul>
<li v-if="help && help.helpId">
<nuxt-link :to="{ name: 'learning-post+', params: { post: help.helpId.title } }"
>راهنمای ثبت گارانتی</nuxt-link
>
</li>
<li>
<nuxt-link :to="{ name: 'index' }">استعلام گارانتی</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'warranty-terms', query: { page: 1 } }">شرایط گارانتی</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'FAQ' }">سوالات متداول</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'account-post' }">ارسال کالا برای گارانتی</nuxt-link>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 mb-5 mb-sm-0 r3-3">
<h3>با ما همراه باشید</h3>
<ul>
<li>
<a :href="config.whatsApp" target="_blank">
<img src="/assets/img/footer/whatsapp.svg" alt="icon" />
</a>
</li>
<li>
<a :href="config.instagram" target="_blank">
<img src="/assets/img/footer/instagram.svg" alt="icon" />
</a>
</li>
<li>
<a :href="config.aparat" target="_blank">
<img src="/assets/img/footer/aparat.svg" alt="icon" />
</a>
</li>
</ul>
<div class="newsletter">
<h3>از اخبار مطلع شوید</h3>
<div class="inputBox">
<input v-model="newsletter" type="text" placeholder="ایمیل خودرا وارد کنید" />
<button :disabled="!newsletter.length" @click="registerNewsletter">ثبت</button>
</div>
</div>
</div>
</nav>
</section>
<section class="col-12 apps">
<div class="btns">
<button id="showPwaDialog">
<img src="/assets/img/footer/pwaApp.png" alt="icon" />
</button>
<button>
<a :href="config.andoridAppURL" target="_blank">
<img src="/assets/img/footer/androidApp.png" alt="icon" />
</a>
</button>
</div>
</section>
<section class="col-12 r4">
<div class="bg">
<div class="container-fluid">
<div class="row">
<div class="col-12 col-md-6 logo">
<nuxt-link id="footerTitle" :to="{ name: 'index' }">
<Logo />
</nuxt-link>
</div>
<div class="col-12 col-md-6 companies">
<ul>
<li>
<img src="/assets/img/footer/sony.png" alt="logo" />
</li>
<li>
<img src="/assets/img/footer/apple.png" alt="logo" />
</li>
<li>
<img src="/assets/img/footer/panatech.png" alt="logo" />
</li>
<li>
<img src="/assets/img/footer/verity.png" alt="logo" />
</li>
<li>
<img src="/assets/img/footer/nintendo.png" alt="logo" />
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<section class="col-12 r5">
<h3>آسان سرویس اجرا کننده خدمات پس از فروش</h3>
<p>
امروزه یکی از ارکان اصلی شرکت های تولیدی صنعتی و برندهای تجاری ارائه خدمات پس از فروش است و رضایتمندی
مشتریان از نحوه رسیدگی به هنگام و آگاهی از روند انجام خدمات پس از فروش نقش بسزایی در روند توسعه برندهای
تجاری دارد . آسان سرویس به عنوان بازوی اجرایی خدمات پس از فروش شرکت تولیدی صنعتی پخش صبا درصدد است با به
کارگیری صحیح از منابع انسانی متخصص و نیز مدیریت واحدهای مختلف دپارتمان خدمات پس از فروش ، رضایت مشتریان
گرامی را از لحظه ورود محصول تا انجام خدمت به صورت مطلوب تامین نماید .
</p>
<div class="btns">
<nuxt-link :to="{ name: 'about' }">
<span>بیشتر بخوانید</span>
<i class="fas fa-angle-left"></i>
</nuxt-link>
</div>
</section>
</div>
</div>
<div class="container-fluid">
<div class="row">
<section class="col-12 r6">
<a id="copyright" :href="config.copyrightURL" target="_blank">
Designed and Developed in {{ config.copyrightName }}
</a>
</section>
</div>
</div>
</footer>
</template>
<script>
export default {
data() {
return {
newsletter: '',
help: null
}
},
computed: {
config() {
return this.$config
}
},
mounted() {
// fetch help page info
this.$axios.get('/api/public/help?front=true').then(res => (this.help = res.data))
// split text
const copyright = new this.$ATextSplitter({ rtl: false, letterSpace: 3, wordSpace: 7 })
copyright.injectToElement('copyright')
// animate text
this.$gsap
.timeline({ repeat: -1 })
.from($('#copyright .tsLetters'), { opacity: 0.2, duration: 0.7, stagger: 0.08 })
.to($('#copyright .tsLetters'), { opacity: 0.2, duration: 0.7, stagger: 0.08 }, 0.4)
},
methods: {
registerNewsletter() {
this.newsletter = ''
return this.$message({
type: 'warning',
message: 'مشکلی در ثبت اطلاعات پیش آمده'
})
}
}
}
</script>
+143
View File
@@ -0,0 +1,143 @@
<template>
<aside class="mobile-menu">
<nav class="body">
<ul>
<nuxt-link :to="{ name: 'index' }" exact tag="li">
<a>استعلام گارانتی</a>
</nuxt-link>
<nuxt-link :to="{ name: 'warranty-terms', query: { page: 1 } }" tag="li">
<a>شرایط گارانتی</a>
</nuxt-link>
<nuxt-link :to="{ name: 'download', query: { category: 'all', page: 1 } }" tag="li">
<a>دانلود</a>
</nuxt-link>
<nuxt-link :to="{ name: 'about' }" tag="li">
<a>درباره ما</a>
</nuxt-link>
<nuxt-link :to="{ name: 'contact' }" tag="li">
<a>ارتباط با ما</a>
</nuxt-link>
</ul>
<div class="title">
<!-- <span>نمایندگی</span>-->
</div>
<ul>
<nuxt-link :to="{ name: 'agents' }" tag="li">
<a>لیست نمایندگان</a>
</nuxt-link>
<nuxt-link :to="{ name: 'agent-benefits' }" tag="li">
<a>مزایای نمایندگی</a>
</nuxt-link>
<nuxt-link :to="{ name: 'representation' }" tag="li">
<a>اخذ نمایندگی</a>
</nuxt-link>
</ul>
<div class="title">
<!-- <span>راهنما</span>-->
</div>
<ul>
<nuxt-link :to="{ name: 'learning', query: { page: 1 } }" tag="li">
<a>آموزش</a>
</nuxt-link>
<nuxt-link :to="{ name: 'FAQ' }" tag="li">
<a>سوالات متداول</a>
</nuxt-link>
</ul>
<div class="title">
<!-- <span>حساب کاربری</span>-->
</div>
<ul>
<nuxt-link :to="isUser ? { name: 'account' } : { name: 'auth-login-register' }" tag="li">
<a>
<span v-if="isUser">{{ $auth.user.first_name + ' ' + $auth.user.last_name }}</span>
<span v-else>ورود</span>
<!-- user icon -->
<i v-if="isUser && userHasNotification" class="notificationAnim fas fa-bell"></i>
<i v-else class="fal fa-user"></i>
</a>
</nuxt-link>
</ul>
</nav>
<div class="bg" @click="menu(false)"></div>
</aside>
</template>
<script>
export default {
computed: {
mobileMenu() {
return this.$store.state.front.mobileMenu
},
isUser() {
return this.$auth.loggedIn && this.$auth.user.scope.includes('user')
},
userHasNotification() {
return this.$store.state.front.unreadTickets + this.$store.state.front.agentInbox
}
},
mounted() {
$('#menu').click(() => {
this.menu(!this.mobileMenu)
})
$('.mobile-menu ul li').click(() => {
this.menu(false)
})
},
methods: {
menu(action) {
const _DU = 0.5
const _EASE = 'power4.inOut'
this.$gsap
.timeline({
onComplete: () => {
if (!action) $('.mobile-menu').css({ display: 'none' })
}
})
.set($('.mobile-menu'), { display: 'block' })
.fromTo(
$('.mobile-menu .body'),
{ left: action ? -250 : 0 },
{ left: action ? 0 : -250, duration: _DU, ease: _EASE }
)
.fromTo(
$('.mobile-menu .body li'),
{
x: action ? -30 : 0,
opacity: action ? 0 : 1
},
{
x: action ? 0 : -30,
opacity: action ? 1 : 0,
duration: _DU,
ease: _EASE
},
'-=0.4'
)
.fromTo(
$('.mobile-menu .bg'),
{
opacity: action ? 0 : 1
},
{
opacity: action ? 1 : 0,
duration: _DU
},
0
)
.to(
$('#menu'),
{
opacity: 0,
scale: 0.9,
duration: _DU / 2,
onComplete: () => {
this.$store.commit('front/toggleMobileMenu')
}
},
0
)
.to($('#menu'), { opacity: 1, scale: 1, duration: _DU / 2 }, _DU / 2)
}
}
}
</script>
+124
View File
@@ -0,0 +1,124 @@
<template>
<header class="site--header">
<div class="container-fluid">
<div class="row">
<nav class="col-6 col-lg-2 logo">
<nuxt-link :to="{ name: 'index' }">
<logo />
</nuxt-link>
</nav>
<nav class="col-8 d-none d-lg-block">
<ul class="links">
<li
class="dropDown-container help"
:class="helpDropDownActiveClass && 'active'"
@mouseenter="openDrop('help')"
@mouseleave="closeDrop('help')"
>
<a>
<span>راهنما</span>
<i class="fas fa-angle-down"></i>
</a>
<div class="drop-down">
<nuxt-link
:to="{ name: 'learning', query: { page: 1 } }"
:class="$route.name.includes('learning') && 'active'"
>آموزش</nuxt-link
>
<nuxt-link :to="{ name: 'FAQ' }">سوالات متداول</nuxt-link>
</div>
</li>
<nuxt-link :to="{ name: 'index' }" exact tag="li">
<a>استعلام گارانتی</a>
</nuxt-link>
<nuxt-link :to="{ name: 'warranty-terms', query: { page: 1 } }" tag="li">
<a>شرایط گارانتی</a>
</nuxt-link>
<li
class="dropDown-container agents"
:class="agentsDropDownActiveClass && 'active'"
@mouseenter="openDrop('agents')"
@mouseleave="closeDrop('agents')"
>
<a>
<span>نمایندگان</span>
<i class="fas fa-angle-down"></i>
</a>
<div class="drop-down">
<nuxt-link :to="{ name: 'agents' }">لیست نمایندگان</nuxt-link>
<nuxt-link :to="{ name: 'agent-benefits' }">مزایای نمایندگی</nuxt-link>
<nuxt-link :to="{ name: 'representation' }" :exact="false">اخذ نمایندگی</nuxt-link>
</div>
</li>
<nuxt-link
:to="{ name: 'download', query: { category: 'all', page: 1 } }"
:class="$route.name.includes('download') && 'active'"
tag="li"
>
<a>دانلود</a>
</nuxt-link>
<nuxt-link :to="{ name: 'about' }" tag="li">
<a>درباره ما</a>
</nuxt-link>
<nuxt-link :to="{ name: 'contact' }" tag="li">
<a>ارتباط با ما</a>
</nuxt-link>
</ul>
</nav>
<nav class="col-2 d-none d-lg-flex account">
<nuxt-link :to="isUser ? { name: 'account' } : { name: 'auth-login-register' }">
<span v-if="isUser" class="singleLineTxt" :title="fullName">{{ fullName }}</span>
<span v-else>ورود</span>
<i v-if="isUser && userHasNotification" class="notificationAnim fas fa-bell"></i>
<i v-else class="fal fa-user"></i>
</nuxt-link>
</nav>
<div class="col-6 d-flex d-lg-none align-items-center justify-content-end menu">
<i id="menu" class="far" :class="!mobileMenu ? 'fa-bars' : 'fa-chevron-left'"></i>
</div>
</div>
</div>
</header>
</template>
<script>
import WS_User from '@/mixins/WS_User'
import WS_Agent from '@/mixins/WS_Agent'
export default {
mixins: [WS_User, WS_Agent],
data() {
return {}
},
computed: {
mobileMenu() {
return this.$store.state.front.mobileMenu
},
isUser() {
return this.$auth.loggedIn && this.$auth.user.scope.includes('user')
},
userHasNotification() {
const store = this.$store.state.front
return store.unreadTickets + store.agentInbox + store.newUserAnnosCount + store.newAgentAnnosCount
},
helpDropDownActiveClass() {
return this.$route.name === 'learning' || this.$route.name === 'learning-post+' || this.$route.name === 'FAQ'
},
agentsDropDownActiveClass() {
return this.$route.name === 'representation' || this.$route.name === 'agent-benefits'
},
fullName() {
return this.$auth.user.first_name + ' ' + this.$auth.user.last_name
}
},
methods: {
openDrop(name) {
$(`.dropDown-container.${name}`).addClass('d-active')
},
closeDrop(name) {
$(`.dropDown-container.${name}`).removeClass('d-active')
}
}
}
</script>
+94
View File
@@ -0,0 +1,94 @@
<template>
<svg viewBox="0 0 71 71" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g>
<path
fill="#1b3545"
opacity="1.00"
d=" M 28.74 0.00 L 34.10 0.00 C 33.02 1.52 31.05 1.66 29.38 1.27 L 28.92 0.70 L 28.74 0.00 Z"
/>
<path
fill="#1b3545"
opacity="1.00"
d=" M 37.63 0.00 L 41.28 0.00 L 42.04 0.62 L 42.15 1.17 C 40.55 1.93 38.66 1.44 37.63 0.00 Z"
/>
<path
fill="#1b3545"
opacity="1.00"
d=" M 9.85 47.79 C 14.44 46.13 19.29 44.70 24.15 44.52 C 25.20 48.92 26.58 53.31 28.31 57.47 C 29.25 61.59 30.93 65.54 32.03 69.64 L 32.29 70.57 C 21.00 69.86 10.49 62.90 4.92 53.16 C 5.93 50.87 7.87 49.22 9.85 47.79 Z"
/>
<path
fill="#1b3545"
opacity="1.00"
d=" M 42.78 59.43 C 44.99 54.66 46.11 49.39 47.83 44.41 C 50.42 44.20 52.74 45.64 55.31 45.49 C 59.61 46.45 64.66 48.21 66.27 52.74 C 60.98 62.37 50.84 69.47 39.79 70.42 C 40.31 66.62 42.12 63.17 42.78 59.43 Z"
/>
</g>
<g>
<path
fill="#0c0a0b"
opacity="1.00"
d=" M 34.10 0.00 L 37.63 0.00 C 38.66 1.44 40.55 1.93 42.15 1.17 C 45.42 2.46 49.09 4.05 50.63 7.46 C 52.37 11.28 52.33 15.63 51.92 19.73 C 51.30 21.29 50.24 22.60 49.42 24.05 C 50.53 21.21 47.36 19.64 46.64 17.17 C 45.60 14.50 42.90 13.14 40.20 12.75 C 36.54 13.46 34.02 17.60 30.00 16.49 C 27.73 16.57 25.95 13.82 23.76 14.65 C 23.73 17.83 22.10 20.69 22.47 23.92 C 21.86 22.67 21.15 21.47 20.40 20.30 C 19.93 16.41 18.50 12.24 20.49 8.53 C 21.61 4.52 25.71 2.43 29.38 1.27 C 31.05 1.66 33.02 1.52 34.10 0.00 Z"
/>
</g>
<g>
<path
fill="#f6f6f6"
opacity="1.00"
d=" M 8.62 12.65 C 13.68 6.38 21.11 2.39 28.92 0.70 L 29.38 1.27 C 25.71 2.43 21.61 4.52 20.49 8.53 C 18.50 12.24 19.93 16.41 20.40 20.30 C 17.05 21.21 18.70 24.97 20.22 26.81 C 23.04 29.84 25.07 33.48 27.17 37.03 C 27.22 38.22 27.27 39.42 27.33 40.62 C 22.69 45.53 14.62 43.30 9.85 47.79 C 7.87 49.22 5.93 50.87 4.92 53.16 C 1.70 47.94 0.38 41.81 0.00 35.75 L 0.00 35.21 C 0.32 27.05 3.07 18.77 8.62 12.65 Z"
/>
<path
fill="#f6f6f6"
opacity="1.00"
d=" M 42.15 1.17 L 42.04 0.62 C 49.81 2.46 57.33 6.30 62.34 12.65 C 67.92 18.77 70.67 27.06 71.00 35.24 L 71.00 35.78 C 70.60 41.66 69.39 47.65 66.27 52.74 C 64.66 48.21 59.61 46.45 55.31 45.49 C 51.91 43.24 47.19 44.11 44.36 40.82 C 44.34 40.01 44.30 38.38 44.28 37.57 C 46.52 33.85 48.46 29.74 51.86 26.90 C 53.69 25.00 54.69 21.33 51.92 19.73 C 52.33 15.63 52.37 11.28 50.63 7.46 C 49.09 4.05 45.42 2.46 42.15 1.17 Z"
/>
<path
fill="#f6f6f6"
opacity="1.00"
d=" M 28.31 57.47 C 29.92 56.62 31.53 55.76 32.97 54.63 C 34.69 59.48 32.23 64.65 32.03 69.64 C 30.93 65.54 29.25 61.59 28.31 57.47 Z"
/>
<path
fill="#f6f6f6"
opacity="1.00"
d=" M 38.86 54.55 C 40.46 55.93 42.88 56.93 42.78 59.43 C 42.12 63.17 40.31 66.62 39.79 70.42 L 39.79 70.42 C 39.77 65.14 37.00 59.70 38.86 54.55 Z"
/>
</g>
<g>
<path
fill="#edcaa8"
opacity="1.00"
d=" M 30.00 16.49 C 34.02 17.60 36.54 13.46 40.20 12.75 C 42.90 13.14 45.60 14.50 46.64 17.17 C 47.36 19.64 50.53 21.21 49.42 24.05 C 50.24 22.60 51.30 21.29 51.92 19.73 C 54.69 21.33 53.69 25.00 51.86 26.90 C 48.46 29.74 46.52 33.85 44.28 37.57 C 41.40 39.03 38.76 41.82 35.30 41.50 C 32.73 40.79 30.63 39.01 28.23 37.92 C 28.09 38.71 27.81 40.27 27.68 41.06 L 27.33 40.62 C 27.27 39.42 27.22 38.22 27.17 37.03 C 25.07 33.48 23.04 29.84 20.22 26.81 C 18.70 24.97 17.05 21.21 20.40 20.30 C 21.15 21.47 21.86 22.67 22.47 23.92 C 22.10 20.69 23.73 17.83 23.76 14.65 C 25.95 13.82 27.73 16.57 30.00 16.49 Z"
/>
</g>
<g>
<path
fill="#e1ac88"
opacity="1.00"
d=" M 28.23 37.92 C 30.63 39.01 32.73 40.79 35.30 41.50 C 38.76 41.82 41.40 39.03 44.28 37.57 C 44.30 38.38 44.34 40.01 44.36 40.82 C 41.47 44.64 38.17 48.31 36.29 52.77 C 36.09 52.73 35.69 52.64 35.49 52.60 C 33.48 48.39 30.45 44.78 27.68 41.06 C 27.81 40.27 28.09 38.71 28.23 37.92 Z"
/>
</g>
<g>
<path
fill="#cbcbcb"
opacity="1.00"
d=" M 9.85 47.79 C 14.62 43.30 22.69 45.53 27.33 40.62 L 27.68 41.06 C 30.45 44.78 33.48 48.39 35.49 52.60 C 34.66 53.28 33.82 53.96 32.97 54.63 C 31.53 55.76 29.92 56.62 28.31 57.47 C 26.58 53.31 25.20 48.92 24.15 44.52 C 19.29 44.70 14.44 46.13 9.85 47.79 Z"
/>
<path
fill="#cbcbcb"
opacity="1.00"
d=" M 44.36 40.82 C 47.19 44.11 51.91 43.24 55.31 45.49 C 52.74 45.64 50.42 44.20 47.83 44.41 C 46.11 49.39 44.99 54.66 42.78 59.43 C 42.88 56.93 40.46 55.93 38.86 54.55 C 38.04 53.91 37.18 53.32 36.29 52.77 C 38.17 48.31 41.47 44.64 44.36 40.82 Z"
/>
</g>
<g>
<path
fill="#ac0101"
opacity="1.00"
d=" M 32.97 54.63 C 33.82 53.96 34.66 53.28 35.49 52.60 C 35.69 52.64 36.09 52.73 36.29 52.77 C 37.18 53.32 38.04 53.91 38.86 54.55 C 37.00 59.70 39.77 65.14 39.79 70.42 C 38.44 70.62 37.10 70.81 35.75 71.00 L 34.54 71.00 C 33.97 70.89 32.85 70.68 32.29 70.57 L 32.03 69.64 C 32.23 64.65 34.69 59.48 32.97 54.63 Z"
/>
</g>
</svg>
</template>
<script>
export default {
name: 'UserIconSVG'
}
</script>
+148
View File
@@ -0,0 +1,148 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 178.678 47.133">
<g transform="translate(111.26 -6.5)">
<g transform="translate(-129.36 -45)">
<path
d="M31.039,152.2l-2.864,10.174H26.792l-2.173-8.4-2.272,8.4H20.964L18.1,152.2h1.087l2.469,8.89,2.469-8.89h.988l2.371,8.89,2.568-8.89Z"
transform="translate(0 -70.408)"
fill="#ffe"
/>
<path
d="M40.8,162.4h-.988v-1.383a3.128,3.128,0,0,1-2.963,1.58,3.874,3.874,0,0,1-1.778-.4,4.451,4.451,0,0,1-1.383-.988A3.7,3.7,0,0,1,33,160.034a3.963,3.963,0,0,1-.3-1.482,3.155,3.155,0,0,1,.3-1.383,5.6,5.6,0,0,1,.79-1.284A3.758,3.758,0,0,1,35.071,155a4.613,4.613,0,0,1,1.679-.3,3.874,3.874,0,0,1,1.778.4,2.745,2.745,0,0,1,1.185,1.185V154.8H40.7l.1,7.606Zm-.988-3.753a2.69,2.69,0,0,0-.889-2.074,2.843,2.843,0,0,0-2.074-.889,3.064,3.064,0,0,0-2.173.889,2.843,2.843,0,0,0-.889,2.074,2.69,2.69,0,0,0,.889,2.074,3.064,3.064,0,0,0,2.173.889,2.843,2.843,0,0,0,2.074-.889,2.69,2.69,0,0,0,.889-2.074"
transform="translate(-0.179 -70.438)"
fill="#ffe"
/>
<path
d="M46.662,155.688a2.08,2.08,0,0,0-1.284.494,1.576,1.576,0,0,0-.691.889,2.135,2.135,0,0,0-.1,1.087V162.4H43.6V154.9h.988v1.086a2.162,2.162,0,0,1,.889-.988,3.155,3.155,0,0,1,1.383-.3Z"
transform="translate(-0.313 -70.438)"
fill="#ffe"
/>
<path
d="M51.662,155.688a2.08,2.08,0,0,0-1.284.494,1.576,1.576,0,0,0-.691.889,2.135,2.135,0,0,0-.1,1.087V162.4H48.6V154.9h.988v1.086a2.162,2.162,0,0,1,.889-.988,3.155,3.155,0,0,1,1.383-.3Z"
transform="translate(-0.374 -70.438)"
fill="#ffe"
/>
<path
d="M61.2,162.4h-.988v-1.383a3.128,3.128,0,0,1-2.963,1.58,3.874,3.874,0,0,1-1.778-.4,4.451,4.451,0,0,1-1.383-.988,3.7,3.7,0,0,1-.691-1.185,3.963,3.963,0,0,1-.3-1.482,3.155,3.155,0,0,1,.3-1.383A4.439,4.439,0,0,1,55.471,155a4.613,4.613,0,0,1,1.679-.3,3.874,3.874,0,0,1,1.778.4,2.745,2.745,0,0,1,1.185,1.185V154.8H61.1l.1,7.606Zm-.988-3.753a2.69,2.69,0,0,0-.889-2.074,2.843,2.843,0,0,0-2.074-.889,3.064,3.064,0,0,0-2.173.889,2.843,2.843,0,0,0-.889,2.074,2.69,2.69,0,0,0,.889,2.074,3.064,3.064,0,0,0,2.173.889,2.843,2.843,0,0,0,2.074-.889,2.4,2.4,0,0,0,.889-2.074"
transform="translate(-0.43 -70.438)"
fill="#ffe"
/>
<path
d="M70.617,162.4h-.988v-3.951a3.7,3.7,0,0,0-.1-1.087,2.05,2.05,0,0,0-.593-.988,1.809,1.809,0,0,0-1.679-.593,4.2,4.2,0,0,0-1.086.2,5.473,5.473,0,0,0-.79.593,1.985,1.985,0,0,0-.4.79,4.052,4.052,0,0,0-.1,1.087V162.4H63.9V154.9h.988v1.086a2.779,2.779,0,0,1,2.371-1.284,3.963,3.963,0,0,1,1.482.3,3.407,3.407,0,0,1,1.185.889,2.253,2.253,0,0,1,.593,1.185,3.288,3.288,0,0,1,.1,1.383Z"
transform="translate(-0.562 -70.438)"
fill="#ffe"
/>
<path
d="M76.946,155.756H75.168v6.618H74.18v-6.618H72.6v-.889h1.58V152.2h.988v2.667h1.778Z"
transform="translate(-0.669 -70.408)"
fill="#ffe"
/>
<path
d="M85.31,154.9l-4.445,10.174h-.988l1.185-2.864L78.1,154.9h1.087l2.469,5.926,2.469-5.926Z"
transform="translate(-0.736 -70.441)"
fill="#ffe"
/>
<path
d="M98.323,159.6a2.69,2.69,0,0,1-.889,2.074,3.064,3.064,0,0,1-2.173.889,3.3,3.3,0,0,1-2.272-.889,2.7,2.7,0,0,1-.889-2.173h1.086a2.178,2.178,0,0,0,.593,1.482,2.074,2.074,0,0,0,3.556-1.482,1.861,1.861,0,0,0-.2-.79,1.772,1.772,0,0,0-.494-.691,1.593,1.593,0,0,0-.691-.4c-.3-.1-.691-.2-.988-.3a6.137,6.137,0,0,1-.988-.3,3.468,3.468,0,0,1-.79-.494,1.537,1.537,0,0,1-.593-.79,1.954,1.954,0,0,1-.2-1.087,2.487,2.487,0,0,1,.889-1.975,3.187,3.187,0,0,1,2.074-.79,2.936,2.936,0,0,1,1.975.79,2.758,2.758,0,0,1,.79,1.975H97.038a1.878,1.878,0,0,0-.494-1.284,2.36,2.36,0,0,0-1.383-.494,2.081,2.081,0,0,0-1.284.494,1.878,1.878,0,0,0-.494,1.284,1.485,1.485,0,0,0,.4,1.087,2.6,2.6,0,0,0,1.482.691,11.743,11.743,0,0,0,1.383.4,3.548,3.548,0,0,1,.988.691,3.48,3.48,0,0,1,.691,2.074"
transform="translate(-0.908 -70.404)"
fill="#ffe"
/>
<path
d="M108,159.045h-6.815a2.112,2.112,0,0,0,.889,1.778,2.937,2.937,0,0,0,1.975.79,2.985,2.985,0,0,0,1.58-.494,2.513,2.513,0,0,0,1.087-1.185H107.8a3.967,3.967,0,1,1-7.507-2.568,3.866,3.866,0,0,1,.988-1.58,3.738,3.738,0,0,1,2.766-1.185,3.956,3.956,0,0,1,2.864,1.185,5,5,0,0,1,1.086,3.26m-.988-.988a2.668,2.668,0,0,0-.988-1.679,2.892,2.892,0,0,0-3.753,0,2.908,2.908,0,0,0-.988,1.778h5.729Z"
transform="translate(-1.006 -70.437)"
fill="#ffe"
/>
<path
d="M113.462,155.688a1.878,1.878,0,0,0-1.284.494,1.97,1.97,0,0,0-.79,1.975V162.4H110.4V154.9h.988v1.086a2.162,2.162,0,0,1,.889-.988,3.155,3.155,0,0,1,1.383-.3Z"
transform="translate(-1.132 -70.438)"
fill="#ffe"
/>
<path
d="M122.008,154.9l-3.161,7.507h-1.087L114.6,154.9h1.087l2.667,6.223,2.568-6.223Z"
transform="translate(-1.184 -70.441)"
fill="#ffe"
/>
<path
d="M135.1,157.168h-1.185a2.869,2.869,0,0,0-1.087-1.087,2.787,2.787,0,0,0-1.482-.4,3.452,3.452,0,0,0-2.173.79,2.69,2.69,0,0,0-.889,2.074,2.91,2.91,0,0,0,2.963,2.963,2.787,2.787,0,0,0,1.482-.4,3.14,3.14,0,0,0,1.185-1.087H135a4.228,4.228,0,0,1-1.482,1.778,3.459,3.459,0,0,1-2.173.593,4.56,4.56,0,0,1-2.963-1.086,3.476,3.476,0,0,1-1.185-2.864,3.587,3.587,0,0,1,1.185-2.766,3.517,3.517,0,0,1,2.864-1.086,3.843,3.843,0,0,1,2.272.691,3.633,3.633,0,0,1,1.58,1.877"
transform="translate(-1.339 -70.437)"
fill="#ffe"
/>
<path
d="M145,159.047h-6.815a2.112,2.112,0,0,0,.889,1.778,2.937,2.937,0,0,0,1.975.79,2.985,2.985,0,0,0,1.58-.494,2.513,2.513,0,0,0,1.087-1.185H144.8a4.281,4.281,0,0,1-3.753,2.667,3.88,3.88,0,0,1-2.766-1.087,3.737,3.737,0,0,1-1.185-2.766,3.587,3.587,0,0,1,1.185-2.766,3.738,3.738,0,0,1,2.766-1.185,3.956,3.956,0,0,1,2.864,1.185A3.809,3.809,0,0,1,145,159.047m-.988-.988a2.669,2.669,0,0,0-.988-1.679,2.893,2.893,0,0,0-3.753,0,2.908,2.908,0,0,0-.988,1.778h5.729Z"
transform="translate(-1.46 -70.439)"
fill="#ffe"
/>
<rect width="3.26" height="10.667" transform="translate(140.282 62.137)" fill="#ffe" />
<rect width="4.346" height="1.58" transform="translate(139.788 59.075)" fill="#ffe" />
<path
d="M60.6,136.944a6.1,6.1,0,0,0,5.926,6.025H68.5v.988a.556.556,0,0,1-.691.593H66.329v3.161a6,6,0,0,0,5.433-5.926V132.4H65.045a4.577,4.577,0,0,0-4.445,4.544m8,2.667H64.748a.885.885,0,0,1-.889-.889h0V136.45a.885.885,0,0,1,.889-.889H68.6Z"
transform="translate(-0.522 -70.165)"
fill="#ffe"
/>
<path
d="M124.26,138.781V129.2H121v7.7a5.986,5.986,0,0,0,6.025,6.025h12.84v-3.26H125.148a.885.885,0,0,1-.889-.889"
transform="translate(-1.262 -70.125)"
fill="#ffe"
/>
<path
d="M78.433,139.215V132.4h-3.26v11.655a.661.661,0,0,1-.593.691H73v3.161a5.935,5.935,0,0,0,5.433-5.531,3.9,3.9,0,0,0,2.766.691H96.31v-3.26H79.025c-.3-.1-.593-.3-.593-.593"
transform="translate(-0.674 -70.165)"
fill="#ffe"
/>
<path
d="M115.907,143.561a.885.885,0,0,1-.889.889H103.66V132.4H100.4v15.31h13.927a4.848,4.848,0,0,0,4.84-4.84h0V132.4h-3.259Z"
transform="translate(-1.01 -70.165)"
fill="#ffe"
/>
<path
d="M109.88,132.361a1.58,1.58,0,1,0-1.58-1.58h0a1.56,1.56,0,0,0,1.58,1.58"
transform="translate(-1.107 -70.125)"
fill="#ffe"
/>
<path
d="M55.98,144.9a1.58,1.58,0,1,0,1.58,1.58h0a1.56,1.56,0,0,0-1.58-1.58"
transform="translate(-0.445 -70.318)"
fill="#ffe"
/>
<path
d="M52.68,144.9a1.58,1.58,0,1,0,1.58,1.58h0a1.56,1.56,0,0,0-1.58-1.58h0"
transform="translate(-0.405 -70.318)"
fill="#ffe"
/>
<path
d="M54.65,132.4v6.618a.661.661,0,0,1-.593.691h-16.1a.556.556,0,0,1-.593-.691V132.4H34.1v11.161a.885.885,0,0,1-.889.889H21.66V132.4H18.4v15.31H31.339c3.951,0,5.729-2.074,5.926-5.334a4.086,4.086,0,0,0,1.877.494H52.773c3.062-.1,5.136-2.864,5.136-5.926V132.4Z"
transform="translate(-0.004 -70.165)"
fill="#ffe"
/>
<path
d="M124.988,153.882H124V152.4h.988Zm0,8.494H124v-7.507h.988Z"
transform="translate(-1.3 -70.41)"
fill="#ffe"
/>
</g>
<g>
<path
d="M46.766,6.5A23.566,23.566,0,1,0,70.333,30.066,23.553,23.553,0,0,0,46.766,6.5m0,45.119a21.553,21.553,0,1,1,21.6-21.553,21.532,21.532,0,0,1-21.6,21.553"
transform="translate(-2.915)"
fill="#ffe"
/>
<path
d="M75.868,20.943V38.253a1.977,1.977,0,0,1-.857,1.671L68.584,44.38h0l-6.427-4.413A2.033,2.033,0,0,1,61.3,38.3V20.943a17.97,17.97,0,0,1,14.568,0"
transform="translate(-24.689 -7.373)"
fill="#ffe"
/>
<path
d="M54.139,60.793A18.041,18.041,0,0,1,42.827,28.7V45.239a2.733,2.733,0,0,0,1.2,2.314l8.741,6.042a2.53,2.53,0,0,0,2.785,0l8.784-6.042a2.733,2.733,0,0,0,1.2-2.314v-16.5a18.057,18.057,0,0,1-11.4,32.05"
transform="translate(-10.287 -12.688)"
fill="#ffe"
/>
</g>
</g>
</svg>
</template>
<script>
export default {
name: 'AsanServiceLogoSVG'
}
</script>
@@ -0,0 +1,167 @@
<template>
<el-dialog :title="title" :visible.sync="showModal">
<div v-loading="fetchingBuffers" class="addPtoPrModal">
<el-form label-position="top" :model="formData">
<el-form-item label="نام کالا" :class="validation.ItemName && 'err'">
<el-select v-model="selectedItem" filterable style="width: 100%">
<el-option-group label="لوازم جانبی کامپیوتر و موبایل">
<el-option
v-for="item in verityProducts"
:key="item.ItemID + '_V'"
:value="item.ItemID + '__v'"
:label="item.ItemName"
></el-option>
</el-option-group>
<el-option-group label="لوازم صوتی و تصویری خودرو">
<el-option
v-for="item in panatechProducts"
:key="item.ItemID + '_P'"
:value="item.ItemID + '__p'"
:label="item.ItemName"
></el-option>
</el-option-group>
</el-select>
<p v-if="validation.ItemName" class="errMsg">{{ validation.ItemName.msg }}</p>
</el-form-item>
<el-form-item label="تعداد درخواستی" :class="validation.bufferQuantity && 'err'">
<el-input
v-model="formData.bufferQuantity"
placeholder="تعداد را وارد کنید"
@input="normalizeQuantityInput"
></el-input>
<p v-if="validation.bufferQuantity" class="errMsg">{{ validation.bufferQuantity.msg }}</p>
</el-form-item>
</el-form>
<div class="btnRow">
<el-button class="btn btn-primary custom-el-button" :loading="postingForm" @click="add">افزودن</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'AddBuffersToBufferRequest',
props: {
show: {
type: Boolean,
default: false
},
brId: {
requred: true,
type: String,
default: null
}
},
data() {
return {
fetchingBuffers: false,
postingForm: false,
selectedItem: '',
formData: {
ItemName: '',
ItemID: '',
ItemCode: '',
bufferQuantity: ''
},
validation: {}
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
title() {
return 'افزودن کالای بافر به فرم'
},
bufferQuantity() {
return this.formData.bufferQuantity
},
verityProducts() {
return this.$store.state.front.verityProducts
},
panatechProducts() {
return this.$store.state.front.panatechProducts
}
},
watch: {
selectedItem() {
const selectedItem = this.selectedItem
let ItemID, db_name
if (selectedItem.includes('__v')) {
ItemID = selectedItem.replace('__v', '')
db_name = 'verity'
} else if (selectedItem.includes('__p')) {
ItemID = selectedItem.replace('__p', '')
db_name = 'panatech'
} else {
return this.$message({
type: 'error',
message: 'Invalid Value'
})
}
// find product
let products
if (db_name === 'verity') products = this.verityProducts
if (db_name === 'panatech') products = this.panatechProducts
const item = products.find(item => item.ItemID === ItemID)
this.formData.ItemName = item?.ItemName
this.formData.ItemID = item?.ItemID
this.formData.ItemCode = item?.ItemCode
}
},
methods: {
normalizeQuantityInput() {
this.formData.bufferQuantity = this.formData.bufferQuantity.toString().replace(/[^0-9]/g, '')
if (
this.formData.bufferQuantity === '' ||
this.formData.bufferQuantity === null ||
this.formData.bufferQuantity < 1
) {
this.formData.bufferQuantity = 1
}
},
add() {
this.validation = {}
this.postingForm = true
const data = this.formData
this.$axios
.put(`/api/agent/addBrItems/${this.brId}`, data)
.then(res => {
this.postingForm = false
this.showModal = false
this.$message({
type: 'success',
message: 'کالای بافر درخواستی به فرم افزوده شد'
})
this.$nuxt.refresh()
})
.catch(err => {
this.postingForm = false
if (err.response.status === 422) {
this.$message({
type: 'warning',
message: 'پارامترها رو بررسی و دوباره تلاش کنید'
})
this.validation = err.response.data.validation
} else {
this.$message({
type: 'error',
message: err.response?.data?.message
})
}
})
}
}
}
</script>
@@ -0,0 +1,207 @@
<template>
<el-dialog :title="title" :visible.sync="showModal">
<div v-loading="fetchingPieces" class="addPtoPrModal">
<el-form label-position="top" :model="formData">
<h3 class="mb-3">مشخصات کالا:</h3>
<el-form-item label="تاریخ پذیرش" :class="validation.ItemReceptionTransDate && 'err'">
<div class="datePickerWrapper">
<persian-date-picker
v-model="formData.ItemReceptionTransDate"
display-format="jYYYY/jMM/jDD"
format="YYYY-MM-DD HH:mm:ss"
placeholder="تاریخ را انتخاب کنید"
color="#065495"
/>
</div>
<p v-if="validation.ItemReceptionTransDate" class="errMsg">{{ validation.ItemReceptionTransDate.msg }}</p>
</el-form-item>
<el-form-item label="نام کالا" :class="validation.ItemName && 'err'">
<el-select v-model="selectedItem" filterable style="width: 100%">
<el-option-group label="لوازم جانبی کامپیوتر و موبایل">
<el-option
v-for="item in verityProducts"
:key="item.ItemID + '_V'"
:value="item.ItemID + '__v'"
:label="item.ItemName"
></el-option>
</el-option-group>
<el-option-group label="لوازم صوتی و تصویری خودرو">
<el-option
v-for="item in panatechProducts"
:key="item.ItemID + '_P'"
:value="item.ItemID + '__p'"
:label="item.ItemName"
></el-option>
</el-option-group>
</el-select>
<p v-if="validation.ItemName" class="errMsg">{{ validation.ItemName.msg }}</p>
</el-form-item>
<el-form-item label="سریال">
<el-input v-model="formData.SerialNo1" placeholder="اختیاری"></el-input>
</el-form-item>
<h3 class="mb-3">مشخصات قطعه درخواستی:</h3>
<el-form-item label="نام قطعه" :class="validation.pieceName && 'err'">
<el-select v-model="selectedPiece" filterable style="width: 100%">
<el-option
v-for="item in pieces"
:key="item._id"
:value="item._id"
:label="item.name + ` ( کد: ${item.code} ) `"
></el-option>
</el-select>
<p v-if="validation.pieceName" class="errMsg">{{ validation.pieceName.msg }}</p>
</el-form-item>
</el-form>
<div class="btnRow">
<el-button class="btn btn-primary custom-el-button" :loading="postingForm" @click="add">افزودن</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'AddOldPiecesToOldPieceRequest',
props: {
show: {
type: Boolean,
default: false
},
oprId: {
requred: true,
type: String,
default: null
}
},
data() {
return {
fetchingPieces: false,
postingForm: false,
pieces: [],
selectedItem: '',
selectedPiece: '',
formData: {
ItemReceptionTransDate: '',
ItemName: '',
SerialNo1: '',
ItemID: '',
ItemCode: '',
// piece info
pieceName: '',
pieceCode: '',
pieceId: ''
},
validation: {}
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
title() {
return 'افزودن قطعه داغی به فرم'
},
verityProducts() {
return this.$store.state.front.verityProducts
},
panatechProducts() {
return this.$store.state.front.panatechProducts
}
},
watch: {
showModal(newVal, oldVal) {
if (newVal) {
this.fetchingPieces = true
this.$axios
.get('/api/agent/pieces')
.then(res => {
this.fetchingPieces = false
this.pieces = res.data
})
.catch(err => {
console.log(err)
})
}
},
selectedItem() {
const selectedItem = this.selectedItem
let ItemID, db_name
if (selectedItem.includes('__v')) {
ItemID = selectedItem.replace('__v', '')
db_name = 'verity'
} else if (selectedItem.includes('__p')) {
ItemID = selectedItem.replace('__p', '')
db_name = 'panatech'
} else {
return this.$message({
type: 'error',
message: 'Invalid Value'
})
}
// find product
let products
if (db_name === 'verity') products = this.verityProducts
if (db_name === 'panatech') products = this.panatechProducts
const item = products.find(item => item.ItemID === ItemID)
this.formData.ItemName = item?.ItemName
this.formData.ItemID = item?.ItemID
this.formData.ItemCode = item?.ItemCode
},
selectedPiece() {
const item = this.pieces.find(item => item._id === this.selectedPiece)
this.formData.pieceId = item?._id
this.formData.pieceName = item?.name
this.formData.pieceCode = item?.code
}
},
methods: {
add() {
this.validation = {}
this.postingForm = true
const data = this.formData
this.$axios
.put(`/api/agent/addOprItems/${this.oprId}`, data)
.then(res => {
this.postingForm = false
this.showModal = false
this.$message({
type: 'success',
message: 'قطعه داغی درخواستی به فرم افزوده شد'
})
this.$nuxt.refresh()
})
.catch(err => {
this.postingForm = false
if (err.response.status === 422) {
this.$message({
type: 'warning',
message: 'پارامترها رو بررسی و دوباره تلاش کنید'
})
this.validation = err.response.data.validation
} else {
this.$message({
type: 'error',
message: err.response?.data?.message
})
}
})
}
}
}
</script>
@@ -0,0 +1,239 @@
<template>
<el-dialog :title="title" :visible.sync="showModal">
<div v-loading="fetchingPieces" class="addPtoPrModal">
<el-form label-position="top" :model="formData">
<h3 class="mb-3">مشخصات کالا:</h3>
<el-form-item label="تاریخ پذیرش" :class="validation.ItemReceptionTransDate && 'err'">
<div class="datePickerWrapper">
<persian-date-picker
v-model="formData.ItemReceptionTransDate"
display-format="jYYYY/jMM/jDD"
format="YYYY-MM-DD HH:mm:ss"
placeholder="تاریخ را انتخاب کنید"
color="#065495"
/>
</div>
<p v-if="validation.ItemReceptionTransDate" class="errMsg">{{ validation.ItemReceptionTransDate.msg }}</p>
</el-form-item>
<el-form-item label="نام کالا" :class="validation.ItemName && 'err'">
<el-select v-model="selectedItem" filterable style="width: 100%">
<el-option-group label="لوازم جانبی کامپیوتر و موبایل">
<el-option
v-for="item in verityProducts"
:key="item.ItemID + '_V'"
:value="item.ItemID + '__v'"
:label="item.ItemName"
></el-option>
</el-option-group>
<el-option-group label="لوازم صوتی و تصویری خودرو">
<el-option
v-for="item in panatechProducts"
:key="item.ItemID + '_P'"
:value="item.ItemID + '__p'"
:label="item.ItemName"
></el-option>
</el-option-group>
</el-select>
<p v-if="validation.ItemName" class="errMsg">{{ validation.ItemName.msg }}</p>
</el-form-item>
<el-form-item label="سریال">
<el-input v-model="formData.SerialNo1" placeholder="اختیاری"></el-input>
</el-form-item>
<el-form-item label="وضعیت گارانتی" :class="validation.gStatus && 'err'">
<el-select v-model="formData.gStatus" style="width: 100%">
<el-option :value="true" label="دارد"></el-option>
<el-option :value="false" label="ندارد"></el-option>
</el-select>
<p v-if="validation.gStatus" class="errMsg">{{ validation.gStatus.msg }}</p>
</el-form-item>
<h3 class="mb-3">مشخصات قطعه درخواستی:</h3>
<el-form-item label="نام قطعه" :class="validation.pieceName && 'err'">
<el-select v-model="selectedPiece" filterable style="width: 100%">
<el-option
v-for="item in pieces"
:key="item._id"
:value="item._id"
:label="item.name + ` ( کد: ${item.code} ) `"
></el-option>
</el-select>
<p v-if="validation.pieceName" class="errMsg">{{ validation.pieceName.msg }}</p>
</el-form-item>
<el-form-item label="تعداد درخواستی" :class="validation.pieceQuantity && 'err'">
<el-input
v-model="formData.pieceQuantity"
placeholder="تعداد را وارد کنید"
@input="normalizeQuantityInput"
></el-input>
<p v-if="validation.pieceQuantity" class="errMsg">{{ validation.pieceQuantity.msg }}</p>
</el-form-item>
</el-form>
<div class="btnRow">
<el-button class="btn btn-primary custom-el-button" :loading="postingForm" @click="add">افزودن</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'AddPiecesToPieceRequest',
props: {
show: {
type: Boolean,
default: false
},
prId: {
requred: true,
type: String,
default: null
}
},
data() {
return {
fetchingPieces: false,
postingForm: false,
pieces: [],
selectedItem: '',
selectedPiece: '',
formData: {
ItemReceptionTransDate: '',
ItemName: '',
SerialNo1: '',
ItemID: '',
ItemCode: '',
gStatus: '',
// piece info
pieceName: '',
pieceCode: '',
pieceQuantity: '',
pieceId: ''
},
validation: {}
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
title() {
return 'افزودن قطعه به فرم'
},
pieceQuantity() {
return this.formData.pieceQuantity
},
verityProducts() {
return this.$store.state.front.verityProducts
},
panatechProducts() {
return this.$store.state.front.panatechProducts
}
},
watch: {
showModal(newVal, oldVal) {
if (newVal) {
this.fetchingPieces = true
this.$axios
.get('/api/agent/pieces')
.then(res => {
this.fetchingPieces = false
this.pieces = res.data
})
.catch(err => {
console.log(err)
})
}
},
selectedItem() {
const selectedItem = this.selectedItem
let ItemID, db_name
if (selectedItem.includes('__v')) {
ItemID = selectedItem.replace('__v', '')
db_name = 'verity'
} else if (selectedItem.includes('__p')) {
ItemID = selectedItem.replace('__p', '')
db_name = 'panatech'
} else {
return this.$message({
type: 'error',
message: 'Invalid Value'
})
}
// find product
let products
if (db_name === 'verity') products = this.verityProducts
if (db_name === 'panatech') products = this.panatechProducts
const item = products.find(item => item.ItemID === ItemID)
this.formData.ItemName = item?.ItemName
this.formData.ItemID = item?.ItemID
this.formData.ItemCode = item?.ItemCode
},
selectedPiece() {
const item = this.pieces.find(item => item._id === this.selectedPiece)
this.formData.pieceId = item?._id
this.formData.pieceName = item?.name
this.formData.pieceCode = item?.code
}
},
methods: {
normalizeQuantityInput() {
this.formData.pieceQuantity = this.formData.pieceQuantity.toString().replace(/[^0-9]/g, '')
if (
this.formData.pieceQuantity === '' ||
this.formData.pieceQuantity === null ||
this.formData.pieceQuantity < 1
) {
this.formData.pieceQuantity = 1
}
},
add() {
this.validation = {}
this.postingForm = true
const data = this.formData
this.$axios
.put(`/api/agent/addPrItems/${this.prId}`, data)
.then(res => {
this.postingForm = false
this.showModal = false
this.$message({
type: 'success',
message: 'قطعه درخواستی به فرم افزوده شد'
})
this.$nuxt.refresh()
})
.catch(err => {
this.postingForm = false
if (err.response.status === 422) {
this.$message({
type: 'warning',
message: 'پارامترها رو بررسی و دوباره تلاش کنید'
})
this.validation = err.response.data.validation
} else {
this.$message({
type: 'error',
message: err.response?.data?.message
})
}
})
}
}
}
</script>
@@ -0,0 +1,223 @@
<template>
<el-dialog :title="title" :visible.sync="showModal">
<div class="addPtoPrModal reportModal">
<el-form label-position="top" :model="formData">
<el-form-item label="نام و نام خانوادگی مشتری" :class="validation.customerName && 'err'">
<el-input v-model="formData.customerName" placeholder="نام را وارد کنید"></el-input>
<p v-if="validation.customerName" class="errMsg">{{ validation.customerName.msg }}</p>
</el-form-item>
<el-form-item label="شماره تماس مشتری" :class="validation.customerTel && 'err'">
<el-input v-model="formData.customerTel" placeholder="شماره را وارد کنید"></el-input>
<p v-if="validation.customerTel" class="errMsg">{{ validation.customerTel.msg }}</p>
</el-form-item>
<el-form-item label="مدل کالا" :class="validation.ItemName && 'err'">
<el-select v-model="selectedItem" filterable style="width: 100%">
<el-option-group label="لوازم جانبی کامپیوتر و موبایل">
<el-option
v-for="item in verityProducts"
:key="item.ItemID + '_V'"
:value="item.ItemID + '__v'"
:label="item.ItemName"
></el-option>
</el-option-group>
<el-option-group label="لوازم صوتی و تصویری خودرو">
<el-option
v-for="item in panatechProducts"
:key="item.ItemID + '_P'"
:value="item.ItemID + '__p'"
:label="item.ItemName"
></el-option>
</el-option-group>
</el-select>
<p v-if="validation.ItemName" class="errMsg">{{ validation.ItemName.msg }}</p>
</el-form-item>
<el-form-item label="سریال">
<el-input v-model="formData.SerialNo1" placeholder="اختیاری"></el-input>
</el-form-item>
<el-form-item label="ایراد کالا" :class="validation.productIssue && 'err'">
<el-input
v-model="formData.productIssue"
type="textarea"
:rows="5"
placeholder="شرح ایرادات کالا را بنویسید"
></el-input>
<p v-if="validation.productIssue" class="errMsg">{{ validation.productIssue.msg }}</p>
</el-form-item>
<el-form-item label="قطعات مصرفی" :class="validation.usedPieces && 'err'">
<el-input
v-model="formData.usedPieces"
type="textarea"
:rows="5"
placeholder="شرح قطقات مصرفی را بنویسید"
></el-input>
<p v-if="validation.usedPieces" class="errMsg">{{ validation.usedPieces.msg }}</p>
</el-form-item>
<el-form-item label="تاریخ دریافت از مشتی" :class="validation.recieveDate && 'err'">
<div class="datePickerWrapper">
<persian-date-picker
v-model="formData.recieveDate"
display-format="jYYYY/jMM/jDD"
format="YYYY-MM-DD HH:mm:ss"
placeholder="تاریخ را انتخاب کنید"
color="#065495"
/>
</div>
<p v-if="validation.recieveDate" class="errMsg">{{ validation.recieveDate.msg }}</p>
</el-form-item>
<el-form-item label="تاریخ تحویل به مشتری" :class="validation.deliverDate && 'err'">
<div class="datePickerWrapper">
<persian-date-picker
v-model="formData.deliverDate"
display-format="jYYYY/jMM/jDD"
format="YYYY-MM-DD HH:mm:ss"
:min="formData.recieveDate"
placeholder="تاریخ را انتخاب کنید"
color="#065495"
/>
</div>
<p v-if="validation.deliverDate" class="errMsg">{{ validation.deliverDate.msg }}</p>
</el-form-item>
</el-form>
<div class="btnRow">
<el-button class="btn btn-primary custom-el-button" :loading="postingForm" @click="add">افزودن</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'AddReportToGuaranteeReportForm',
props: {
show: {
type: Boolean,
default: false
},
grId: {
requred: true,
type: String,
default: null
}
},
data() {
return {
postingForm: false,
selectedItem: '',
formData: {
customerName: '',
customerTel: '',
// product info
ItemName: '',
SerialNo1: '',
ItemID: '',
ItemCode: '',
// product issue
productIssue: '',
usedPieces: '',
// dates
recieveDate: '',
deliverDate: ''
},
validation: {}
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
title() {
return 'افزودن گزارش به فرم'
},
verityProducts() {
return this.$store.state.front.verityProducts
},
panatechProducts() {
return this.$store.state.front.panatechProducts
},
recieveDate() {
return this.formData.recieveDate
}
},
watch: {
recieveDate(newVal, oldVal) {
this.formData.deliverDate = ''
},
selectedItem() {
const selectedItem = this.selectedItem
let ItemID, db_name
if (selectedItem.includes('__v')) {
ItemID = selectedItem.replace('__v', '')
db_name = 'verity'
} else if (selectedItem.includes('__p')) {
ItemID = selectedItem.replace('__p', '')
db_name = 'panatech'
} else {
return this.$message({
type: 'error',
message: 'Invalid Value'
})
}
// find product
let products
if (db_name === 'verity') products = this.verityProducts
if (db_name === 'panatech') products = this.panatechProducts
const item = products.find(item => item.ItemID === ItemID)
this.formData.ItemName = item?.ItemName
this.formData.ItemID = item?.ItemID
this.formData.ItemCode = item?.ItemCode
}
},
methods: {
add() {
this.validation = {}
this.postingForm = true
const data = this.formData
this.$axios
.put(`/api/agent/addGrItems/${this.grId}`, data)
.then(res => {
this.postingForm = false
this.showModal = false
this.$message({
type: 'success',
message: 'گزارش به فرم افزوده شد'
})
this.$nuxt.refresh()
})
.catch(err => {
this.postingForm = false
if (err.response.status === 422) {
this.$message({
type: 'warning',
message: 'پارامترها رو بررسی و دوباره تلاش کنید'
})
this.validation = err.response.data.validation
} else {
this.$message({
type: 'error',
message: err.response?.data?.message
})
}
})
}
}
}
</script>
+300
View File
@@ -0,0 +1,300 @@
<template>
<el-dialog :title="title" :visible.sync="showModal">
<div>
<form v-loading="fetchingSerials" class="form form_3 stuffModal" @submit.prevent="addStuff">
<div class="formRow">
<el-select
v-if="!currentItem.name"
ref="productSelector"
v-model="currentItem.item"
filterable
:placeholder="productsPlaceholder"
>
<el-option v-for="item in products" :key="item.ItemID" :label="item.ItemName" :value="item.ItemID">
</el-option>
</el-select>
<p v-else>
<b>نام کالا: </b>
<span>{{ currentItem.name }}</span>
<span style="margin: 0 5px"> - </span>
<i style="color: blue; font-weight: bold; cursor: pointer" @click="changeProduct">تغییر کالا</i>
</p>
</div>
<div
v-if="currentItem.item && !serials.length && !fetchingSerials"
class="formRow"
:class="validation.quantity ? 'err' : null"
>
<p style="user-select: none">
<b style="margin-left: 10px">تعداد: </b>
<i
style="color: #bf6060; cursor: pointer"
class="fas fa-minus-circle"
@click="changeQuantity('decrease')"
></i>
<!-- <span style="font-weight: bold;margin: 0 5px">{{ currentItem.quantity }}</span> -->
<input
ref="quantityInput"
v-model="currentItem.quantity"
type="text"
style="
width: 50px;
display: inline-block;
border-radius: 50px;
padding: 5px;
direction: ltr;
text-align: center;
"
@input="normalizeQuantityInput"
/>
<i
style="color: #658865; cursor: pointer"
class="fas fa-plus-circle"
@click="changeQuantity('increase')"
></i>
</p>
</div>
<div v-if="serials.length" class="formRow" :class="serialInput.length && !isValid ? 'err' : null">
<el-input
v-if="!currentItem.SerialNo1"
ref="serialInput"
v-model="serialInput"
:disabled="isValid"
placeholder="شماره سریال را به صورت کامل وارد کنید"
@input="checkSerial"
>
<template v-if="serialInput.length">
<i v-if="isValid" slot="prefix" style="color: green" class="el-input__icon fas fa-check-circle"></i>
<i v-else slot="prefix" style="color: red" class="el-input__icon fas fa-exclamation-circle"></i>
</template>
</el-input>
<p v-else>
<b>شماره سریال: </b>
<span>{{ currentItem.SerialNo1 }}</span>
<span style="margin: 0 5px"> - </span>
<i v-if="isValid" style="color: blue; font-weight: bold; cursor: pointer" @click="changeSerial">
تغییر شماره سریال
</i>
</p>
</div>
<div v-if="addBtnVisible" class="formRow">
<button id="addBtn" ref="addBtn" type="submit" class="btn btn-primary">افزودن</button>
</div>
</form>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'AddStuffModal',
props: {
show: {
type: Boolean,
default: false
},
db_name: {
type: String,
required: true
}
},
data() {
return {
serials: [],
fetchingSerials: false,
currentItem: {
name: null,
item: null,
quantity: 1,
SerialNo1: '',
GStartDate: '',
GEndDate: ''
},
isValid: false,
serialInput: '',
validation: {}
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
title() {
if (this.db_name === 'panatech') return 'افزودن کالاهای صوتی تصویری به فرم'
if (this.db_name === 'verity') return 'افزودن کالاهای لوازم جانبی به فرم'
else return ''
},
products() {
if (this.db_name === 'verity') return this.$store.state.front.verityProducts
else if (this.db_name === 'panatech') return this.$store.state.front.panatechProducts
else return []
},
productsPlaceholder() {
return this.products ? 'نام کالا را جستجو کنید' : 'درحال بارگیری اطلاعات...'
},
selectedItem() {
return this.currentItem.item
},
selectedSerial() {
return this.currentItem.SerialNo1
},
addBtnVisible() {
if (this.serials.length) {
return this.currentItem.item && this.currentItem.SerialNo1
} else {
return this.currentItem.item && !this.fetchingSerials
}
}
},
watch: {
addBtnVisible(newVal, oldVal) {
if (newVal) {
if (this.serials.length) setTimeout(() => this.$refs.addBtn?.focus(), 300)
else setTimeout(() => this.$refs.quantityInput?.focus(), 300)
}
},
async selectedSerial(newVal, oldVal) {
if (newVal) {
const serialObject = await this.serials.filter(item => item.SerialNo1 === newVal)[0]
this.currentItem.GStartDate = serialObject.GStartDate
this.currentItem.GEndDate = serialObject.GEndDate
} else {
this.currentItem.GStartDate = ''
this.currentItem.GEndDate = ''
}
},
async selectedItem(newVal, oldVal) {
if (newVal) {
try {
this.fetchingSerials = true
this.currentItem.SerialNo1 = ''
this.serials = []
this.currentItem.name = null
const item = await this.products.filter(item => item.ItemID === newVal)[0]
this.currentItem.name = item.ItemName
const serialsData = {
url: `/api/GetSerials?ItemCode=${item.ItemCode}&QtyStatus=1`,
db: this.db_name
}
const serials = await this.$axios.post('/api/cross/getRouteManager', serialsData, {
progress: false
})
this.serials = serials.data.data
this.fetchingSerials = false
setTimeout(() => this.$refs.serialInput?.focus(), 300)
} catch (e) {
this.currentItem = {
item: '',
quantity: 1,
SerialNo1: '',
GStartDate: '',
GEndDate: ''
}
console.log(e)
return this.$message({
type: 'error',
message: 'مشکلی در دریافت اطلاعات پیش آمده، لطفا نام کالا را دوباره انتخاب کنید.'
})
}
} else {
this.serials = []
}
},
serials(newVal, oldVal) {
this.currentItem.quantity = 1
},
showModal(newVal, oldVal) {
if (newVal) {
this.$nextTick(() => {
this.$refs?.productSelector?.focus()
})
}
}
},
methods: {
changeProduct() {
this.currentItem.item = this.currentItem.name = null
this.isValid = false
this.serialInput = ''
},
changeSerial() {
this.currentItem.SerialNo1 = ''
this.isValid = false
this.serialInput = ''
setTimeout(() => this.$refs.serialInput?.focus(), 300)
},
checkSerial(serial) {
const SerialNo1 = this.serials.find(item => item.SerialNo1.toLowerCase() === serial.toLowerCase())
if (SerialNo1) {
this.isValid = true
this.currentItem.SerialNo1 = SerialNo1.SerialNo1
} else this.isValid = false
},
changeQuantity(mode) {
if (mode === 'increase') this.currentItem.quantity++
else if (mode === 'decrease' && this.currentItem.quantity > 1) this.currentItem.quantity--
},
addStuff() {
if (this.serials.length && !this.currentItem.SerialNo1) {
return this.$message({
type: 'warning',
message: 'شماره سریال معتبر وارد کنید'
})
}
this.fetchingSerials = true
const currentItem = this.currentItem
const selectedItem = this.products.filter(item => item.ItemID === currentItem.item)[0]
const item = {
ItemID: selectedItem.ItemID,
ItemCode: selectedItem.ItemCode,
MjQty: Number(currentItem.quantity),
SerialNo1: currentItem.SerialNo1,
GStartDate: currentItem.GStartDate,
GEndDate: currentItem.GEndDate
}
this.$axios
.put(`/api/user/transactionDraftItemAdd/${this.$route.params.draftID}`, item, { progress: false })
.then(res => {
this.fetchingSerials = false
this.$message({
type: 'success',
message: res.data.message
})
this.showModal = false
this.$nuxt.refresh()
})
.catch(err => {
this.fetchingSerials = false
if (err.response.status === 406) {
return this.$message({
type: 'warning',
message: err.response.data.message
})
} else {
return this.$message({
type: 'error',
message: 'مشکلی در ثبت اطلاعات پیش آمده، لطفا دوباره امتحان کنید'
})
}
})
},
normalizeQuantityInput() {
this.currentItem.quantity = this.currentItem.quantity.toString().replace(/[^0-9]/g, '')
if (this.currentItem.quantity === '' || this.currentItem.quantity === null || this.currentItem.quantity < 1) {
this.currentItem.quantity = 1
}
}
}
}
</script>
@@ -0,0 +1,233 @@
<template>
<el-dialog :title="title" :visible.sync="showModal">
<div v-loading="fetchingDrafts">
<template v-if="!addingStuff">
<h3 class="mb-3">پیشنویس مورد نظر جهت افزودن اقلام انتخاب شده را انتخاب کنید:</h3>
<div class="tableBox">
<table class="drafts-modal">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="description">توضیحات</th>
<th class="brand">نوع</th>
<th class="quantity">تعداد کالاها</th>
<th class="details">افزودن</th>
</tr>
</thead>
<tbody>
<template v-if="filteredDrafts.length">
<tr v-for="(item, index) in filteredDrafts" :key="item._id" :title="item.description">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="description">
<span v-if="item.description" class="singleLineTxt">{{ item.description }}</span>
<span v-else style="color: gray">بدون توضیحات</span>
</td>
<td class="brand">
<!-- <img src="/assets/img/verity-small.png" alt="verity" v-if="item.db_name === 'verity'" />
<img src="/assets/img/panatech-small.png" alt="panatech" v-if="item.db_name === 'panatech'" /> -->
<i
v-if="item.db_name === 'verity'"
class="fas fa-phone-laptop"
title="لوازم جانبی کامپیوتر و موبایل"
></i>
<i
v-if="item.db_name === 'panatech'"
class="fas fa-photo-video"
title="لوازم صوتی و تصویری خودرو"
></i>
</td>
<td class="quantity">
<span>{{ totalItemsCount(item) }}</span>
</td>
<td class="details">
<button class="btn btn-primary" @click="addStuffToDraft(item._id)">
<i class="fas fa-link"></i>
</button>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<template v-else>
<el-progress
class="mb-3"
:text-inside="true"
:stroke-width="20"
:percentage="addProgress"
:status="addProgressStatus"
></el-progress>
<div class="tableBox">
<table class="drafts-modal">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="name">نام</th>
<th class="quantity">تعداد کالاها</th>
<th class="brand">شماره سریال</th>
<th class="addStatus">وضعیت</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in addedStuff" :key="index + '_addedStuff_modal_itemStatus'">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="name">
<span class="singleLineTxt" :title="getItemName(item.ItemID)">{{ getItemName(item.ItemID) }}</span>
</td>
<td class="quantity">
<span>{{ item.MjQty }}</span>
</td>
<td class="brand">
<span> {{ item.SerialNo1 || '-' }} </span>
</td>
<td class="addStatus">
<i
v-if="item.status"
class="el-icon-success"
style="color: rgb(19, 206, 102)"
:title="item.statusTxt"
></i>
<i v-else class="el-icon-info" style="color: orange" :title="item.statusTxt"></i>
</td>
</tr>
</tbody>
</table>
</div>
</template>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'AddUserItemsToAgentDraft',
props: {
show: {
type: Boolean,
default: false
},
db_name: {
type: String,
required: true
},
items: {
type: Array,
required: true
}
},
data() {
return {
fetchingDrafts: false,
addingStuff: false,
addProgress: 0,
addProgressStatus: 'success',
transactionDrafts: [],
addedStuff: [],
validation: {}
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
title() {
if (this.db_name === 'panatech') return 'افزودن کالاهای صوتی تصویری به فرم'
if (this.db_name === 'verity') return 'افزودن کالاهای لوازم جانبی به فرم'
else return ''
},
filteredDrafts() {
return this.transactionDrafts.filter(item => item.db_name === this.db_name)
},
products() {
if (this.db_name === 'verity') return this.$store.state.front.verityProducts
else if (this.db_name === 'panatech') return this.$store.state.front.panatechProducts
else return []
}
},
watch: {
showModal(newVal, oldVal) {
if (newVal) {
this.fetchingDrafts = true
this.$axios
.get('/api/user/transactionDrafts')
.then(res => {
this.transactionDrafts = res.data
this.fetchingDrafts = false
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در دریافت اطلاعات پیش آمده'
})
this.showModal = false
})
}
}
},
methods: {
totalItemsCount(draft) {
const items = draft.items
let count = 0
items.forEach(item => (count += item.MjQty))
return count
},
getItemName(ItemID) {
return this.products.find(item => item.ItemID === ItemID)?.ItemName
},
async addStuffToDraft(draftId) {
this.addingStuff = true
try {
let index = 1
for await (const item of this.items) {
this.addProgress = Number(((index * 100) / this.items.length).toFixed(0))
await new Promise((resolve, reject) => {
index++
this.$axios
.put(`/api/user/transactionDraftItemAdd/${draftId}`, item, { progress: false })
.then(res => {
this.addedStuff.push({ ...item, status: true, statusTxt: res.data.message })
resolve()
})
.catch(err => {
this.addedStuff.push({ ...item, status: false, statusTxt: err.response.data.message })
this.addProgressStatus = 'warning'
resolve()
})
})
}
} catch (e) {
this.$message({
type: 'error',
message: 'مشکلی در ثبت اطلاعات پیش آمده'
})
}
}
}
}
</script>
+99
View File
@@ -0,0 +1,99 @@
<template>
<el-dialog :title="title" :visible.sync="showModal">
<div>
<form class="form form_3 stuffModal" @submit.prevent="change">
<div class="formRow" :class="[validation.email && 'err', validation.mobile && 'err']">
<el-input v-model="input" :placeholder="inputPlaceholder"> </el-input>
<p v-if="validation.email">{{ validation.email.msg }}</p>
<p v-if="validation.mobile">{{ validation.mobile.msg }}</p>
</div>
<div class="formRow">
<el-button
class="btn btn-primary custom-el-button"
type="primary"
native-type="submit"
:loading="posting"
:disabled="input.length < 1"
>
تغییر
</el-button>
</div>
</form>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'ChangeEmailOrMobileModal',
props: {
show: {
type: Boolean,
default: false
},
type: {
required: true,
type: String
}
},
data() {
return {
input: '',
posting: false,
validation: {}
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
title() {
if (this.type === 'mobile') return 'تغییر شماره موبایل'
if (this.type === 'email') return 'تغییر ایمیل'
else return ''
},
inputPlaceholder() {
if (this.type === 'mobile') return 'شماره موبایل خود را وارد کنید'
if (this.type === 'email') return 'ایمیل خود را وارد کنید'
else return ''
}
},
methods: {
async change() {
try {
this.posting = true
this.validation = {}
let res
if (this.type === 'email') {
res = await this.$axios.put('/api/user/changeEmail', { email: this.input })
}
if (this.type === 'mobile') {
res = await this.$axios.put('/api/user/changeMobile', { mobile: this.input })
}
this.posting = false
this.$message({
type: 'success',
message: res.data.message
})
this.$auth.fetchUser()
this.showModal = false
} catch (err) {
this.posting = false
if (err.response.status === 422) this.validation = err.response.data.validation
else {
this.$message({
type: 'error',
message: 'مشکلی در بروزرسانی اطلاعات پیش آمده'
})
}
}
}
}
}
</script>
+230
View File
@@ -0,0 +1,230 @@
<template>
<el-dialog title="انتخاب نمایندگی و ارسال فرم" :visible.sync="showModal">
<div v-loading="fetchingAgents" class="terms">
<h2>تعهدنامه:</h2>
<p class="mb-5">
کاربر محترم درخواست کننده خدمت با تایید این متن هرگونه ادعایی خارج از پروتکل های اعلامی این شرکت را از خود سلب
مینماید و تشخیص و سنجش کارشناسان واحد خدمات پس از فروش آسان سرویس ملاک عمل خواهد بود .دریافت کننده خدمات با
تایید این متن تصدیق مینماید موارد خارج از شمول گارانتی اعلامی توسط آسان سرویس را میپذیرد .در صورتیکه کالایی فاقد
شرایط گارانتی باشد نخست جهت تعمیر به درخواست کننده خدمت در این سامانه اطلاع رسانی میگردد و در صورت عدم اعلام نظر
توسط کاربر جهت ثبت درخواست تعمیر ،کالای مذکور به نشانی کاربر عودت خواهد گردید.
</p>
<h4>موارد خارج از شمول گارانتی :</h4>
<ol>
<li>
<p>دستکاری توسط افراد غیر مجاز</p>
</li>
<li>
<p>مغایرت محصول با پک و یا نداشتن پک</p>
</li>
<li>
<p>شکستگی، ضربه خوردگی، آبخوردگی</p>
</li>
<li>
<p>مخدوش بودن سریال کالا با کارت گارانتی و پکیج محصول</p>
</li>
<li>
<p>کسورات لوازم جانبی و قطعات محصول در پک</p>
</li>
</ol>
<div class="form form_2">
<div class="formRow">
<label for="accept">
<input id="accept" v-model="termsOfUse" type="checkbox" />
<span>قوانین را میپذیرم</span>
</label>
</div>
<div class="formRow agents">
<el-select
v-model="agent"
:disabled="!termsOfUse || user.isAgent"
filterable
placeholder="نماینگی نزدیک خودرا انتخاب کنید"
>
<el-option label="شرکت آسان سرویس (تهران)" value="main"></el-option>
<el-option
v-for="item in filteredAgents"
:key="item._id"
:label="agentName(item)"
:title="agentName(item)"
:value="item._id"
>
</el-option>
</el-select>
<el-button
class="btn btn-primary custom-el-button"
:disabled="!termsOfUse"
:loading="postingForm"
@click="sendForm"
>
ارسال
</el-button>
</div>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'SelectAgentModal',
props: {
show: {
type: Boolean,
default: false
},
draft: {
required: true,
type: Object
}
},
data() {
return {
termsOfUse: false,
fetchingAgents: true,
postingForm: false,
agents: [],
agent: ''
}
},
computed: {
showModal: {
get() {
return this.show
},
set(value) {
this.$emit('closeModal')
}
},
user() {
return this.$auth.user
},
userAddress() {
const user = this.user
return user.province_name + '، ' + user.city_name + '، ' + user.address + '،کد پستی: ' + user.postal_code
},
filteredAgents() {
return this.agents.filter(item => {
if (this.draft.db_name === 'verity')
return item.representation_type === 'verity' || item.representation_type === 'both'
else if (this.draft.db_name === 'panatech')
return item.representation_type === 'panatech' || item.representation_type === 'both'
else return false
})
}
},
watch: {
show(newVal, oldVal) {
if (newVal) {
this.$axios
.get('/api/public/agents')
.then(res => {
this.agents = res.data
this.fetchingAgents = false
})
.catch(() => {
this.$message({
type: 'error',
message: 'در دریافت لیست نمایندگان مشکلی پیش آمده'
})
this.showModal = false
})
}
}
},
mounted() {
if (this.user.isAgent) this.agent = 'main'
},
methods: {
agentName(item) {
return (
'نمایندگی ' +
item.city_name +
' کد ' +
item.agent_code +
' ' +
'(' +
item.province_name +
', ' +
item.city_name +
', ' +
item.address +
')'
)
},
sendForm() {
// validations
if (this.postingForm) return
if (!this.termsOfUse)
return this.$message({
type: 'warning',
message: 'با قوانین و مقررات موافقت نکرده اید.'
})
if (!this.agent)
return this.$message({
type: 'warning',
message: 'نماینده مورد نظر را انتخاب کنید'
})
// set postingForm true
this.postingForm = true
const businessID = () => {
if (this.draft.db_name === 'panatech') return this.user.panatech_businessID
else if (this.draft.db_name === 'verity') return this.user.verity_businessID
else return ''
}
const agent = () => {
if (this.user.isAgent) return 'main'
else return this.agent
}
const data = {
BusinessID: businessID(),
Description: this.draft.description,
cAddress1: this.userAddress,
TransCCustom1: this.user.first_name + ' ' + this.user.last_name,
cTel1: this.user.mobile_number,
items: this.draft.items,
termsOfUse: this.termsOfUse,
draftId: this.draft._id,
db_name: this.draft.db_name,
agent: agent()
}
this.$axios
.post('/api/user/transaction', data)
.then(res => {
this.$message({
type: 'success',
message: 'فرم شما با موفقیت ارسال شد'
})
this.postingForm = false
this.$router.push({
name: 'account-guarantee-receipt',
query: { ttn: res.data.transNumber, host: res.data.host, db_name: this.draft.db_name }
})
})
.catch(e => {
this.postingForm = false
if (e.response.status === 422) {
this.$message({
type: 'error',
message: 'اطلاعات را بررسی و دوباره تلاش کنید'
})
} else if (e.response.status === 406) {
this.$message({
type: 'error',
message: e.response.data.message
})
} else {
this.$arpaError()
console.log(e)
}
})
}
}
}
</script>
+237
View File
@@ -0,0 +1,237 @@
<template>
<div class="user-aside">
<ul>
<template v-if="userContactConfirmed && user.isAgent">
<div class="seprator">
<div class="txt">
<span>امکانات نمایندگی</span>
</div>
<div class="line"></div>
</div>
<nuxt-link
:to="{ name: 'account-agents-inbox', query: { type: 'ttl' } }"
tag="li"
:class="$route.name.includes('account-agents-inbox') && 'active'"
>
<a>
<b v-if="agentInbox" class="badge">{{ agentInbox }}</b>
<i v-else class="fal fa-inbox"></i>
<span>صندوق ورودی</span>
</a>
</nuxt-link>
<nuxt-link
:to="{ name: 'account-agents-pieces', query: { type: 'temp' } }"
tag="li"
:class="$route.name.includes('account-agents-pieces') && 'active'"
>
<a>
<i class="fas fa-wrench"></i>
<span>درخواست قطعه</span>
</a>
</nuxt-link>
<nuxt-link
:to="{ name: 'account-agents-ops', query: { type: 'temp' } }"
tag="li"
:class="$route.name.includes('account-agents-ops') && 'active'"
>
<a>
<i class="fas fa-backpack"></i>
<span>درخواست قطعه داغی</span>
</a>
</nuxt-link>
<nuxt-link
:to="{ name: 'account-agents-buffer', query: { type: 'temp' } }"
tag="li"
:class="$route.name.includes('account-agents-buffer') && 'active'"
>
<a>
<i class="fab fa-buffer"></i>
<span>درخواست کالای بافر</span>
</a>
</nuxt-link>
<nuxt-link
:to="{ name: 'account-agents-guaranteeReports', query: { type: 'temp' } }"
tag="li"
:class="$route.name.includes('account-agents-guaranteeReports') && 'active'"
>
<a>
<i class="fas fa-file-chart-line"></i>
<span>ارسال گزارش عملکرد</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-agents-reports' }" tag="li">
<a>
<i class="fas fa-file-chart-pie"></i>
<span>گزارشات</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-agents-announcements' }" tag="li">
<a class="relativePos">
<b v-if="newAgentAnnosCount" class="badge">{{ newAgentAnnosCount }}</b>
<i v-else class="fas fa-bullhorn"></i>
<span>اطلاعیه ها</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-agents-edit-info' }" tag="li">
<a>
<i class="fas fa-edit"></i>
<span>ویرایش اطلاعات نمایندگی</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-agents-file-upload' }" tag="li">
<a>
<i class="fas fa-edit"></i>
<span>ویرایش مدارک نمایندگی</span>
</a>
</nuxt-link>
<div class="seprator">
<div class="txt">
<span>امکانات کاربری</span>
</div>
<div class="line"></div>
</div>
</template>
<nuxt-link :to="{ name: 'account' }" tag="li" exact class="username">
<a>
<i class="fas fa-user"></i>
<span class="singleLineTxt" :title="fullName">{{ fullName }}</span>
</a>
</nuxt-link>
<template v-if="userContactConfirmed">
<nuxt-link :to="{ name: 'account-post' }" tag="li">
<a>
<i class="fas fa-shipping-fast"></i>
<span>ارسال کالا</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-drafts' }" tag="li">
<a>
<b v-if="draftsCount" class="badge">{{ draftsCount }}</b>
<i v-else class="fas fa-mail-bulk"></i>
<span>پیش نویس ها</span>
</a>
</nuxt-link>
<nuxt-link
:to="{ name: 'account-guarantee', query: { type: 'ttl' } }"
tag="li"
:class="$route.name.includes('account-guarantee') && 'active'"
>
<a>
<i class="fal fa-list"></i>
<span>لیست گارانتی</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-history' }" tag="li">
<a>
<i class="fal fa-book"></i>
<span>مانده معین مشتری</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-addTicket' }" tag="li" exact>
<a>
<i class="fal fa-plus"></i>
<span>افزودن تیکت</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-tickets' }" tag="li">
<a class="relativePos">
<b v-if="unreadTickets" class="badge">{{ unreadTickets }}</b>
<i v-else class="fal fa-envelope"></i>
<span>تیکت ها</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-announcements' }" tag="li">
<a class="relativePos">
<b v-if="newUserAnnosCount" class="badge">{{ newUserAnnosCount }}</b>
<i v-else class="fas fa-bell"></i>
<span>اعلانات</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-survey' }" tag="li">
<a>
<i class="fas fa-chart-bar"></i>
<span>نظر سنجی</span>
</a>
</nuxt-link>
<nuxt-link :to="{ name: 'account-profile' }" tag="li">
<a>
<i class="fal fa-user-edit"></i>
<span>ویرایش پروفایل</span>
</a>
</nuxt-link>
</template>
<nuxt-link v-if="!user.email_confirmed || !user.mobile_confirmed" :to="{ name: 'account-verify' }" tag="li">
<a>
<i class="fas fa-badge-check"></i>
<span>تایید اطلاعات</span>
</a>
</nuxt-link>
<li>
<a @click="logOut">
<i class="fal fa-sign-out-alt"></i>
<span>خروج</span>
</a>
</li>
</ul>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
unreadTickets: state => state.front.unreadTickets,
draftsCount: state => state.front.draftsCount,
agentInbox: state => state.front.agentInbox,
newUserAnnosCount: state => state.front.newUserAnnosCount,
newAgentAnnosCount: state => state.front.newAgentAnnosCount
}),
user() {
return this.$auth.user
},
fullName() {
return this.user.first_name + ' ' + this.user.last_name
},
userContactConfirmed() {
return this.user.email_confirmed
}
},
methods: {
logOut() {
this.$confirm('میخواهید از حساب کاربری خارج شوید؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(async () => {
try {
await this.$auth.logout()
location.reload()
} catch (e) {
console.log(e.response.data)
}
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
@@ -0,0 +1,34 @@
<template>
<div class="user-dashboard page" :class="pageClass">
<slot name="body" />
<div class="container">
<div class="row">
<div class="col-12">
<div class="panel">
<div class="panel-title">
<p class="singleLineTxt" :title="panelTitle">{{ panelTitle }}</p>
</div>
<slot />
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
pageClass: {
required: false,
type: String,
default: null
},
panelTitle: {
required: false,
type: String,
default: null
}
}
}
</script>
+12
View File
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./*"],
"@/*": ["./*"],
"~~/*": ["./*"],
"@@/*": ["./*"]
}
},
"exclude": ["node_modules", ".nuxt", "dist"]
}
+13
View File
@@ -0,0 +1,13 @@
<template>
<client-only>
<div class="c-app flex-row align-items-center">
<CContainer>
<nuxt />
</CContainer>
</div>
</client-only>
</template>
<style lang="scss" scoped>
@import '~/sass/admin/style.scss';
</style>
+98
View File
@@ -0,0 +1,98 @@
<template>
<client-only>
<div class="c-app">
<TheSidebar />
<CWrapper>
<TheHeader />
<div class="c-body">
<main class="c-main">
<CContainer fluid class="pt-5">
<transition name="fade" mode="out-in">
<nuxt :key="$route.path" />
</transition>
</CContainer>
</main>
</div>
<TheFooter />
</CWrapper>
</div>
</client-only>
</template>
<script>
import WS_Admin from '@/mixins/WS_Admin'
export default {
name: 'AdminLayout',
mixins: [WS_Admin],
middleware: ['auth-admin', 'permissions'],
data() {
return {
subHeaderContent: null
}
},
head() {
return {
htmlAttrs: {
lang: 'fa',
dir: 'rtl'
},
title: 'آسان سرویس | مدیریت سایت'
}
},
async mounted() {
/// /////////////////////////////////////////////////// get products list | provinces | cities
try {
// verity request info
const verityData = {
url: `/api/GetItem?UserGroupID=${this.$config.VerityUserGroupId}`,
db: 'verity'
}
// panatech request info
const panatechData = {
url: `/api/GetItem?UserGroupID=${this.$config.PanatechUserGroupId}`,
db: 'panatech'
}
const allData = await Promise.all([
// fetch verity products
this.$axios.post('/api/cross/getRouteManager', verityData),
// fetch panatech products
this.$axios.post('/api/cross/getRouteManager', panatechData),
// fetch iranProvinces
this.$axios.post('/api/cross/getRouteManager', { url: '/api/GetProvince', db: 'verity' }),
// fetch iranCities
this.$axios.post('/api/cross/getRouteManager', { url: '/api/GetCity', db: 'verity' })
])
const verityProducts = allData[0]
const panatechProducts = allData[1]
const iranProvinces = allData[2]
const iranCities = allData[3]
this.$store.commit('admin/set', ['verityProducts', verityProducts.data.data])
this.$store.commit('admin/set', ['panatechProducts', panatechProducts.data.data])
this.$store.commit('admin/set', ['iranProvinces', iranProvinces.data.data])
this.$store.commit('admin/set', ['iranCities', iranCities.data.data])
} catch (e) {
this.$arpaError()
}
}
}
</script>
<style lang="scss">
@import '~/sass/admin/style.scss';
</style>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
+11
View File
@@ -0,0 +1,11 @@
<template>
<div>
<nuxt />
</div>
</template>
<script>
export default {
name: 'BlankLayout'
}
</script>
+23
View File
@@ -0,0 +1,23 @@
<template>
<div>
<SiteHeader />
<nuxt class="default" />
<SiteFooter v-if="$route.name !== 'index'" />
<MobileMenu />
<LotteryPopUp />
<AppInstallDialog />
</div>
</template>
<script>
export default {
name: 'DefaultLayout',
head() {
return {
htmlAttrs: {
lang: 'fa'
}
}
}
}
</script>
+26
View File
@@ -0,0 +1,26 @@
<template>
<div v-if="error.statusCode === 404" class="error--page">
<h1>{{ error.statusCode }}</h1>
<p>{{ error.message }}</p>
<nuxt-link :to="{ name: 'index' }">Home</nuxt-link>
</div>
<div v-else class="error--page">
<h1>{{ error.statusCode }}</h1>
<p>{{ error.message }}</p>
<nuxt-link :to="{ name: 'index' }">Home</nuxt-link>
</div>
</template>
<script>
export default {
name: 'ErrorPage',
layout: 'blank',
props: {
error: {
required: true,
type: Object,
default: null
}
}
}
</script>
+20
View File
@@ -0,0 +1,20 @@
<template>
<div>
<SiteHeader />
<nuxt />
<MobileMenu />
</div>
</template>
<script>
export default {
name: 'UserAuthLayout',
head() {
return {
htmlAttrs: {
lang: 'fa'
}
}
}
}
</script>
+102
View File
@@ -0,0 +1,102 @@
<template>
<client-only>
<div class="user-dashboard-layout">
<site-header />
<div class="topBG">
<div class="user-name">
<nuxt-link :to="{ name: 'account' }" exact>
<i class="fas fa-user"></i>
<span class="singleLineTxt" :title="fullName">{{ fullName }}</span>
</nuxt-link>
</div>
</div>
<div class="container-fluid">
<div class="row">
<user-aside-menu class="col-12 col-lg-3 col-xxl-2" />
<nuxt class="col-12 col-lg-9 col-xxl-10" />
</div>
</div>
<!-- <site-footer /> -->
<mobile-menu />
<AppInstallDialog />
</div>
</client-only>
</template>
<script>
export default {
name: 'UserLayout',
middleware: 'auth-user',
head() {
return {
title: 'آسان سرویس | حساب کاربری',
htmlAttrs: {
lang: 'fa'
}
}
},
computed: {
user() {
return this.$auth.user
},
fullName() {
return this.user.first_name + ' ' + this.user.last_name
}
},
async mounted() {
if (this.user.confirmed) {
if (!this.user.email_confirmed) {
this.$notify({
type: 'warning',
title: 'توجه',
message:
'کاربر گرامی آدرس ایمیل خود را تایید نکرده اید، لطفا هرچه سریع تر نسبت به تایید آدرس ایمیل خود از "منوی تایید اطلاعات" اقدام نمایید.',
position: 'top-left',
offset: 60,
duration: 0
})
}
if (!this.user.mobile_confirmed) {
this.$notify({
type: 'warning',
title: 'توجه',
message:
'کاربر گرامی شماره تلفن همراه خود را تایید نکرده اید، لطفا هرچه سریع تر نسبت به تایید شماره تلفن همراه خود از منوی "تایید اطلاعات" اقدام نمایید.',
position: 'top-left',
offset: 60,
duration: 0
})
}
}
/// /// get products list
try {
// verity request info
const verityData = {
url: `/api/GetItem?UserGroupID=${this.$config.VerityUserGroupId}`,
db: 'verity'
}
// panatech request info
const panatechData = {
url: `/api/GetItem?UserGroupID=${this.$config.PanatechUserGroupId}`,
db: 'panatech'
}
const allData = await Promise.all([
// fetch verity products
this.$axios.post('/api/cross/getRouteManager', verityData),
// fetch panatech products
this.$axios.post('/api/cross/getRouteManager', panatechData)
])
const verityProducts = allData[0]
const panatechProducts = allData[1]
this.$store.commit('front/set', ['verityProducts', verityProducts.data.data])
this.$store.commit('front/set', ['panatechProducts', panatechProducts.data.data])
} catch (e) {
this.$arpaError()
}
}
}
</script>
+4
View File
@@ -0,0 +1,4 @@
export default function ({ $auth, redirect }) {
if ($auth.loggedIn && $auth.hasScope('admin')) return true
else return redirect('/auth/login-register')
}
+5
View File
@@ -0,0 +1,5 @@
export default function ({ $auth, redirect, route }) {
if (!$auth.loggedIn || !$auth.hasScope('user')) return redirect('/auth/login-register')
if (!$auth.user.email_confirmed && route.name !== 'account-verify') return redirect('/account/verify')
return true
}
+16
View File
@@ -0,0 +1,16 @@
export default async function ({ $auth, redirect, route }) {
try {
if (route.name === 'admin') {
return true
} else {
let hasPermission = false
for await (const permission of $auth.user.permissions) {
if ((await route.name.includes(permission)) && permission !== '') hasPermission = true
}
if (hasPermission) return true
else redirect('/admin')
}
} catch (e) {
redirect('/admin')
}
}
+172
View File
@@ -0,0 +1,172 @@
export default {
methods: {
getCssCustomProperties() {
if (process.client) {
const cssCustomProperties = {}
const sheets = document.styleSheets
let cssText = ''
for (let i = sheets.length - 1; i > -1; i--) {
const rules = sheets[i].cssRules
for (let j = rules.length - 1; j > -1; j--) {
if (rules[j].selectorText === '.ie-custom-properties') {
// eslint-disable-next-line prefer-destructuring
cssText = rules[j].cssText
break
}
}
if (cssText) {
break
}
}
// eslint-disable-next-line unicorn/prefer-string-slice
cssText = cssText.substring(cssText.lastIndexOf('{') + 1, cssText.lastIndexOf('}'))
cssText.split(';').forEach(property => {
if (property) {
const name = property.split(': ')[0]
const value = property.split(': ')[1]
if (name && value) {
cssCustomProperties[`--${name.trim()}`] = value.trim()
}
}
})
return cssCustomProperties
} else {
return null
}
},
deepObjectsMerge(target, source) {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (const key of Object.keys(source)) {
if (source[key] instanceof Object) {
Object.assign(source[key], this.deepObjectsMerge(target[key], source[key]))
}
}
// Join `target` and modified `source`
Object.assign(target || {}, source)
return target
},
getColor(rawProperty, element = process.client ? document.body : null) {
const property = `--${rawProperty}`
const style = this.getStyle(property, element)
return style || rawProperty
},
getStyle(property, element = process.client ? document.body : null) {
if (process.client) {
const minIEVersion = 10
const isIE1x = () => Boolean(document.documentMode) && document.documentMode >= minIEVersion
const isCustomProperty = property => property.match(/^--.*/i)
///
let style
if (isCustomProperty(property) && isIE1x()) {
const cssCustomProperties = this.getCssCustomProperties()
style = cssCustomProperties[property]
} else {
style = window.getComputedStyle(element, null).getPropertyValue(property).replace(/^\s/, '')
}
return style
} else {
return null
}
},
hexToRgb(color) {
if (typeof color === 'undefined') {
throw new TypeError('Hex color is not defined')
}
const hex = color.match(/^#(?:[0-9a-f]{3}){1,2}$/i)
if (!hex) {
throw new Error(`${color} is not a valid hex color`)
}
let r
let g
let b
if (color.length === 7) {
r = parseInt(color.slice(1, 3), 16)
g = parseInt(color.slice(3, 5), 16)
b = parseInt(color.slice(5, 7), 16)
} else {
r = parseInt(color.slice(1, 2), 16)
g = parseInt(color.slice(2, 3), 16)
b = parseInt(color.slice(3, 5), 16)
}
return `rgba(${r}, ${g}, ${b})`
},
hexToRgba(color, opacity = 100) {
if (typeof color === 'undefined') {
throw new TypeError('Hex color is not defined')
}
const hex = color.match(/^#(?:[0-9a-f]{3}){1,2}$/i)
if (!hex) {
throw new Error(`${color} is not a valid hex color`)
}
let r
let g
let b
if (color.length === 7) {
r = parseInt(color.slice(1, 3), 16)
g = parseInt(color.slice(3, 5), 16)
b = parseInt(color.slice(5, 7), 16)
} else {
r = parseInt(color.slice(1, 2), 16)
g = parseInt(color.slice(2, 3), 16)
b = parseInt(color.slice(3, 5), 16)
}
return `rgba(${r}, ${g}, ${b}, ${opacity / 100})`
},
makeUid() {
const key = Math.random().toString(36).substr(2)
return 'uid-' + key
},
omitByKeys(originalObject, keys) {
const newObj = {}
const objKeys = Object.keys(originalObject)
for (let i = 0; i < objKeys.length; i++) {
!keys.includes(objKeys[i]) && (newObj[objKeys[i]] = originalObject[objKeys[i]])
}
return newObj
},
pickByKeys(originalObject, keys) {
const newObj = {}
for (let i = 0; i < keys.length; i++) {
newObj[keys[i]] = originalObject[keys[i]]
}
return newObj
},
rgbToHex(color) {
if (typeof color === 'undefined') {
throw new TypeError('Hex color is not defined')
}
if (color === 'transparent') {
return '#00000000'
}
const rgb = color.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i)
if (!rgb) {
throw new Error(`${color} is not a valid rgb color`)
}
const r = `0${parseInt(rgb[1], 10).toString(16)}`
const g = `0${parseInt(rgb[2], 10).toString(16)}`
const b = `0${parseInt(rgb[3], 10).toString(16)}`
return `#${r.slice(-2)}${g.slice(-2)}${b.slice(-2)}`
}
}
}
+25
View File
@@ -0,0 +1,25 @@
export default {
mounted() {
$(document).ready(() => {
const elements = $('.fadeInAnim')
Object.keys(elements).forEach((item, index) => {
if (index < elements.length) {
this.$gsap.fromTo(
elements[item],
{ y: 20, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.5,
scrollTrigger: {
trigger: elements[item],
start: 'top 90%'
}
}
)
}
})
})
}
}
+154
View File
@@ -0,0 +1,154 @@
import { io } from 'socket.io/client-dist/socket.io'
export default {
data() {
return {
adminNotificationOffset: 60
}
},
computed: {
userIsLoggedIn() {
return this.$auth.loggedIn
},
adminWS: {
get() {
return this.$store.state.admin.adminWS
},
set(val) {
this.$store.commit('front/set', ['adminWS', val])
}
}
},
methods: {
initAdminWS() {
this.adminWS = true
/// /////////////////////////////////////////// connetct to ws server
const socket = io(`${this.$config.WebSocketURL}/admin`, {
reconnectionDelay: 20000,
reconnectionDelayMax: 20000,
auth: {
token: this.$auth.strategy.token.get()
}
})
/// /////////////////////////////////////////// connection error
socket.on('connect_error', () => {
this.$notify({
type: 'error',
title: 'خطا',
message: 'دریافت اعلانات ادمین با مشکل مواجه شد',
position: 'top-left',
offset: this.adminNotificationOffset
// duration: 0
})
})
/// /////////////////////////////////////////// events
socket.on('connect', () => {
// console.log('**************** You have access to admin notifications')
})
socket.on(`admin:allNotifs`, data => {
this.$store.commit('admin/set', ['unreadCuMsgs', data.unreadCuMsgs])
this.$store.commit('admin/set', ['unreadTickets', data.unreadTickets])
this.$store.commit('admin/set', ['newCustomers', data.newCustomers])
this.$store.commit('admin/set', ['newRepresentations', data.newRepresentations])
this.$store.commit('admin/set', ['newPieceRequests', data.newPieceRequests])
this.$store.commit('admin/set', ['newOldPieceRequests', data.newOldPieceRequests])
this.$store.commit('admin/set', ['newBufferRequests', data.newBufferRequests])
this.$store.commit('admin/set', ['newGuaranteeReports', data.newGuaranteeReports])
})
socket.on(`admin:notify`, data => {
if (data.type === 'updateUnreadCuMsgs') {
// update store
this.$store.commit('admin/set', ['unreadCuMsgs', data.unreadCuMsgs])
// update DOM
if (this.$route.name === 'admin-contact-us') {
this.$nuxt.refresh()
}
}
if (data.type === 'updateUnreadTickets') {
// update store
this.$store.commit('admin/set', ['unreadTickets', data.unreadTickets])
// update DOM
if (this.$route.name === 'admin-tickets') {
this.$nuxt.refresh()
}
}
if (data.type === 'newTicketMsg') {
if (this.$route.name === 'admin-tickets-ticket') {
this.$nuxt.refresh()
setTimeout(() => {
window.scrollTo(0, document.body.scrollHeight)
}, 500)
}
}
if (data.type === 'updateNewCustomers') {
this.$store.commit('admin/set', ['newCustomers', data.newCustomers])
}
if (data.type === 'updateNewRepresentations') {
// update store
this.$store.commit('admin/set', ['newRepresentations', data.newRepresentations])
// update DOM
if (this.$route.name === 'admin-representations') {
this.$nuxt.refresh()
}
}
if (data.type === 'updateNewPieceRequests') {
// update store
this.$store.commit('admin/set', ['newPieceRequests', data.newPieceRequests])
// update DOM
if (this.$route.name === 'admin-piece-requests') {
this.$nuxt.refresh()
}
}
if (data.type === 'updateNewOldPieceRequests') {
// update store
this.$store.commit('admin/set', ['newOldPieceRequests', data.newOldPieceRequests])
// update DOM
if (this.$route.name === 'admin-op-requests') {
this.$nuxt.refresh()
}
}
if (data.type === 'updateNewBufferRequests') {
// update store
this.$store.commit('admin/set', ['newBufferRequests', data.newBufferRequests])
// update DOM
if (this.$route.name === 'admin-buffer-requests') {
this.$nuxt.refresh()
}
}
if (data.type === 'updateNewGuaranteeReports') {
// update store
this.$store.commit('admin/set', ['newGuaranteeReports', data.newGuaranteeReports])
// update DOM
if (this.$route.name === 'admin-quarantee-reports') {
this.$nuxt.refresh()
}
}
})
}
},
mounted() {
if (this.userIsLoggedIn && !this.adminWS) {
this.initAdminWS()
}
}
}
+106
View File
@@ -0,0 +1,106 @@
import { io } from 'socket.io/client-dist/socket.io'
import Vue from 'vue'
export default {
data() {
return {
agentNotificationOffset: 60
}
},
computed: {
user() {
return this.$auth.user
},
userIsLoggedIn() {
return this.$auth.loggedIn
},
agentWS: {
get() {
return this.$store.state.front.agentWS
},
set(val) {
this.$store.commit('front/set', ['agentWS', val])
}
}
},
methods: {
initAgentWS() {
this.agentWS = true
/// /////////////////////////////////////////// connetct to ws server
const socket = io(`${this.$config.WebSocketURL}/agent`, {
reconnectionDelay: 20000,
reconnectionDelayMax: 20000,
auth: {
token: this.$auth.strategy.token.get()
}
})
Vue.prototype.$agentSocket = socket
/// /////////////////////////////////////////// connection error
// eslint-disable-next-line node/handle-callback-err
socket.on('connect_error', err => {})
/// /////////////////////////////////////////// events
socket.on('connect', () => {
// console.log('**************** You have access to agent notifications')
socket.emit('agent:fetchAnnouncements')
})
socket.on(`agent:allNotifs`, data => {
this.$store.commit('front/set', ['agentInbox', data.agentInbox])
})
socket.on(`agent:announcements`, data => {
this.$store.commit('front/set', ['newAgentAnnosCount', data.newAgentAnnosCount])
this.$store.commit('front/set', ['agentAnnouncements', data.agentAnnouncements])
})
socket.on(`agent:fetchNewAnnouncements`, data => {
socket.emit('agent:fetchAnnouncements')
})
socket.on(`agent:notify`, data => {
if (data.type === 'updateAgentInbox') {
// update store
this.$store.commit('front/set', ['agentInbox', data.agentInbox])
// update DOM
if (this.$route.name === 'account-agents-inbox') {
this.$nuxt.refresh()
}
}
if (data.type === 'newAgentInbox') {
// sent ui notif
this.$notify({
type: 'success',
title: 'توجه',
message: ' فرم گارانتی جدید در صندوق ورودی شما قرار گرفت',
position: 'top-left',
offset: this.agentNotificationOffset,
duration: 10 * 1000
})
}
})
socket.on(`agent:notifyAll`, data => {
if (data.type === 'fetchNewAnnouncements') {
socket.emit('agent:fetchAnnouncements')
this.$notify({
type: 'success',
title: 'توجه',
message: 'پیام جدید در اطلاعیه های نمایندگان دارید',
position: 'top-left',
offset: this.userNotificationOffset
})
}
})
}
},
mounted() {
if (this.userIsLoggedIn && this.user.isAgent && !this.agentWS) {
this.initAgentWS()
}
}
}
+128
View File
@@ -0,0 +1,128 @@
import { io } from 'socket.io/client-dist/socket.io'
import Vue from 'vue'
export default {
data() {
return {
userNotificationOffset: 60
}
},
computed: {
userIsLoggedIn() {
return this.$auth.loggedIn
},
userWS: {
get() {
return this.$store.state.front.userWS
},
set(val) {
this.$store.commit('front/set', ['userWS', val])
}
}
},
methods: {
initUserWS() {
this.userWS = true
/// /////////////////////////////////////////// connetct to ws server
const socket = io(`${this.$config.WebSocketURL}/user`, {
reconnectionDelay: 20000,
reconnectionDelayMax: 20000,
auth: {
token: this.$auth.strategy.token.get()
}
})
Vue.prototype.$userSocket = socket
/// /////////////////////////////////////////// connection error
// eslint-disable-next-line node/handle-callback-err
socket.on('connect_error', err => {
this.$notify({
type: 'error',
title: 'خطا',
message: 'دریافت اعلانات با مشکل مواجه شد',
position: 'top-left',
offset: this.userNotificationOffset
// duration: 0
})
})
/// /////////////////////////////////////////// events
socket.on('connect', () => {
// console.log('**************** You have access to notifications')
socket.emit('user:fetchAnnouncements')
})
socket.on(`user:allNotifs`, data => {
this.$store.commit('front/set', ['unreadTickets', data.unreadTickets])
this.$store.commit('front/set', ['draftsCount', data.draftsCount])
})
socket.on(`user:announcements`, data => {
this.$store.commit('front/set', ['newUserAnnosCount', data.newUserAnnosCount])
this.$store.commit('front/set', ['userAnnouncements', data.userAnnouncements])
})
socket.on(`user:fetchNewAnnouncements`, data => {
socket.emit('user:fetchAnnouncements')
})
socket.on(`user:notify`, data => {
if (data.type === 'updateUnreadTickets') {
// update store
this.$store.commit('front/set', ['unreadTickets', data.unreadTickets])
// update DOM
if (this.$route.name === 'account-tickets') {
this.$nuxt.refresh()
}
}
if (data.type === 'newTicketMsg') {
this.$notify({
type: 'success',
title: 'توجه',
message: 'پیام دارید',
position: 'top-left',
offset: this.userNotificationOffset
})
if (this.$route.name === 'account-tickets-ticket') {
this.$nuxt.refresh()
setTimeout(() => {
window.scrollTo(0, document.body.scrollHeight)
}, 500)
}
}
if (data.type === 'updateDraftsCount') {
// update store
this.$store.commit('front/set', ['draftsCount', data.draftsCount])
// update DOM
if (this.$route.name === 'account-drafts') {
this.$nuxt.refresh()
}
}
})
socket.on(`user:notifyAll`, data => {
if (data.type === 'fetchNewAnnouncements') {
socket.emit('user:fetchAnnouncements')
this.$notify({
type: 'success',
title: 'توجه',
message: 'پیام جدید در اعلانات دارید',
position: 'top-left',
offset: this.userNotificationOffset
})
}
})
}
},
mounted() {
if (this.userIsLoggedIn && this.$auth.hasScope('user') && !this.userWS) {
this.initUserWS()
}
}
}
+24
View File
@@ -0,0 +1,24 @@
export default {
data() {
return {
axiosConfig: {
onUploadProgress: progressEvent => {
if (progressEvent.total / 1024 > 100) {
const text = 'درحال آپلود '
const uploadLayout = this.$loading({
lock: true,
text,
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
document.querySelector('.el-loading-text').innerText =
text + Math.floor((progressEvent.loaded / progressEvent.total) * 100) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
uploadLayout.close()
}
}
}
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
export default {
mounted() {
setTimeout(() => {
this.$alert(
'کاربر گرامی سایت در حال حاضر نسخه آزمایشی میباشد و ممکن است در بعضی بخش ها ایراداتی داشته باشد که به زودی برطرف خواهند شد، با تشکر از صبوری شما.',
'توجه',
{
type: 'warning'
}
)
}, 2000)
}
}
+9
View File
@@ -0,0 +1,9 @@
const wss = require('../server/WebSocket/wss')
const { isProduction } = require('../server/_env')
export default function () {
this.nuxt.hook('listen', (server, { host, port }) => {
// attach WebSocket Server to Nuxt Server in production mode
if (isProduction) wss(server)
})
}
+188
View File
@@ -0,0 +1,188 @@
import webpack from 'webpack'
import {
DevServerPort,
WebSocketURL,
NuxtPort,
NuxtHost,
isProduction,
// arpa
VerityUserGroupId,
VerityBusinessCategoryId,
VerityStockAreaId,
PanatechUserGroupId,
PanatechBusinessCategoryId,
PanatechStockAreaId
} from './server/_env'
import { serverMiddleware } from './server/index'
const serverMiddlewareArray = []
if (isProduction) serverMiddlewareArray.push(serverMiddleware)
export default {
// Global page headers (https://go.nuxtjs.dev/config-head)
head: {
title: 'آسان سرویس',
htmlAttrs: {
lang: 'fa'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ name: 'theme-color', content: '#065495' },
{ name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' },
{
hid: 'description',
name: 'description',
content:
'آسان سرویس یکی از بزرگترین و فعالترین ارائه دهنده خدمات پس از فروش محصولات الکترونیکی به مدد شبکه گسترده و منسجم خدمات پس از فروش خود توانسته پاسخگوی مشتریان فهیم و گرانقدر باشد.'
}
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/assets/img/favicon.png' },
{ rel: 'stylesheet', type: 'text/css', href: '/assets/css/bootstrap-grid.css' },
{ rel: 'stylesheet', type: 'text/css', href: '/assets/css/reset-css.css' },
{ rel: 'stylesheet', type: 'text/css', href: '/assets/css/fontawesome/css/all.min.css' }
],
script: [{ src: '/CustomSW.js', deafer: true, body: true }]
},
loading: false,
pageTransition: 'page',
// Global CSS (https://go.nuxtjs.dev/config-css)
css: ['element-ui/lib/theme-chalk/index.css', '~/sass/main.scss'],
// Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
plugins: [
'@/plugins/element-ui',
'@/plugins/ckEditor.client',
'@/plugins/gsap.client',
'@/plugins/core-ui.client',
'@/plugins/datePicker.client',
'@/plugins/ATextSplitterVuePlugin.client',
'@/plugins/ArpaError.client',
'@/plugins/jDate'
],
// Auto import components (https://go.nuxtjs.dev/config-components)
components: true,
// Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
buildModules: ['@nuxtjs/pwa'],
// Modules (https://go.nuxtjs.dev/config-modules)
modules: [
// https://go.nuxtjs.dev/axios
'@nuxtjs/axios',
'@nuxtjs/auth-next',
'~/modules/WebSocketServer.js'
],
pwa: {
icon: {
fileName: 'bigIcon.png'
},
manifest: {
name: 'خدمات گارانتی آسان سرویس',
short_name: 'AsanService App',
description: false,
lang: 'fa',
useWebmanifestExtension: false,
start_url: '/account'
},
meta: {
nativeUI: true,
mobileAppIOS: true,
name: 'اسان سرویس',
theme_color: '#065495'
},
workbox: {
cleanupOutdatedCaches: true
}
},
// Axios module configuration (https://go.nuxtjs.dev/config-axios)
axios: {
baseURL: `http://127.0.0.1:${NuxtPort}`,
proxy: true
},
proxy: {
'/api': { target: `http://127.0.0.1:${isProduction ? NuxtPort : DevServerPort}` }
},
// Build Configuration (https://go.nuxtjs.dev/config-build)
build: {
transpile: [/^element-ui/],
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
],
splitChunks: {
layouts: true
}
},
watchers: {
chokidar: {
ignored: /(server)/
},
webpack: {
ignored: /(server)/
}
},
router: {
linkActiveClass: 'active'
},
server: {
host: NuxtHost,
port: NuxtPort
},
serverMiddleware: serverMiddlewareArray,
auth: {
strategies: {
local: {
token: {
property: 'token',
required: true,
type: ''
},
user: {
property: 'user',
autoFetch: true
},
endpoints: {
login: { url: '/api/auth/login', method: 'post' },
logout: { url: '/api/auth/logout', method: 'post' },
user: { url: '/api/auth/user', method: 'get' }
}
}
},
redirect: false
},
publicRuntimeConfig: {
WebSocketURL: WebSocketURL(),
// verity
VerityUserGroupId,
VerityBusinessCategoryId,
VerityStockAreaId,
// panatech
PanatechUserGroupId,
PanatechBusinessCategoryId,
PanatechStockAreaId,
// footer variables
copyrightName: 'Danak Corporation',
copyrightURL: 'https://danakcorp.com/fa',
whatsApp: '',
instagram: '',
aparat: '',
supportTel: '021-67341',
supportEmail: 'info@asan-service.com',
andoridAppURL: '',
// contact page variables
address: 'تهران، میدان ولیعصر، خیابان نجات اللهی، خیابان جعفر شهری (سپند)، پلاک ۳۶، طبقه ۵',
contactTel: '021-67341',
contactEmail: 'info@asan-service.com',
// post receipt info (for asan service only)
recieverName: 'شرکت آسان سرویس (تهران)',
recieverAddress: 'تهران، میدان ولیعصر، خیابان نجات اللهی، خیابان جعفر شهری (سپند)، پلاک ۳۶، طبقه ۵',
recieverPostalCode: '1598993733',
recieverPhone: '02167341'
},
privateRuntimeConfig: {}
}
+15684
View File
File diff suppressed because it is too large Load Diff
+60
View File
@@ -0,0 +1,60 @@
{
"name": "asan-service",
"version": "1.0.0",
"private": true,
"scripts": {
"nodemon": "nodemon --watch server --exec \"nuxt start\"",
"server": "nodemon --watch server --exec \"SET NODE_ENV=devServer&&node ./server/index.js\"",
"dev": "nuxt",
"start": "nuxt start",
"generate": "nuxt generate",
"build": "nuxt build",
"lint:js": "eslint --ext \".js,.vue\" .",
"lint:prettier": "prettier --check .",
"lint": "npm run lint:js && npm run lint:prettier",
"lintfix": "prettier --write --list-different . && npm run lint:js -- --fix"
},
"dependencies": {
"@coreui/coreui": "^3.2.2",
"@coreui/icons": "^2.0.0-beta.5",
"@coreui/utils": "^1.3.1",
"@coreui/vue": "^3.1.2",
"@coreui/vue-chartjs": "^1.0.5",
"@nuxtjs/auth": "^4.9.1",
"@nuxtjs/auth-next": "5.0.0-1610375166.4d8db9d",
"@nuxtjs/axios": "^5.12.2",
"bcryptjs": "^2.4.3",
"ckeditor4-vue": "^1.2.0",
"core-js": "^3.6.5",
"dateformat": "^4.4.1",
"element-ui": "^2.15.13",
"express": "^4.17.1",
"express-fileupload": "^1.2.0",
"express-validator": "^6.8.0",
"gsap": "^3.5.1",
"jimp": "^0.16.1",
"jquery": "^3.5.1",
"jsonwebtoken": "^8.5.1",
"moment-jalaali": "^0.9.2",
"mongoose": "^5.11.8",
"mongoose-paginate-v2": "^1.3.13",
"nodemailer": "^6.4.17",
"nuxt": "^2.14.6",
"read-excel-file": "^5.2.2",
"socket.io": "^4.4.1",
"vue-persian-datetime-picker": "^2.10.3"
},
"devDependencies": {
"@babel/eslint-parser": "^7.16.3",
"@nuxtjs/eslint-config": "^8.0.0",
"@nuxtjs/eslint-module": "^3.0.2",
"eslint": "^8.4.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-nuxt": "^3.1.0",
"eslint-plugin-vue": "^8.2.0",
"prettier": "^2.5.1",
"@nuxtjs/pwa": "^3.3.5",
"node-sass": "^5.0.0",
"sass-loader": "^10.1.0"
}
}
+80
View File
@@ -0,0 +1,80 @@
<template>
<div class="FAQ--page page">
<hero title="سوالات متداول">
<!-- <button class="btn btn-primary" @click.prevent="faqModal = true">سوال خود را بپرسید</button>-->
</hero>
<section class="s1">
<div class="container">
<div class="row">
<div v-for="(item, index) in faqs" :key="item._id" class="col-12 mb-3">
<div
:id="`q${item._id}`"
class="q-a fadeInAnim"
:class="index === 0 ? 'first' : null"
@click="toggle(item._id)"
>
<i class="fas fa-chevron-down"></i>
<h3>{{ item.question }}</h3>
<div class="answer">
<b>پاسخ</b>
<p>{{ item.answer }}</p>
</div>
</div>
</div>
<div v-if="!faqs.length" class="col-12 no-post">
<h2>هیچ پستی در این صفحه وجود نداد.</h2>
</div>
</div>
</div>
</section>
<!-- <el-dialog title="سوال خودرا بپرسید" :visible.sync="faqModal">-->
<!-- <el-input type="textarea" autocomplete="off"></el-input>-->
<!-- <span slot="footer" class="dialog-footer">-->
<!-- <el-button @click="faqModal = false">لغو</el-button>-->
<!-- <el-button class="submit" type="success" @click="faqModal = false">ثبت</el-button>-->
<!-- </span>-->
<!-- </el-dialog>-->
</div>
</template>
<script>
import FadeInAnimation from '~/mixins/FadeInAnimation'
export default {
name: 'FAQPage',
mixins: [FadeInAnimation],
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 {
faqs: null,
faqModal: false
}
},
head() {
return {
title: 'آسان سرویس | سوالات متداول'
}
},
mounted() {
$('.FAQ--page .q-a:not(.first)').addClass('collapsed')
$('.FAQ--page .q-a.collapsed .answer').slideUp()
},
methods: {
toggle(id) {
$(`#q${id}`).toggleClass('collapsed')
$(`#q${id} .answer`).slideToggle()
}
}
}
</script>
+86
View File
@@ -0,0 +1,86 @@
<template>
<div class="about--page page">
<section class="s1">
<h1>درباره ما</h1>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12 col-md-4 mb-5 mb-md-0 txt">
<h2>درباره آسان سرویس</h2>
</div>
<div class="col-12 col-md-8 txt">
<p>
امروزه یکی از ارکان اصلی شرکت های تولیدی صنعتی و برندهای تجاری ارائه خدمات پس از فروش است و رضایتمندی
مشتریان از نحوه رسیدگی به هنگام و آگاهی از روند انجام خدمات پس از فروش نقش بسزایی در روند توسعه برندهای
تجاری دارد . آسان سرویس به عنوان بازوی اجرایی خدمات پس از فروش شرکت تولیدی صنعتی پخش صبا درصدد است با به
کارگیری صحیح از منابع انسانی متخصص و نیز مدیریت واحدهای مختلف دپارتمان خدمات پس از فروش ، رضایت مشتریان
گرامی را از لحظه ورود محصول تا انجام خدمت به صورت مطلوب تامین نماید .
</p>
</div>
</div>
</div>
</section>
<section class="s3">
<div class="container">
<div class="row">
<div class="col-12 col-md-4 mb-5 mb-md-0 txt">
<h2>متخصصین آسان سرویس</h2>
</div>
<div class="col-12 col-md-8 txt">
<p>
آموزش نیروهای فنی زیر نظر کارشناسان تایوانی شرکت آسان سرویس پرسنل فنی خود را بطور سالانه در خصوص آموزش فنی
برای دستگاههای جدید به خارج از کشور اعزام نموده که اکثرا در آزمونهای انجام شده درجات بالایی را به ارمغان
آورده اند.
</p>
</div>
</div>
</div>
</section>
<section class="s4">
<div class="container">
<div class="row">
<div class="col-12 col-md-4 mb-5 mb-md-0 txt">
<h2>سفارش و تهیه قطعات یدکی اصلی</h2>
</div>
<div class="col-12 col-md-8 txt">
<p>
انبار قطعات یدکی این شرکت حجم بسیار بالایی از قطعات را در خود جا داده است که شامل 22000عنوان و بالغ بر صد
هزار تعداد قطعه موجود می باشد. با توجه به اینکه کارخانه سازنده حداکثر تا 5 سال بعد از تولید، قطعات یدکی را
تامین می کند،شرکت در پایان این دوره حجم بالایی از قطعات را سفارش می دهد تا مدت طولانی تری قادر به تامین
قطعات به مشتریان گرامی باشد.
</p>
</div>
</div>
</div>
</section>
<section class="s5">
<div class="container">
<div class="row">
<div class="col-12 col-md-4 mb-5 mb-md-0 txt">
<h2>گستردگی مراکز خدمات در سراسر کشور</h2>
</div>
<div class="col-12 col-md-8 txt">
<p>
آسان سرویس با دارا بودن بیش از 300 نماینده فروش در سراسر ایران و همچنین شبکه منسجم ارایه خدمات پس از فروش
با، امروز به یکی از موفقترین شرکتهای ایران در زمینه شبکه، IT و برق / الکترونیک بدل شده است که توانسته
رابطه تجاری بسیار خوبی با شرکتهای معتبر تایوانی و اروپایی مثل وریتی و پاناتک برقرار کند. شرکت آسان سرویس
در تمامی مراکز استان کشور نمایندگی آموزش دیده معتبر دارد که تعداد آنها به 95 مرکز خدمات پس از فروش می رسد
</p>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
export default {
name: 'AboutPage',
head() {
return {
title: 'آسان سرویس | درباره ما'
}
}
}
</script>
+140
View File
@@ -0,0 +1,140 @@
<template>
<user-dashboard-container page-class="post" panel-title="افزودن تیکت">
<form class="form form_3" @submit.prevent="post">
<div class="formRow" :class="validation.title ? 'err' : null">
<label for="title">:عنوان تیکت</label>
<input id="title" v-model="ticket.title" type="text" />
<p v-if="validation.title">{{ validation.title.msg }}</p>
</div>
<div class="formRow">
<label>کد پذیرش:</label>
<el-select v-model="ticket.transaction_id" filterable :placeholder="tnPlaceholder" :loading="fetching">
<el-option-group :key="0" label="پذیرش موقت ها">
<el-option
v-for="(item, index) in ttns"
:key="index + '_getAll_tempTransactions_for_new_ticket'"
:value="item"
></el-option>
</el-option-group>
<el-option-group :key="1" label="پذیرش دائم ها">
<el-option
v-for="(item, index) in atns"
:key="index + '_getAll_transactions_for_new_ticket'"
:value="item"
></el-option>
</el-option-group>
</el-select>
</div>
<div class="btnRow">
<button class="btn btn-primary" type="submit">
<span>افزودن</span>
<i class="far fa-plus-circle"></i>
</button>
</div>
</form>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAddTicket',
layout: 'user',
data() {
return {
verityTransactions: [],
panatechTransactions: [],
agentsTransactions: [],
fetching: false,
ticket: {
title: '',
transaction_id: '',
user_id: this.$auth.user._id
},
validation: {}
}
},
computed: {
transactions() {
return [...this.verityTransactions, ...this.panatechTransactions, ...this.agentsTransactions]
},
ttns() {
const array = []
this.transactions.forEach(item => {
if (!item.ItemReceptionTransNumber) array.push(item.TempReceiptTransNumber)
})
return array
},
atns() {
const array = []
this.transactions.forEach(item => {
if (item.ItemReceptionTransNumber) array.push(item.ItemReceptionTransNumber)
})
return array
},
tnPlaceholder() {
if (this.fetching) return 'در حال بارگیری...'
else return 'اختیاری'
}
},
async mounted() {
try {
this.fetching = true
const user = this.$auth.user
const verityData = {
url: `/api/GetItemReceptionInfo?BusinessCode=${user.verity_businessCode}`,
db: 'verity'
}
const panatechData = {
url: `/api/GetItemReceptionInfo?BusinessCode=${user.panatech_businessCode}`,
db: 'panatech'
}
const allData = await Promise.all([
// fetch verityTransactions
this.$axios.post('/api/cross/getRouteManager', verityData),
// fetch panatechTransactions
this.$axios.post('/api/cross/getRouteManager', panatechData),
// fetch agentstransactions
this.$axios.get('/api/user/transactions')
])
const verityTransactions = allData[0]
const panatechTransactions = allData[1]
const agentsTransactions = allData[2]
this.verityTransactions = verityTransactions.data.data
this.panatechTransactions = panatechTransactions.data.data
this.agentsTransactions = agentsTransactions.data
this.fetching = false
} catch (e) {
this.$arpaError()
}
},
methods: {
post() {
this.validation = {}
this.$axios
.post('/api/user/addTicketConversation', this.ticket)
.then(res => {
this.$message({
type: 'success',
message: 'تیکت با موفقیت ثبت شد، پیام خودرا بنویسید.'
})
this.$router.push({ name: 'account-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)
})
}
}
}
</script>
@@ -0,0 +1,39 @@
<template>
<user-dashboard-container page-class="announcements" panel-title="اطلاعیه های نمایندگان">
<div v-for="item in agentAnnouncements" :key="item._id" class="item" :class="!item.seen && 'unread'">
<el-collapse :key="item._id + 'co_parent'" accordion @change="seeAnnouncement">
<el-collapse-item :key="item._id + 'co_item'" :name="item._id">
<template slot="title">
<h3>{{ item.title }}</h3>
</template>
<div>
<p>{{ item.caption }}</p>
</div>
</el-collapse-item>
</el-collapse>
</div>
<h3 v-if="!agentAnnouncements.length" style="text-align: center; margin-top: 50px">هیچ اطلاعیه ای موجود نیست</h3>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentAnnouncements',
layout: 'user',
data() {
return {}
},
computed: {
agentAnnouncements() {
return this.$store.state.front.agentAnnouncements
}
},
methods: {
seeAnnouncement(id) {
if (!id) return
const item = this.agentAnnouncements.find(item => item._id === id)
if (!item.seen) this.$agentSocket.emit('agent:updateAnnouncement', id)
}
}
}
</script>
+297
View File
@@ -0,0 +1,297 @@
<template>
<user-dashboard-container page-class="post agent-requests-details" panel-title="فرم درخواست کالای بافر">
<el-alert v-if="bufferRequest.status === 'temp'" :title="alertMsg" class="mb-3" type="warning"> </el-alert>
<form class="form form_3">
<div class="userInfo">
<div class="formRow">
<label for="customer_name">نام و نام خانوادگی:</label>
<input id="customer_name" type="text" :value="bufferRequest.agent_id.full_name" disabled />
</div>
<div class="formRow">
<label for="customer_code">کد نمایندگی:</label>
<input id="customer_code" type="text" :value="bufferRequest.agent_id.agent_code" disabled />
</div>
<div class="formRow">
<label for="mobile">شماره موبایل:</label>
<input id="mobile" type="text" :value="bufferRequest.agent_id.mobile_number" disabled />
</div>
<div class="formRow">
<label for="fax">شماره فکس:</label>
<input id="fax" type="text" :value="bufferRequest.agent_id.fax_number" disabled />
</div>
<div class="formRow">
<label for="province">استان:</label>
<input id="province" type="text" :value="bufferRequest.agent_id.province_name" disabled />
</div>
<div class="formRow">
<label for="city">شهر:</label>
<input id="city" type="text" :value="bufferRequest.agent_id.city_name" disabled />
</div>
</div>
<div class="formRow">
<label>آدرس:</label>
<textarea name="description" cols="30" rows="5" disabled :value="bufferRequest.agent_id.address"></textarea>
</div>
<hr />
<div class="formRow">
<label v-if="bufferRequest.status === 'temp'" for="description">توضیحات فرم (اختیاری):</label>
<label v-else for="description">توضیحات فرم:</label>
<el-tooltip
v-model="descriptionTooltip"
class="item"
effect="dark"
content="میتوانید توضیحات را در هر زمان تغییر دهید"
placement="top-start"
:disabled="bufferRequest.status !== 'temp'"
>
<textarea
id="description"
v-model="bufferRequest.description"
name="description"
:disabled="bufferRequest.status !== 'temp'"
:placeholder="descriptionPlaceHolder"
cols="30"
rows="10"
@blur="updateDescription"
></textarea>
</el-tooltip>
</div>
</form>
<div class="add-list">
<h2>لیست کالاهای بافر درخواستی:</h2>
<div class="tableBox">
<table class="pieces-items">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="itemName">نام کالا</th>
<th class="quantity">تعداد</th>
<th v-if="bufferRequest.status === 'temp'" class="removeBtn">حذف</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in bufferRequest.items"
:key="item.ItemID + index + '_br_buffers'"
:title="item.ItemName"
>
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="itemName">
<span class="singleLineTxt">{{ item.ItemName }}</span>
</td>
<td class="quantity">
<span>{{ item.bufferQuantity }}</span>
</td>
<td v-if="bufferRequest.status === 'temp'" class="removeBtn">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removeItemFromList(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
</td>
</tr>
<tr v-if="!bufferRequest.items.length" class="odd">
<td class="noItem" colspan="5">
<p style="color: #000">هنوز هیچ آیتمی اضافه نکردید.</p>
</td>
</tr>
<tr v-if="bufferRequest.status === 'temp'" class="addStuffBtn" @click="bufferModal = true">
<td colspan="5">
<button>
<span>افزودن قطعه</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
<hr />
<div v-if="bufferRequest.status === 'temp'" class="btnRow">
<button class="btn btn-primary" @click="sendForm">ارسال به آسان سرویس</button>
<button class="btn btn-danger" @click="removeBR">حذف این فرم</button>
</div>
</div>
<template #body>
<AddBuffersToBufferRequest
:key="buffersModalKey"
:show="bufferModal"
:br-id="bufferRequest._id"
@closeModal="closeBuffersModal"
/>
</template>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentBufferDetails',
layout: 'user',
async asyncData({ $axios, params, error }) {
try {
const bufferRequest = await $axios.get(`/api/agent/br/${params.br}`)
return {
bufferRequest: bufferRequest.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
bufferRequest: null,
validation: {},
bufferModal: false,
buffersModalKey: 0,
descriptionTooltip: false,
alertMsg:
'این درخواست در پیشنویس ها ذخیره شده و هنوز در پایگاه داده شرکت آسان سرویس ثبت نگردیده. شما میتوانید قطعات را در هر زمان به این فرم اضافه یا از فرم حذف کنید سپس نسبت به ارسال نهایی اقدام کنید.'
}
},
computed: {
brId() {
return this.$route.params.br
},
descriptionPlaceHolder() {
if (this.bufferRequest.status === 'temp') return 'توضیحات راجع به کالای بافر را میتوانید اینجا بنویسید'
else return 'بدون توضیحات'
}
},
mounted() {
setTimeout(() => {
if (this.bufferRequest.status === 'temp') this.descriptionTooltip = true
}, 1000)
},
methods: {
closeBuffersModal() {
this.bufferModal = false
this.buffersModalKey = Math.random()
},
removeItemFromList(id) {
if (this.bufferRequest.status !== 'temp') return
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/removeBrItems/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در انجام عملیات پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
updateDescription() {
if (this.bufferRequest.status !== 'temp') return
const data = { description: this.bufferRequest.description }
this.$axios
.put(`/api/agent/brDescription/${this.brId}`, data)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در ثبت اطلاعات پیش آمده'
})
})
},
sendForm() {
this.$confirm('فرم درخواست کالای بافر به آسان سرویس ارسال شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.post(`/api/agent/sendBr/${this.brId}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-agents-buffer', query: { type: 'sent' } })
})
.catch(err => {
let msg = 'مشکلی در ارسال درخواست پیش آمده'
if (err.response.status === 406) msg = err.response.data.message
this.$message({
type: 'error',
message: msg
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
removeBR() {
this.$confirm('این فرم از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/br/${this.brId}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-agents-buffer', query: { type: 'temp' } })
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف پیشنویس پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+232
View File
@@ -0,0 +1,232 @@
<template>
<user-dashboard-container page-class="agent-requests" panel-title="لیست درخواست های کالای بافر">
<div class="filter mb-5">
<h4 style="display: inline-block; margin-left: 15px">مشاهده لیست:</h4>
<button class="switchBtns btn" :class="type === 'temp' && 'btn-primary'" @click="type = 'temp'">
پیشنویس ها
</button>
<button class="switchBtns btn" :class="type === 'sent' && 'btn-primary'" @click="type = 'sent'">
ارسال شده ها
</button>
<button class="switchBtns btn" :class="type === 'delivered' && 'btn-primary'" @click="type = 'delivered'">
انجام شده ها
</button>
<div v-if="type !== 'temp'" class="search mt-3" :class="serachBoxClass">
<el-input v-model="searchInput" clearable placeholder="جستجو در لیست با کد پیگیری" />
</div>
</div>
<div class="tableBox">
<table class="agent-requests" :class="type !== 'temp' && 'extended'">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="description">توضیحات</th>
<th class="createDate">تاریخ ایجاد</th>
<template v-if="type === 'sent' || type === 'delivered'">
<th class="sendDate">تاریخ ارسال</th>
<th class="trackingCode">کد پیگیری</th>
<th class="status">وضعیت</th>
</template>
<th v-if="type === 'delivered'" class="deliveryCode">کد ارسال مرسوله</th>
<th class="quantity">تعداد کالا</th>
<th class="details">جزئیات</th>
</tr>
</thead>
<tbody>
<template v-if="filteredList.length">
<tr v-for="(item, index) in filteredList" :key="item._id" :title="item.description">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="description">
<span v-if="item.description" class="singleLineTxt">{{ item.description }}</span>
<span v-else style="color: gray">بدون توضیحات</span>
</td>
<td class="createDate">
<span> {{ $jDate(item.createDate) }} </span>
</td>
<template v-if="type === 'sent' || type === 'delivered'">
<td class="sendDate">
<span>{{ $jDate(item.sendDate) }}</span>
</td>
<td class="trackingCode">
<span>{{ item.trackingCode }}</span>
</td>
<td class="status">
<span v-if="item.status === 'sent'">ارسال شده</span>
<span v-if="item.status === 'ongoing'">در دست اقدام</span>
<span v-if="item.status === 'waiting'">در انتظار قطعه</span>
<span v-if="item.status === 'delivered'">تحویل شده</span>
</td>
</template>
<td v-if="type === 'delivered'" class="deliveryCode">
<span>{{ item.deliveryCode || '-' }}</span>
</td>
<td class="quantity">
<span>{{ totalItemsCount(item.items) }}</span>
</td>
<td class="details">
<template v-if="item.status === 'temp'">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removePR(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
<nuxt-link
:to="{
name: 'account-agents-buffer-br',
params: {
br: item._id
}
}"
class="btn btn-primary"
>
تکمیل فرم
</nuxt-link>
</template>
<nuxt-link
v-else
:to="{
name: 'account-agents-buffer-br',
params: {
br: item._id
}
}"
class="btn btn-primary"
>
مشاهده
</nuxt-link>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
<tr v-if="type === 'temp'" class="addStuffBtn" @click="addBufferRequest">
<td colspan="5">
<button>
<span>افزودن درخواست</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentBufferList',
layout: 'user',
async asyncData({ $axios, $auth, error }) {
try {
const bufferRequests = await $axios.get('/api/agent/brList')
return {
bufferRequests: bufferRequests.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
bufferRequests: null,
searchInput: ''
}
},
computed: {
type: {
get() {
return this.$route.query.type
},
set(val) {
this.$router.push({ name: 'account-agents-buffer', query: { type: val } })
}
},
serachBoxClass() {
if (this.searchInput && this.filteredList.length) return 'success'
if (this.searchInput && !this.filteredList.length) return 'error'
return null
},
filteredList() {
let filteredBySearch
if (!this.searchInput || this.type === 'temp') filteredBySearch = this.bufferRequests
else {
filteredBySearch = this.bufferRequests.filter(item =>
item.trackingCode?.toLowerCase().includes(this.searchInput.toLowerCase())
)
}
return filteredBySearch.filter(item => {
if (this.type === 'temp') return item.status === 'temp'
if (this.type === 'sent') return item.status !== 'temp' && item.status !== 'delivered'
if (this.type === 'delivered') return item.status === 'delivered'
return false
})
}
},
methods: {
addBufferRequest() {
this.$axios
.post('/api/agent/br')
.then(res => {
this.$message({
type: 'success',
message: 'درخواست جدید افزوده شد'
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در افزودن درخواست پیش آمده'
})
})
},
totalItemsCount(items) {
let count = 0
items.forEach(item => (count += item.bufferQuantity))
return count
},
removePR(id) {
this.$confirm('این درخواست از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/br/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف درخواست پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+53
View File
@@ -0,0 +1,53 @@
<template>
<user-dashboard-container page-class="agent-requests" panel-title="ویرایش اطلاعات نمایندگی">
<div class="upload-assets">
<el-skeleton v-if="loading" class="mt-5" :rows="6" />
<template v-else>
<template v-if="lastRepresentation.editAccess">
<EnrollRepresentationForm :data="lastRepresentation"/>
</template>
<div v-else class="mt-5" style="text-align: center; color: red">
<h3>شما دسترسی ویرایش اطلاعات ندارید</h3>
</div>
</template>
</div>
</user-dashboard-container>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'AgentEditInfo',
layout: 'user',
data() {
return {
lastRepresentation: {},
loading: true
}
},
head() {
return {
title: 'آسان سرویس | ویرایش اطلاعات'
}
},
computed: {
...mapGetters({
agentAssetCategories: 'front/agentAssetCategories'
}),
user() {
return this.$auth.user
}
},
async mounted() {
try {
const lastRep = await this.$axios.$get(`/api/user/representation/${this.user.representation_id}`)
this.lastRepresentation = lastRep
} catch (err) {
console.log('err', err)
}
this.loading = false
}
}
</script>
@@ -0,0 +1,81 @@
<template>
<user-dashboard-container page-class="agent-requests" panel-title="ویرایش مدارک نمایندگی">
<div class="upload-assets">
<el-skeleton v-if="loading" class="mt-5" :rows="6" />
<template v-else>
<template v-if="lastRepresentation.upload">
<div class="upload-description mt-0">
<h3>نکاتی درباره بارگذاری مدارک:</h3>
<ul>
<li>
<span>در هر بخش تصاویر مدارک مربوطه را بارگذاری نمایید.</span>
</li>
<li>
<span>فیلدهای بارگذاری عکس در این صفحه هیچ کدام اجباری نیست.</span>
</li>
<li>
<span>فرمت مجاز تصاور jpeg میباشد.</span>
</li>
<li>
<span>نهایت حجم مجاز برای هر تصویر 2 مگابایت میباشد.</span>
</li>
</ul>
</div>
<div class="upload">
<section v-for="item in agentAssetCategories" :key="item.title">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
<RepresentationImageUploader
:name="item.fieldName"
:files-list="lastRepresentation[item.fieldName] || []"
:representation_code="lastRepresentation.representation_code"
/>
</section>
</div>
</template>
<div v-else class="mt-5" style="text-align: center; color: red">
<h3>شما دسترسی ویرایش مدارک ندارید</h3>
</div>
</template>
</div>
</user-dashboard-container>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'AgentAssetsEdit',
layout: 'user',
data() {
return {
lastRepresentation: {},
loading: true
}
},
head() {
return {
title: 'آسان سرویس | ویرایش مدارک'
}
},
computed: {
...mapGetters({
agentAssetCategories: 'front/agentAssetCategories'
}),
user() {
return this.$auth.user
}
},
async mounted() {
try {
const lastRep = await this.$axios.$get(`/api/user/representation/${this.user.representation_id}`)
this.lastRepresentation = lastRep
} catch (err) {
console.log('err', err)
}
this.loading = false
}
}
</script>
@@ -0,0 +1,341 @@
<template>
<user-dashboard-container page-class="post agent-requests-details" panel-title="فرم گزارش عملکرد گارانتی">
<el-alert v-if="guaranteeReport.status === 'temp'" :title="alertMsg" class="mb-3" type="warning"> </el-alert>
<form class="form form_3">
<div class="userInfo">
<div class="formRow">
<label for="customer_name">نام و نام خانوادگی:</label>
<input id="customer_name" type="text" :value="guaranteeReport.agent_id.full_name" disabled />
</div>
<div class="formRow">
<label for="customer_code">کد نمایندگی:</label>
<input id="customer_code" type="text" :value="guaranteeReport.agent_id.agent_code" disabled />
</div>
<div class="formRow">
<label for="mobile">شماره موبایل:</label>
<input id="mobile" type="text" :value="guaranteeReport.agent_id.mobile_number" disabled />
</div>
<div class="formRow">
<label for="fax">شماره فکس:</label>
<input id="fax" type="text" :value="guaranteeReport.agent_id.fax_number" disabled />
</div>
<div class="formRow">
<label for="province">استان:</label>
<input id="province" type="text" :value="guaranteeReport.agent_id.province_name" disabled />
</div>
<div class="formRow">
<label for="city">شهر:</label>
<input id="city" type="text" :value="guaranteeReport.agent_id.city_name" disabled />
</div>
</div>
<div class="formRow">
<label>آدرس:</label>
<textarea name="description" cols="30" rows="5" disabled :value="guaranteeReport.agent_id.address"></textarea>
</div>
<hr />
<div class="formRow">
<label v-if="guaranteeReport.status === 'temp'" for="description">توضیحات فرم (اختیاری):</label>
<label v-else for="description">توضیحات فرم:</label>
<el-tooltip
v-model="descriptionTooltip"
class="item"
effect="dark"
content="میتوانید توضیحات را در هر زمان تغییر دهید"
placement="top-start"
:disabled="guaranteeReport.status !== 'temp'"
>
<textarea
id="description"
v-model="guaranteeReport.description"
name="description"
:disabled="guaranteeReport.status !== 'temp'"
:placeholder="descriptionPlaceHolder"
cols="30"
rows="10"
@blur="updateDescription"
></textarea>
</el-tooltip>
</div>
</form>
<div class="notes">
<h3>توجه:</h3>
<ul>
<li>
<p>مدارک گارانتی فقط تا سه ماه بعد از تاریخ پذیرش دستگاه اعتبار دارد.</p>
</li>
<li>
<p>هر سه ماه یک بار مدارک گارانتی خود را جهت تسویه حساب به همراه داغی قطعات ارسال نمایید.</p>
</li>
</ul>
</div>
<div class="add-list">
<h2>لیست قطعات درخواستی:</h2>
<div class="tableBox">
<table class="report-items">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="customerName">نام مشتری</th>
<th class="customerTel">تلفن مشتری</th>
<th class="itemName">نام کالا</th>
<th class="itemSerial">سریال گارانتی</th>
<th class="productIssue">ایراد کالا</th>
<th class="usedPieces">قطعات مصرفی</th>
<th class="recieveDate">تاریخ دریافت</th>
<th class="deliverDate">تاریخ تحویل</th>
<th v-if="guaranteeReport.status === 'temp'" class="removeBtn">حذف</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in guaranteeReport.items"
:key="item.ItemID + index + '_gr_reports'"
:title="item.ItemName + ' - ' + item.pieceName"
>
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="customerName">
<span>{{ item.customerName }}</span>
</td>
<td class="customerTel">
<span>{{ item.customerTel }}</span>
</td>
<td class="itemName">
<span>{{ item.ItemName }}</span>
</td>
<td class="itemSerial">
<span>{{ item.SerialNo1 || '-' }}</span>
</td>
<td class="productIssue">
<span> {{ item.productIssue }} </span>
</td>
<td class="usedPieces">
<span> {{ item.usedPieces }} </span>
</td>
<td class="recieveDate">
<span> {{ $jDate(item.recieveDate) }} </span>
</td>
<td class="deliverDate">
<span> {{ $jDate(item.deliverDate) }} </span>
</td>
<td v-if="guaranteeReport.status === 'temp'" class="removeBtn">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removeItemFromList(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
</td>
</tr>
<tr v-if="!guaranteeReport.items.length" class="odd">
<td class="noItem" colspan="5">
<p style="color: #000">هنوز هیچ آیتمی اضافه نکردید.</p>
</td>
</tr>
<tr v-if="guaranteeReport.status === 'temp'" class="addStuffBtn" @click="reportModal = true">
<td colspan="5">
<button>
<span>افزودن گزارش</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
<hr />
<div v-if="guaranteeReport.status === 'temp'" class="btnRow">
<button class="btn btn-primary" @click="sendForm">ارسال به آسان سرویس</button>
<button class="btn btn-danger" @click="removeGR">حذف این فرم</button>
</div>
</div>
<template #body>
<AddReportToGuaranteeReportForm
:key="reportModalKey"
:show="reportModal"
:gr-id="guaranteeReport._id"
@closeModal="closeReportModal"
/>
</template>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentGrDetails',
layout: 'user',
async asyncData({ $axios, params, error }) {
try {
const guaranteeReport = await $axios.get(`/api/agent/gr/${params.gr}`)
return {
guaranteeReport: guaranteeReport.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
guaranteeReport: null,
validation: {},
reportModal: false,
reportModalKey: 0,
descriptionTooltip: false,
alertMsg:
'این فرم گزارش عملکرد در پیشنویس ها ذخیره شده و هنوز در پایگاه داده شرکت آسان سرویس ثبت نگردیده. شما میتوانید گزارش ها را در هر زمان به این فرم اضافه یا از فرم حذف کنید سپس نسبت به ارسال نهایی اقدام کنید.'
}
},
computed: {
grId() {
return this.$route.params.gr
},
descriptionPlaceHolder() {
if (this.guaranteeReport.status === 'temp') return 'توضیحات راجع به فرم گزارش را میتوانید اینجا بنویسید'
else return 'بدون توضیحات'
}
},
mounted() {
setTimeout(() => {
if (this.guaranteeReport.status === 'temp') this.descriptionTooltip = true
}, 1000)
},
methods: {
closeReportModal() {
this.reportModal = false
this.reportModalKey = Math.random()
},
removeItemFromList(id) {
if (this.guaranteeReport.status !== 'temp') return
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/removeGrItems/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در انجام عملیات پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
updateDescription() {
if (this.guaranteeReport.status !== 'temp') return
const data = { description: this.guaranteeReport.description }
this.$axios
.put(`/api/agent/grDescription/${this.grId}`, data)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در ثبت اطلاعات پیش آمده'
})
})
},
sendForm() {
this.$confirm('فرم گزارش عملکرد گارانتی به آسان سرویس ارسال شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.post(`/api/agent/sendGr/${this.grId}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-agents-guaranteeReports', query: { type: 'sent' } })
})
.catch(err => {
let msg = 'مشکلی در ارسال گزارش پیش آمده'
if (err.response.status === 406) msg = err.response.data.message
this.$message({
type: 'error',
message: msg
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
removeGR() {
this.$confirm('این فرم از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/gr/${this.grId}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-agents-guaranteeReports', query: { type: 'temp' } })
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف پیشنویس پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
@@ -0,0 +1,220 @@
<template>
<user-dashboard-container page-class="agent-requests" panel-title="لیست گزارش عملکرد گارانتی">
<div class="filter mb-5">
<h4 style="display: inline-block; margin-left: 15px">مشاهده لیست:</h4>
<button class="switchBtns btn" :class="type === 'temp' && 'btn-primary'" @click="type = 'temp'">
پیشنویس ها
</button>
<button class="switchBtns btn" :class="type === 'sent' && 'btn-primary'" @click="type = 'sent'">
ارسال شده ها
</button>
<div v-if="type === 'sent'" class="search mt-3" :class="serachBoxClass">
<el-input v-model="searchInput" clearable placeholder="جستجو در لیست با کد پیگیری" />
</div>
</div>
<div class="tableBox">
<table class="agent-requests" :class="type !== 'temp' && 'extended'">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="description">توضیحات</th>
<th class="createDate">تاریخ ایجاد</th>
<template v-if="type === 'sent' || type === 'delivered'">
<th class="sendDate">تاریخ ارسال</th>
<th class="trackingCode">کد پیگیری</th>
<th class="status">وضعیت</th>
</template>
<th class="quantity">تعداد گزارش</th>
<th class="details">جزئیات</th>
</tr>
</thead>
<tbody>
<template v-if="filteredList.length">
<tr v-for="(item, index) in filteredList" :key="item._id" :title="item.description">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="description">
<span v-if="item.description" class="singleLineTxt">{{ item.description }}</span>
<span v-else style="color: gray">بدون توضیحات</span>
</td>
<td class="createDate">
<span> {{ $jDate(item.createDate) }} </span>
</td>
<template v-if="type === 'sent' || type === 'delivered'">
<td class="sendDate">
<span>{{ $jDate(item.sendDate) }}</span>
</td>
<td class="trackingCode">
<span>{{ item.trackingCode }}</span>
</td>
<td class="status">
<span v-if="item.status === 'sent'">ارسال شده</span>
<!-- <span v-if="item.status === 'ongoing'">در دست اقدام</span>
<span v-if="item.status === 'waiting'">در انتظار قطعه</span>
<span v-if="item.status === 'delivered'">تحویل شده</span> -->
</td>
</template>
<td class="quantity">
<span>{{ totalItemsCount(item.items) }}</span>
</td>
<td class="details">
<template v-if="item.status === 'temp'">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removeGR(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
<nuxt-link
:to="{
name: 'account-agents-guaranteeReports-gr',
params: {
gr: item._id
}
}"
class="btn btn-primary"
>
تکمیل فرم
</nuxt-link>
</template>
<nuxt-link
v-else
:to="{
name: 'account-agents-guaranteeReports-gr',
params: {
gr: item._id
}
}"
class="btn btn-primary"
>
مشاهده
</nuxt-link>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
<tr v-if="type === 'temp'" class="addStuffBtn" @click="addGuaranteeReport">
<td colspan="5">
<button>
<span>افزودن فرم گزارش</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentGrList',
layout: 'user',
async asyncData({ $axios, $auth, error }) {
try {
const guaranteeReports = await $axios.get('/api/agent/grList')
return {
guaranteeReports: guaranteeReports.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
guaranteeReports: null,
searchInput: ''
}
},
computed: {
type: {
get() {
return this.$route.query.type
},
set(val) {
this.$router.push({ name: 'account-agents-guaranteeReports', query: { type: val } })
}
},
serachBoxClass() {
if (this.searchInput && this.filteredList.length) return 'success'
if (this.searchInput && !this.filteredList.length) return 'error'
return null
},
filteredList() {
let filteredBySearch
if (!this.searchInput || this.type === 'temp') filteredBySearch = this.guaranteeReports
else {
filteredBySearch = this.guaranteeReports.filter(item =>
item.trackingCode?.toLowerCase().includes(this.searchInput.toLowerCase())
)
}
return filteredBySearch.filter(item => {
if (this.type === 'temp') return item.status === 'temp'
if (this.type === 'sent') return item.status !== 'temp'
return false
})
}
},
methods: {
addGuaranteeReport() {
this.$axios
.post('/api/agent/gr')
.then(res => {
this.$message({
type: 'success',
message: 'فرم گزارش جدید افزوده شد'
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در افزودن گزارش پیش آمده'
})
})
},
totalItemsCount(items) {
return items.length
},
removeGR(id) {
this.$confirm('این گزارش از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/gr/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف گزارش پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+159
View File
@@ -0,0 +1,159 @@
<template>
<user-dashboard-container page-class="guarantee" panel-title="صندوق ورودی نماینده">
<div class="filter mb-5">
<h4 style="display: inline-block; margin-left: 15px">مشاهده لیست:</h4>
<button class="switchBtns btn" :class="type === 'ttl' && 'btn-primary'" @click="type = 'ttl'">دریافتی ها</button>
<button class="switchBtns btn" :class="type === 'atl' && 'btn-primary'" @click="type = 'atl'">
پذیرش شده ها
</button>
<div class="search mt-3" :class="serachBoxClass">
<el-input v-model="searchInput" clearable placeholder="جستجو در لیست با کد پذیرش موقت یا دائم" />
</div>
</div>
<div class="tableBox">
<table class="qaurantee">
<thead>
<tr>
<th>ردیف</th>
<th>شماره پذیرش موقت</th>
<th>تاریخ ارسال فرم</th>
<template v-if="type === 'atl'">
<th>شماره پذیرش دائم</th>
<th>تاریخ پذیرش</th>
<th>وضعیت</th>
</template>
<th class="brand">برند</th>
<th>جزئیات</th>
</tr>
</thead>
<tbody>
<template v-if="filteredList.length">
<tr v-for="(item, index) in filteredList" :key="item._id" :class="!item.seen && 'unread'">
<td>
<span>{{ index + 1 }}</span>
</td>
<td>
<span>{{ item.TempReceiptTransNumber }}</span>
</td>
<td>
<span>{{ $jDate(item.TempReceiptTransDate) }}</span>
</td>
<template v-if="type === 'atl'">
<td>
<span>{{ item.ItemReceptionTransNumber }}</span>
</td>
<td>
<span>{{ $jDate(item.ItemReceptionTransDate) }}</span>
</td>
<td>
<span v-if="item.status === 'recieved'">پذیرش شده</span>
<span v-if="item.status === 'ongoing'">در دست اقدام</span>
<span v-if="item.status === 'waiting'">در انتظار قطعه</span>
<span v-if="item.status === 'delivered'">تحویل شده</span>
</td>
</template>
<td class="brand">
<!-- <img
v-if="item.db_name === 'verity'"
src="/assets/img/verity-small.png"
alt="verity"
style="width: 80px;"
/>
<img
v-if="item.db_name === 'panatech'"
src="/assets/img/panatech-small.png"
alt="panatech"
style="width: 80px;"
/> -->
<i
v-if="item.db_name === 'verity'"
class="fas fa-phone-laptop"
title="لوازم جانبی کامپیوتر و موبایل"
></i>
<i v-if="item.db_name === 'panatech'" class="fas fa-photo-video" title="لوازم صوتی و تصویری خودرو"></i>
</td>
<td>
<nuxt-link
:to="{
name: 'account-agents-inbox-view',
query: {
tid: item._id,
ttn: item.TempReceiptTransNumber,
atn: item.ItemReceptionTransNumber || undefined,
db_name: item.db_name
}
}"
class="btn btn-primary"
>
مشاهده
</nuxt-link>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentInbox',
layout: 'user',
async asyncData({ $axios, error }) {
try {
const transactions = await $axios.get('/api/agent/inbox')
return {
transactions: transactions.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
transactions: null,
searchInput: ''
}
},
computed: {
type: {
get() {
return this.$route.query.type
},
set(val) {
this.$router.push({ name: 'account-agents-inbox', query: { type: val } })
}
},
serachBoxClass() {
if (this.searchInput && this.filteredList.length) return 'success'
if (this.searchInput && !this.filteredList.length) return 'error'
return null
},
filteredList() {
let filteredByTC
if (!this.searchInput) filteredByTC = this.transactions
else {
filteredByTC = this.transactions.filter(
item =>
item.TempReceiptTransNumber?.toLowerCase().includes(this.searchInput.toLowerCase()) ||
item.ItemReceptionTransNumber?.toLowerCase().includes(this.searchInput.toLowerCase())
)
}
const transactions = filteredByTC.filter(item => {
if (this.type === 'ttl') return !item.ItemReceptionTransNumber
else if (this.type === 'atl') return item.ItemReceptionTransNumber
return false
})
if (this.type === 'ttl') return transactions.reverse()
else return transactions
}
}
}
</script>
+340
View File
@@ -0,0 +1,340 @@
<template>
<user-dashboard-container page-class="guarantee-details agent-guarantee-details" panel-title="جزئیات">
<div class="agentActions">
<div class="row">
<div class="col-12 col-lg-6">
<div class="statuses">
<h3>تغییر وضعیت فرم:</h3>
<div class="btns">
<!--------------- recieved status btn --------------->
<button
class="btn btn-primary"
:disabled="transaction.status !== 'saved'"
@click="changeStatus('recieved')"
>
{{ getStatusName('recieved') }}
</button>
<!--------------- ongoing status btn --------------->
<button
class="btn btn-primary"
:disabled="transaction.status !== 'recieved'"
@click="changeStatus('ongoing')"
>
{{ getStatusName('ongoing') }}
</button>
<!--------------- waiting status btn --------------->
<button
class="btn btn-primary"
:disabled="
transaction.status === 'saved' ||
transaction.status === 'recieved' ||
transaction.status === 'delivered' ||
transaction.status === 'waiting'
"
@click="changeStatus('waiting')"
>
{{ getStatusName('waiting') }}
</button>
<!--------------- delivered status btn --------------->
<el-popover v-model="deliverPopover" placement="bottom" width="160" @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="changeStatus('delivered')"
>ارسال</el-button
>
</div>
<button
slot="reference"
class="btn btn-primary"
:disabled="
transaction.status === 'saved' ||
transaction.status === 'recieved' ||
transaction.status === 'delivered'
"
>
{{ getStatusName('delivered') }}
</button>
</el-popover>
</div>
</div>
</div>
<div class="col-12 col-lg-6 mt-4 mt-lg-0">
<div class="timeLine">
<h3>تاریخچه وضعیت های فرم:</h3>
<ul>
<li v-for="item in statusHistory" :key="item._id" :class="item.status">
<span> {{ getStatusName(item.status) }} </span>
<span> {{ $jDateTime(item.date) }} </span>
</li>
</ul>
</div>
</div>
</div>
</div>
<form action="" class="form form_3">
<div class="userInfo">
<div class="formRow">
<label>کد مشتری:</label>
<input type="text" disabled :value="transaction.BusinessID" />
</div>
<div class="formRow">
<label>نام و نام خانوادگی:</label>
<input type="text" disabled :value="transaction.TransCCustom1" />
</div>
<div class="formRow">
<label>شماره تماس:</label>
<input type="text" disabled :value="transaction.cTel1" />
</div>
<div class="formRow">
<label>شماره پذیرش موقت:</label>
<input type="text" disabled :value="transaction.TempReceiptTransNumber" />
</div>
<div class="formRow">
<label>شماره پذیرش دائم:</label>
<input type="text" disabled :value="transaction.ItemReceptionTransNumber || '-'" />
</div>
<div class="formRow">
<label>تاریخ ارسال فرم:</label>
<input type="text" disabled :value="$jDate(transaction.TempReceiptTransDate)" />
</div>
</div>
<div class="formRow">
<label>آدرس:</label>
<textarea name="" rows="3" disabled :value="transaction.cAddress1"></textarea>
</div>
<div class="formRow">
<label>توضیحات فرم:</label>
<textarea name="" rows="3" disabled :value="transaction.Description"></textarea>
</div>
</form>
<hr />
<div class="formDB">
<template v-if="transaction.db_name === 'verity'">
<i class="fas fa-phone-laptop"></i>
<span>لوازم جانبی کامپیوتر و موبایل</span>
</template>
<template v-if="transaction.db_name === 'panatech'">
<i class="fas fa-photo-video"></i>
<span>لوازم صوتی و تصویری خودرو</span>
</template>
</div>
<div class="tableBox">
<table class="formItems">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="itemName">نام کالا</th>
<th class="quantity">تعداد</th>
<th class="itemSerial">سریال گارانتی</th>
<th class="date">تاریخ اتمام گارانتی</th>
<th v-if="selectorAvailable" class="selector">
<el-checkbox :value="allItemsAreinDraftsItems" @change="addAllItemsToAgentsDraftItems" />
</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in transaction.items" :key="index + '_guaranteeItemsList'" :title="item.ItemName">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="itemName">
<span class="singleLineTxt">{{ getItemName(item.ItemID) || 'درحال بارگیری ...' }}</span>
</td>
<td class="quantity">
<span>{{ item.MjQty }}</span>
</td>
<td class="itemSerial">
<span>{{ item.SerialNo1 || '-' }}</span>
</td>
<td class="date">
<span>{{ item.GEndDate || '-' }}</span>
</td>
<td v-if="selectorAvailable" class="selector">
<el-checkbox
:value="isInAgentDraftsItem(item.ItemID, item.SerialNo1)"
@change="addSelectedItemsToAgentDraftItems(item.ItemID, item.SerialNo1)"
/>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
<div class="addToDraftsBtn">
<button v-if="agentDraftItems.length" class="btn btn-primary" @click="showDraftsModal = true">
<span>افزودن موارد انتخاب شده به پیشنویس ها</span>
<i class="fas fa-link"></i>
</button>
</div>
<template #body>
<AddUserItemsToAgentDraft
:key="addItemsToDraftModalKey"
:show="showDraftsModal"
:db_name="transaction.db_name"
:items="agentDraftItems"
@closeModal="closeAddItemToDraftModal"
/>
</template>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentInboxItemView',
layout: 'user',
async asyncData({ $axios, $auth, query, error }) {
try {
const tid = query?.tid
// fetch data from asan-service
const transaction = await $axios.get(`/api/agent/inbox/${tid}`)
return {
transaction: transaction.data
}
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
transaction: null,
factor: null,
paymentFactor: null,
deliverPopover: false,
deliveryCode: '',
showDraftsModal: false,
addItemsToDraftModalKey: 0,
agentDraftItems: []
}
},
computed: {
selectorAvailable() {
return this.transaction.status === 'ongoing' || this.transaction.status === 'waiting'
},
products() {
if (this.$route.query.db_name === 'verity') return this.$store.state.front.verityProducts
else if (this.$route.query.db_name === 'panatech') return this.$store.state.front.panatechProducts
else return []
},
host() {
return this.$route.query?.host
},
statusHistory() {
const statusHistory = this.transaction.statusHistory
return statusHistory.reverse()
},
allItemsAreinDraftsItems() {
return this.agentDraftItems.length === this.transaction.items.length
}
},
methods: {
closeAddItemToDraftModal() {
this.showDraftsModal = false
this.agentDraftItems = []
this.addItemsToDraftModalKey = Math.random()
},
addAllItemsToAgentsDraftItems(val) {
if (val) this.agentDraftItems = this.transaction.items
else this.agentDraftItems = []
},
addSelectedItemsToAgentDraftItems(id, serial) {
if (this.isInAgentDraftsItem(id, serial)) {
this.agentDraftItems = this.agentDraftItems.filter(item => {
if (serial) return item.SerialNo1 !== serial
else return item.ItemID !== id
})
} else {
const thisItem = this.transaction.items.find(item => {
if (serial) return item.SerialNo1 === serial
else return item.ItemID === id
})
this.agentDraftItems.push(thisItem)
}
},
isInAgentDraftsItem(id, serial) {
return Boolean(
this.agentDraftItems.find(item => {
if (serial) return item.SerialNo1 === serial
else return item.ItemID === id
})
)
},
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'
},
changeStatus(status) {
const deliveryCode = this.deliveryCode
const alertTitle = 'هشدار'
function alertMsg() {
if (status === 'recieved')
return 'نماینده گرامی تنها در صورتی که تمام کالاها به دست شما رسیده فرم را پذیرش کنید. در غیر اینصورت هرگونه مسئولیتی در قبال مفقودی کالاها بر عهده شما میباشد.'
else if (status === 'ongoing') return 'وضعیت فرم را به در دست اقدام تغییر میدهید'
else if (status === 'waiting') return 'وضعیت فرم را به در انتظار قطعه تغییر میدهید'
else if (status === 'delivered' && deliveryCode.length)
return (
`تغییر وضعیت فرم به ارسال شده با کد ارسال مرسوله "${deliveryCode}".` +
' در آینده قادر به تغییر این وضعیت یا تغییر کد مرسوله نخواهید بود، ادمه میدهید؟ '
)
else if (status === 'delivered')
return (
'تغییر وضعیت فرم به ارسال شدوه بدون کد ارسال مرسوله.' +
' در آینده قادر به تغییر این وضعیت یا افزودن کد مرسوله نخواهید بود، ادامه میدهید؟ '
)
}
this.$confirm(alertMsg(), alertTitle, {
confirmButtonText: 'ادامه',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.put(`/api/agent/changeTStatus/${this.transaction._id}`, { status, deliveryCode })
.then(res => {
this.$message({
type: 'success',
message: 'وضعیت فرم با موفقیت تغییر کرد و پیامک اطلاع رسانی برای کاربر ارسال شد'
})
this.deliveryCode = ''
this.$nuxt.refresh()
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+312
View File
@@ -0,0 +1,312 @@
<template>
<user-dashboard-container page-class="post agent-requests-details" panel-title="فرم درخواست قطعه داغی">
<el-alert v-if="oldPieceRequest.status === 'temp'" :title="alertMsg" class="mb-3" type="warning"> </el-alert>
<form class="form form_3">
<div class="userInfo">
<div class="formRow">
<label for="customer_name">نام و نام خانوادگی:</label>
<input id="customer_name" type="text" :value="oldPieceRequest.agent_id.full_name" disabled />
</div>
<div class="formRow">
<label for="customer_code">کد نمایندگی:</label>
<input id="customer_code" type="text" :value="oldPieceRequest.agent_id.agent_code" disabled />
</div>
<div class="formRow">
<label for="mobile">شماره موبایل:</label>
<input id="mobile" type="text" :value="oldPieceRequest.agent_id.mobile_number" disabled />
</div>
<div class="formRow">
<label for="fax">شماره فکس:</label>
<input id="fax" type="text" :value="oldPieceRequest.agent_id.fax_number" disabled />
</div>
<div class="formRow">
<label for="province">استان:</label>
<input id="province" type="text" :value="oldPieceRequest.agent_id.province_name" disabled />
</div>
<div class="formRow">
<label for="city">شهر:</label>
<input id="city" type="text" :value="oldPieceRequest.agent_id.city_name" disabled />
</div>
</div>
<div class="formRow">
<label>آدرس:</label>
<textarea name="description" cols="30" rows="5" disabled :value="oldPieceRequest.agent_id.address"></textarea>
</div>
<hr />
<div class="formRow">
<label v-if="oldPieceRequest.status === 'temp'" for="description">توضیحات فرم (اختیاری):</label>
<label v-else for="description">توضیحات فرم:</label>
<el-tooltip
v-model="descriptionTooltip"
class="item"
effect="dark"
content="میتوانید توضیحات را در هر زمان تغییر دهید"
placement="top-start"
:disabled="oldPieceRequest.status !== 'temp'"
>
<textarea
id="description"
v-model="oldPieceRequest.description"
name="description"
:disabled="oldPieceRequest.status !== 'temp'"
:placeholder="descriptionPlaceHolder"
cols="30"
rows="10"
@blur="updateDescription"
></textarea>
</el-tooltip>
</div>
</form>
<div class="add-list">
<h2>لیست قطعات درخواستی:</h2>
<div class="tableBox">
<table class="pieces-items">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="recieptDate">تاریخ پذیرش</th>
<th class="itemName">نام کالا</th>
<th class="itemSerial">سریال گارانتی</th>
<th class="pieceName">نام قطعه</th>
<th class="pieceCode">کد قطعه</th>
<th v-if="oldPieceRequest.status === 'temp'" class="removeBtn">حذف</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in oldPieceRequest.items"
:key="item.ItemID + index + '_opr_oldPieces'"
:title="item.ItemName + ' - ' + item.pieceName"
>
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="recieptDate">
<span> {{ $jDate(item.ItemReceptionTransDate) }} </span>
</td>
<td class="itemName">
<span class="singleLineTxt">{{ item.ItemName }}</span>
</td>
<td class="itemSerial">
<span>{{ item.SerialNo1 || '-' }}</span>
</td>
<td class="pieceName">
<span> {{ item.pieceName }} </span>
</td>
<td class="pieceCode">
<span> {{ item.pieceCode }} </span>
</td>
<td v-if="oldPieceRequest.status === 'temp'" class="removeBtn">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removeItemFromList(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
</td>
</tr>
<tr v-if="!oldPieceRequest.items.length" class="odd">
<td class="noItem" colspan="5">
<p style="color: #000">هنوز هیچ آیتمی اضافه نکردید.</p>
</td>
</tr>
<tr v-if="oldPieceRequest.status === 'temp'" class="addStuffBtn" @click="oldPiecesModal = true">
<td colspan="5">
<button>
<span>افزودن قطعه</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
<hr />
<div v-if="oldPieceRequest.status === 'temp'" class="btnRow">
<button class="btn btn-primary" @click="sendForm">ارسال به آسان سرویس</button>
<button class="btn btn-danger" @click="removeOPR">حذف این فرم</button>
</div>
</div>
<template #body>
<AddOldPiecesToOldPieceRequest
:key="oldPiecesModalKey"
:show="oldPiecesModal"
:opr-id="oldPieceRequest._id"
@closeModal="closePiecesModal"
/>
</template>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentOpsDetails',
layout: 'user',
async asyncData({ $axios, params, error }) {
try {
const oldPieceRequest = await $axios.get(`/api/agent/opr/${params.op}`)
return {
oldPieceRequest: oldPieceRequest.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
oldPieceRequest: null,
validation: {},
oldPiecesModal: false,
oldPiecesModalKey: 0,
descriptionTooltip: false,
alertMsg:
'این درخواست در پیشنویس ها ذخیره شده و هنوز در پایگاه داده شرکت آسان سرویس ثبت نگردیده. شما میتوانید قطعات را در هر زمان به این فرم اضافه یا از فرم حذف کنید سپس نسبت به ارسال نهایی اقدام کنید.'
}
},
computed: {
oprId() {
return this.$route.params.op
},
descriptionPlaceHolder() {
if (this.oldPieceRequest.status === 'temp') return 'توضیحات راجع به قطعات داغی را میتوانید اینجا بنویسید'
else return 'بدون توضیحات'
}
},
mounted() {
setTimeout(() => {
if (this.oldPieceRequest.status === 'temp') this.descriptionTooltip = true
}, 1000)
},
methods: {
closePiecesModal() {
this.oldPiecesModal = false
this.oldPiecesModalKey = Math.random()
},
removeItemFromList(id) {
if (this.oldPieceRequest.status !== 'temp') return
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/removeOprItems/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در انجام عملیات پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
updateDescription() {
if (this.oldPieceRequest.status !== 'temp') return
const data = { description: this.oldPieceRequest.description }
this.$axios
.put(`/api/agent/oprDescription/${this.oprId}`, data)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در ثبت اطلاعات پیش آمده'
})
})
},
sendForm() {
this.$confirm('فرم درخواست قطعه داغی به آسان سرویس ارسال شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.post(`/api/agent/sendOpr/${this.oprId}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-agents-ops', query: { type: 'sent' } })
})
.catch(err => {
let msg = 'مشکلی در ارسال درخواست پیش آمده'
if (err.response.status === 406) msg = err.response.data.message
this.$message({
type: 'error',
message: msg
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
removeOPR() {
this.$confirm('این فرم از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/opr/${this.oprId}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-agents-ops', query: { type: 'temp' } })
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف پیشنویس پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+230
View File
@@ -0,0 +1,230 @@
<template>
<user-dashboard-container page-class="agent-requests" panel-title="لیست درخواست های قطعه داغی">
<div class="filter mb-5">
<h4 style="display: inline-block; margin-left: 15px">مشاهده لیست:</h4>
<button class="switchBtns btn" :class="type === 'temp' && 'btn-primary'" @click="type = 'temp'">
پیشنویس ها
</button>
<button class="switchBtns btn" :class="type === 'sent' && 'btn-primary'" @click="type = 'sent'">
ارسال شده ها
</button>
<button class="switchBtns btn" :class="type === 'delivered' && 'btn-primary'" @click="type = 'delivered'">
انجام شده ها
</button>
<div v-if="type !== 'temp'" class="search mt-3" :class="serachBoxClass">
<el-input v-model="searchInput" clearable placeholder="جستجو در لیست با کد پیگیری" />
</div>
</div>
<div class="tableBox">
<table class="agent-requests" :class="type !== 'temp' && 'extended'">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="description">توضیحات</th>
<th class="createDate">تاریخ ایجاد</th>
<template v-if="type === 'sent' || type === 'delivered'">
<th class="sendDate">تاریخ ارسال</th>
<th class="trackingCode">کد پیگیری</th>
<th class="status">وضعیت</th>
</template>
<th v-if="type === 'delivered'" class="deliveryCode">کد ارسال مرسوله</th>
<th class="quantity">تعداد قطعه</th>
<th class="details">جزئیات</th>
</tr>
</thead>
<tbody>
<template v-if="filteredList.length">
<tr v-for="(item, index) in filteredList" :key="item._id" :title="item.description">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="description">
<span v-if="item.description" class="singleLineTxt">{{ item.description }}</span>
<span v-else style="color: gray">بدون توضیحات</span>
</td>
<td class="createDate">
<span> {{ $jDate(item.createDate) }} </span>
</td>
<template v-if="type === 'sent' || type === 'delivered'">
<td class="sendDate">
<span>{{ $jDate(item.sendDate) }}</span>
</td>
<td class="trackingCode">
<span>{{ item.trackingCode }}</span>
</td>
<td class="status">
<span v-if="item.status === 'sent'">ارسال شده</span>
<span v-if="item.status === 'ongoing'">در دست اقدام</span>
<span v-if="item.status === 'waiting'">در انتظار قطعه</span>
<span v-if="item.status === 'delivered'">تحویل شده</span>
</td>
</template>
<td v-if="type === 'delivered'" class="deliveryCode">
<span>{{ item.deliveryCode || '-' }}</span>
</td>
<td class="quantity">
<span>{{ totalItemsCount(item.items) }}</span>
</td>
<td class="details">
<template v-if="item.status === 'temp'">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removeOPR(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
<nuxt-link
:to="{
name: 'account-agents-ops-op',
params: {
op: item._id
}
}"
class="btn btn-primary"
>
تکمیل فرم
</nuxt-link>
</template>
<nuxt-link
v-else
:to="{
name: 'account-agents-ops-op',
params: {
op: item._id
}
}"
class="btn btn-primary"
>
مشاهده
</nuxt-link>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
<tr v-if="type === 'temp'" class="addStuffBtn" @click="addOldPieceRequest">
<td colspan="5">
<button>
<span>افزودن درخواست</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentOpsList',
layout: 'user',
async asyncData({ $axios, error }) {
try {
const oldPieceRequests = await $axios.get('/api/agent/oprList')
return {
oldPieceRequests: oldPieceRequests.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
oldPieceRequests: null,
searchInput: ''
}
},
computed: {
type: {
get() {
return this.$route.query.type
},
set(val) {
this.$router.push({ name: 'account-agents-ops', query: { type: val } })
}
},
serachBoxClass() {
if (this.searchInput && this.filteredList.length) return 'success'
if (this.searchInput && !this.filteredList.length) return 'error'
return null
},
filteredList() {
let filteredBySearch
if (!this.searchInput || this.type === 'temp') filteredBySearch = this.oldPieceRequests
else {
filteredBySearch = this.oldPieceRequests.filter(item =>
item.trackingCode?.toLowerCase().includes(this.searchInput.toLowerCase())
)
}
return filteredBySearch.filter(item => {
if (this.type === 'temp') return item.status === 'temp'
if (this.type === 'sent') return item.status !== 'temp' && item.status !== 'delivered'
if (this.type === 'delivered') return item.status === 'delivered'
return false
})
}
},
methods: {
addOldPieceRequest() {
this.$axios
.post('/api/agent/opr')
.then(res => {
this.$message({
type: 'success',
message: 'درخواست جدید افزوده شد'
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در افزودن درخواست پیش آمده'
})
})
},
totalItemsCount(items) {
return items.length
},
removeOPR(id) {
this.$confirm('این درخواست از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/opr/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف درخواست پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+340
View File
@@ -0,0 +1,340 @@
<template>
<user-dashboard-container page-class="post agent-requests-details" panel-title="فرم درخواست قطعه">
<el-alert v-if="pieceRequest.status === 'temp'" :title="alertMsg" class="mb-3" type="warning"> </el-alert>
<form class="form form_3">
<div class="userInfo">
<div class="formRow">
<label for="customer_name">نام و نام خانوادگی:</label>
<input id="customer_name" type="text" :value="pieceRequest.agent_id.full_name" disabled />
</div>
<div class="formRow">
<label for="customer_code">کد نمایندگی:</label>
<input id="customer_code" type="text" :value="pieceRequest.agent_id.agent_code" disabled />
</div>
<div class="formRow">
<label for="mobile">شماره موبایل:</label>
<input id="mobile" type="text" :value="pieceRequest.agent_id.mobile_number" disabled />
</div>
<div class="formRow">
<label for="fax">شماره فکس:</label>
<input id="fax" type="text" :value="pieceRequest.agent_id.fax_number" disabled />
</div>
<div class="formRow">
<label for="province">استان:</label>
<input id="province" type="text" :value="pieceRequest.agent_id.province_name" disabled />
</div>
<div class="formRow">
<label for="city">شهر:</label>
<input id="city" type="text" :value="pieceRequest.agent_id.city_name" disabled />
</div>
</div>
<div class="formRow">
<label>آدرس:</label>
<textarea name="description" cols="30" rows="5" disabled :value="pieceRequest.agent_id.address"></textarea>
</div>
<hr />
<div class="formRow">
<label v-if="pieceRequest.status === 'temp'" for="description">توضیحات فرم (اختیاری):</label>
<label v-else for="description">توضیحات فرم:</label>
<el-tooltip
v-model="descriptionTooltip"
class="item"
effect="dark"
content="میتوانید توضیحات را در هر زمان تغییر دهید"
placement="top-start"
:disabled="pieceRequest.status !== 'temp'"
>
<textarea
id="description"
v-model="pieceRequest.description"
name="description"
:disabled="pieceRequest.status !== 'temp'"
:placeholder="descriptionPlaceHolder"
cols="30"
rows="10"
@blur="updateDescription"
></textarea>
</el-tooltip>
</div>
</form>
<div class="notes">
<h3>توجه:</h3>
<ul>
<li>
<p>
قطعات غیرگارانتی درخواستی، در صورت موجود بودن، پس از اعلام و دریافت هزینه مربوطه برای نمایندگان محترم ارسال
خواهد شد.
</p>
</li>
<li>
<p>
تمامی قطعات موردنیاز گارانتی برای نمایندگان محترم فاکتور خواهد شد و پس از ارسال داغی قطعات بهمراه کپی کارت
گارانتی مربوطه، از حساب ایشان کسر می گردد.
</p>
</li>
</ul>
</div>
<div class="add-list">
<h2>لیست قطعات درخواستی:</h2>
<div class="tableBox">
<table class="pieces-items">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="recieptDate">تاریخ پذیرش</th>
<th class="itemName">نام کالا</th>
<th class="itemSerial">سریال گارانتی</th>
<th class="guaranteeStatus">وضعیت گارانتی</th>
<th class="pieceName">نام قطعه</th>
<th class="pieceCode">کد قطعه</th>
<th class="quantity">تعداد</th>
<th v-if="pieceRequest.status === 'temp'" class="removeBtn">حذف</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in pieceRequest.items"
:key="item.ItemID + index + '_pr_pieces'"
:title="item.ItemName + ' - ' + item.pieceName"
>
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="recieptDate">
<span> {{ $jDate(item.ItemReceptionTransDate) }} </span>
</td>
<td class="itemName">
<span class="singleLineTxt">{{ item.ItemName }}</span>
</td>
<td class="itemSerial">
<span>{{ item.SerialNo1 || '-' }}</span>
</td>
<td class="guaranteeStatus">
<span v-if="item.gStatus">دارد</span>
<span v-else>ندارد</span>
</td>
<td class="pieceName">
<span> {{ item.pieceName }} </span>
</td>
<td class="pieceCode">
<span> {{ item.pieceCode }} </span>
</td>
<td class="quantity">
<span>{{ item.pieceQuantity }}</span>
</td>
<td v-if="pieceRequest.status === 'temp'" class="removeBtn">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removeItemFromList(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
</td>
</tr>
<tr v-if="!pieceRequest.items.length" class="odd">
<td class="noItem" colspan="5">
<p style="color: #000">هنوز هیچ آیتمی اضافه نکردید.</p>
</td>
</tr>
<tr v-if="pieceRequest.status === 'temp'" class="addStuffBtn" @click="piecesModal = true">
<td colspan="5">
<button>
<span>افزودن قطعه</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
<hr />
<div v-if="pieceRequest.status === 'temp'" class="btnRow">
<button class="btn btn-primary" @click="sendForm">ارسال به آسان سرویس</button>
<button class="btn btn-danger" @click="removePR">حذف این فرم</button>
</div>
</div>
<template #body>
<AddPiecesToPieceRequest
:key="piecesModalKey"
:show="piecesModal"
:pr-id="pieceRequest._id"
@closeModal="closePiecesModal"
/>
</template>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentPrDetails',
layout: 'user',
async asyncData({ $axios, params, error }) {
try {
const pieceRequest = await $axios.get(`/api/agent/pr/${params.pr}`)
return {
pieceRequest: pieceRequest.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
pieceRequest: null,
validation: {},
piecesModal: false,
piecesModalKey: 0,
descriptionTooltip: false,
alertMsg:
'این درخواست در پیشنویس ها ذخیره شده و هنوز در پایگاه داده شرکت آسان سرویس ثبت نگردیده. شما میتوانید قطعات را در هر زمان به این فرم اضافه یا از فرم حذف کنید سپس نسبت به ارسال نهایی اقدام کنید.'
}
},
computed: {
prId() {
return this.$route.params.pr
},
descriptionPlaceHolder() {
if (this.pieceRequest.status === 'temp') return 'توضیحات راجع به قطعات را میتوانید اینجا بنویسید'
else return 'بدون توضیحات'
}
},
mounted() {
setTimeout(() => {
if (this.pieceRequest.status === 'temp') this.descriptionTooltip = true
}, 1000)
},
methods: {
closePiecesModal() {
this.piecesModal = false
this.piecesModalKey = Math.random()
},
removeItemFromList(id) {
if (this.pieceRequest.status !== 'temp') return
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/removePrItems/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در انجام عملیات پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
updateDescription() {
if (this.pieceRequest.status !== 'temp') return
const data = { description: this.pieceRequest.description }
this.$axios
.put(`/api/agent/prDescription/${this.prId}`, data)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در ثبت اطلاعات پیش آمده'
})
})
},
sendForm() {
this.$confirm('فرم درخواست قطعه به آسان سرویس ارسال شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.post(`/api/agent/sendPr/${this.prId}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-agents-pieces', query: { type: 'sent' } })
})
.catch(err => {
let msg = 'مشکلی در ارسال درخواست پیش آمده'
if (err.response.status === 406) msg = err.response.data.message
this.$message({
type: 'error',
message: msg
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
removePR() {
this.$confirm('این فرم از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/pr/${this.prId}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-agents-pieces', query: { type: 'temp' } })
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف پیشنویس پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+232
View File
@@ -0,0 +1,232 @@
<template>
<user-dashboard-container page-class="agent-requests" panel-title="لیست درخواست های قطعه">
<div class="filter mb-5">
<h4 style="display: inline-block; margin-left: 15px">مشاهده لیست:</h4>
<button class="switchBtns btn" :class="type === 'temp' && 'btn-primary'" @click="type = 'temp'">
پیشنویس ها
</button>
<button class="switchBtns btn" :class="type === 'sent' && 'btn-primary'" @click="type = 'sent'">
ارسال شده ها
</button>
<button class="switchBtns btn" :class="type === 'delivered' && 'btn-primary'" @click="type = 'delivered'">
انجام شده ها
</button>
<div v-if="type !== 'temp'" class="search mt-3" :class="serachBoxClass">
<el-input v-model="searchInput" clearable placeholder="جستجو در لیست با کد پیگیری" />
</div>
</div>
<div class="tableBox">
<table class="agent-requests" :class="type !== 'temp' && 'extended'">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="description">توضیحات</th>
<th class="createDate">تاریخ ایجاد</th>
<template v-if="type === 'sent' || type === 'delivered'">
<th class="sendDate">تاریخ ارسال</th>
<th class="trackingCode">کد پیگیری</th>
<th class="status">وضعیت</th>
</template>
<th v-if="type === 'delivered'" class="deliveryCode">کد ارسال مرسوله</th>
<th class="quantity">تعداد قطعه</th>
<th class="details">جزئیات</th>
</tr>
</thead>
<tbody>
<template v-if="filteredList.length">
<tr v-for="(item, index) in filteredList" :key="item._id" :title="item.description">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="description">
<span v-if="item.description" class="singleLineTxt">{{ item.description }}</span>
<span v-else style="color: gray">بدون توضیحات</span>
</td>
<td class="createDate">
<span> {{ $jDate(item.createDate) }} </span>
</td>
<template v-if="type === 'sent' || type === 'delivered'">
<td class="sendDate">
<span>{{ $jDate(item.sendDate) }}</span>
</td>
<td class="trackingCode">
<span>{{ item.trackingCode }}</span>
</td>
<td class="status">
<span v-if="item.status === 'sent'">ارسال شده</span>
<span v-if="item.status === 'ongoing'">در دست اقدام</span>
<span v-if="item.status === 'waiting'">در انتظار قطعه</span>
<span v-if="item.status === 'delivered'">تحویل شده</span>
</td>
</template>
<td v-if="type === 'delivered'" class="deliveryCode">
<span>{{ item.deliveryCode || '-' }}</span>
</td>
<td class="quantity">
<span>{{ totalItemsCount(item.items) }}</span>
</td>
<td class="details">
<template v-if="item.status === 'temp'">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removePR(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
<nuxt-link
:to="{
name: 'account-agents-pieces-pr',
params: {
pr: item._id
}
}"
class="btn btn-primary"
>
تکمیل فرم
</nuxt-link>
</template>
<nuxt-link
v-else
:to="{
name: 'account-agents-pieces-pr',
params: {
pr: item._id
}
}"
class="btn btn-primary"
>
مشاهده
</nuxt-link>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
<tr v-if="type === 'temp'" class="addStuffBtn" @click="addPieceRequest">
<td colspan="5">
<button>
<span>افزودن درخواست</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountAgentPrList',
layout: 'user',
async asyncData({ $axios, error }) {
try {
const pieceRequests = await $axios.get('/api/agent/prList')
return {
pieceRequests: pieceRequests.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
pieceRequests: null,
searchInput: ''
}
},
computed: {
type: {
get() {
return this.$route.query.type
},
set(val) {
this.$router.push({ name: 'account-agents-pieces', query: { type: val } })
}
},
serachBoxClass() {
if (this.searchInput && this.filteredList.length) return 'success'
if (this.searchInput && !this.filteredList.length) return 'error'
return null
},
filteredList() {
let filteredBySearch
if (!this.searchInput || this.type === 'temp') filteredBySearch = this.pieceRequests
else {
filteredBySearch = this.pieceRequests.filter(item =>
item.trackingCode?.toLowerCase().includes(this.searchInput.toLowerCase())
)
}
return filteredBySearch.filter(item => {
if (this.type === 'temp') return item.status === 'temp'
if (this.type === 'sent') return item.status !== 'temp' && item.status !== 'delivered'
if (this.type === 'delivered') return item.status === 'delivered'
return false
})
}
},
methods: {
addPieceRequest() {
this.$axios
.post('/api/agent/pr')
.then(res => {
this.$message({
type: 'success',
message: 'درخواست جدید افزوده شد'
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در افزودن درخواست پیش آمده'
})
})
},
totalItemsCount(items) {
let count = 0
items.forEach(item => (count += item.pieceQuantity))
return count
},
removePR(id) {
this.$confirm('این درخواست از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/agent/pr/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف درخواست پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
File diff suppressed because it is too large Load Diff
+39
View File
@@ -0,0 +1,39 @@
<template>
<user-dashboard-container page-class="announcements" panel-title="اعلانات">
<div v-for="item in userAnnouncements" :key="item._id" class="item" :class="!item.seen && 'unread'">
<el-collapse :key="item._id + 'co_parent'" accordion @change="seeAnnouncement">
<el-collapse-item :key="item._id + 'co_item'" :name="item._id">
<template slot="title">
<h3>{{ item.title }}</h3>
</template>
<div>
<p>{{ item.caption }}</p>
</div>
</el-collapse-item>
</el-collapse>
</div>
<h3 v-if="!userAnnouncements.length" style="text-align: center; margin-top: 50px">هیچ اعلانی موجود نیست</h3>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountUserAnnouncements',
layout: 'user',
data() {
return {}
},
computed: {
userAnnouncements() {
return this.$store.state.front.userAnnouncements
}
},
methods: {
seeAnnouncement(id) {
if (!id) return
const item = this.userAnnouncements.find(item => item._id === id)
if (!item.seen) this.$userSocket.emit('user:updateAnnouncement', id)
}
}
}
</script>
+286
View File
@@ -0,0 +1,286 @@
<template>
<user-dashboard-container page-class="post" panel-title="ارسال برای گارانتی">
<el-alert :title="alertMsg" class="mb-3" type="warning"> </el-alert>
<form class="form form_3">
<div class="formDB">
<!-- <img v-if="transactionDraft.db_name === 'panatech'" src="/assets/img/panatech-small.png" alt="panatech" />
<img v-if="transactionDraft.db_name === 'verity'" src="/assets/img/verity-small.png" alt="verity" /> -->
<template v-if="transactionDraft.db_name === 'verity'">
<i class="fas fa-phone-laptop"></i>
<span>لوازم جانبی کامپیوتر و موبایل</span>
</template>
<template v-if="transactionDraft.db_name === 'panatech'">
<i class="fas fa-photo-video"></i>
<span>لوازم صوتی و تصویری خودرو</span>
</template>
<!-- <hr /> -->
</div>
<div class="userInfo">
<div class="formRow">
<label for="customer_name">نام مشتری:</label>
<input id="customer_name" type="text" :value="user.first_name + ' ' + user.last_name" disabled />
</div>
<div class="formRow">
<label for="customer_code">کد مشتری:</label>
<input id="customer_code" type="text" :value="businessCode" disabled />
</div>
<div class="formRow">
<label for="mobile">شماره موبایل:</label>
<input id="mobile" type="text" :value="user.mobile_number" disabled />
</div>
</div>
<div class="formRow">
<label>آدرس:</label>
<textarea name="address" rows="5" disabled :value="userAddress"></textarea>
</div>
<hr />
<div class="formRow">
<label for="description">توضیحات فرم (اختیاری):</label>
<el-tooltip
v-model="descriptionTooltip"
class="item"
effect="dark"
content="میتوانید توضیحات را در هر زمان تغییر دهید"
placement="top-start"
>
<textarea
id="description"
v-model="transactionDraft.description"
name="description"
placeholder="توضیحات راجع به کالاها را میتوانید اینجا بنویسید"
cols="30"
rows="10"
@blur="updateDescription"
></textarea>
</el-tooltip>
</div>
</form>
<div class="add-list">
<h2>لیست کالاهای افزوده شده:</h2>
<div class="tableBox">
<table class="formItems">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="itemName">نام کالا</th>
<th class="quantity">تعداد</th>
<th class="itemSerial">سریال گارانتی</th>
<th class="removeBtn">حذف</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in transactionDraft.items"
:key="item.ItemID + index + '_addListItemKey'"
:title="getItemName(item.ItemID)"
>
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="itemName">
<span class="singleLineTxt">{{ getItemName(item.ItemID) }}</span>
</td>
<td class="quantity">
<span>{{ item.MjQty }}</span>
</td>
<td class="itemSerial">
<span>{{ item.SerialNo1 || '-' }}</span>
</td>
<td class="removeBtn">
<button class="trashIcon-btn" title="حذف کالا" @click="removeItemFromList(item.SerialNo1, item.ItemID)">
<i class="fal fa-trash-alt"></i>
</button>
</td>
</tr>
<tr v-if="!transactionDraft.items.length" class="odd">
<td class="noItem" colspan="5">
<p style="color: #000">هنوز هیچ آیتمی اضافه نکردید.</p>
</td>
</tr>
<tr class="addStuffBtn" @click="stuffModal = true">
<td colspan="5">
<button>
<span>افزودن کالا</span>
<i class="far fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
<hr />
<div class="btnRow">
<button class="btn btn-primary" @click="agentsModal = true">ارسال به آسان سرویس</button>
<button class="btn btn-danger" @click="removeDraft">حذف این فرم</button>
</div>
</div>
<template #body>
<AddStuffModal
:key="addStuffKey"
:show="stuffModal"
:db_name="transactionDraft.db_name"
@closeModal="closeAddStuff"
/>
<SelectAgentModal :key="agentsKey" :draft="transactionDraft" :show="agentsModal" @closeModal="closeAgents" />
</template>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountDraftDetails',
layout: 'user',
async asyncData({ $axios, params, error }) {
try {
const transactionDraft = await $axios.get(`/api/user/transactionDraft/${params.draftID}`)
return {
transactionDraft: transactionDraft.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
transactionDraft: null,
validation: {},
stuffModal: false,
agentsModal: false,
addStuffKey: 0,
agentsKey: 1,
descriptionTooltip: false,
alertMsg:
'این فرم در پیشنویس ها ذخیره شده و هنوز در پایگاه داده شرکت آسان سرویس ثبت نگردیده. شما میتوانید کالاها را در هر زمان به این فرم اضافه یا از فرم حذف کنید سپس نسبت به ارسال نهایی اقدام کنید.'
}
},
computed: {
user() {
return this.$auth.user
},
userAddress() {
const user = this.user
return user.province_name + '، ' + user.city_name + '، ' + user.address + '،کد پستی: ' + user.postal_code
},
products() {
if (this.transactionDraft.db_name === 'panatech') return this.$store.state.front.panatechProducts
else if (this.transactionDraft.db_name === 'verity') return this.$store.state.front.verityProducts
else return []
},
draftID() {
return this.$route.params.draftID
},
businessCode() {
const errMsg = 'عدم ثبت در پایگاه داده'
if (this.transactionDraft.db_name === 'panatech') return this.user.panatech_businessCode || errMsg
if (this.transactionDraft.db_name === 'verity') return this.user.verity_businessCode || errMsg
return errMsg
}
},
mounted() {
setTimeout(() => (this.descriptionTooltip = true), 1000)
},
methods: {
closeAddStuff() {
this.stuffModal = false
this.addStuffKey = Math.random()
},
closeAgents() {
this.agentsModal = false
this.agentsKey = Math.random() + 1
},
getItemName(id) {
return this.products?.filter(item => item.ItemID === id)[0]?.ItemName || 'درحال بارگیری'
},
removeItemFromList(itemSerial, itemId) {
this.$confirm('این مورد حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.put(`/api/user/transactionDraftItemRemove/${this.draftID}`, { itemId, itemSerial })
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$nuxt.refresh()
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در انجام عملیات پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
},
updateDescription() {
const data = { description: this.transactionDraft.description }
this.$axios
.put(`/api/user/transactionDraft/${this.draftID}`, data)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در ثبت اطلاعات پیش آمده'
})
})
},
removeDraft() {
this.$confirm('این فرم از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/user/transactionDraft/${this.draftID}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
this.$router.push({ name: 'account-drafts' })
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف پیشنویس پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+129
View File
@@ -0,0 +1,129 @@
<template>
<user-dashboard-container page-class="drafts" panel-title="لیست پیشنویس ها">
<div class="tableBox">
<table class="drafts">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="description">توضیحات</th>
<th class="brand">نوع</th>
<th class="quantity">تعداد کالاها</th>
<th class="details">جزئیات</th>
</tr>
</thead>
<tbody>
<template v-if="transactionDrafts.length">
<tr v-for="(item, index) in transactionDrafts" :key="item._id" :title="item.description">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="description">
<span v-if="item.description" class="singleLineTxt">{{ item.description }}</span>
<span v-else style="color: gray">بدون توضیحات</span>
</td>
<td class="brand">
<!-- <img src="/assets/img/verity-small.png" alt="verity" v-if="item.db_name === 'verity'" />
<img src="/assets/img/panatech-small.png" alt="panatech" v-if="item.db_name === 'panatech'" /> -->
<i
v-if="item.db_name === 'verity'"
class="fas fa-phone-laptop"
title="لوازم جانبی کامپیوتر و موبایل"
></i>
<i v-if="item.db_name === 'panatech'" class="fas fa-photo-video" title="لوازم صوتی و تصویری خودرو"></i>
</td>
<td class="quantity">
<span>{{ totalItemsCount(item) }}</span>
</td>
<td class="details">
<button class="trashIcon-btn" title="حذف پیشنویس" @click="removeDraft(item._id)">
<i class="fal fa-trash-alt"></i>
</button>
<nuxt-link
:to="{
name: 'account-drafts-draftID',
params: {
draftID: item._id
}
}"
class="btn btn-primary"
>
تکمیل فرم
</nuxt-link>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountDraftList',
layout: 'user',
async asyncData({ $axios, $auth, error }) {
try {
const transactionDrafts = await $axios.get('/api/user/transactionDrafts')
return {
transactionDrafts: transactionDrafts.data
}
} catch (e) {
error({ status: 404, message: 'There is a problem here' })
}
},
data() {
return {
transactionDrafts: null
}
},
methods: {
totalItemsCount(draft) {
const items = draft.items
let count = 0
items.forEach(item => (count += item.MjQty))
return count
},
removeDraft(id) {
this.$confirm('این فرم از پیشنویس ها حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
})
.then(() => {
this.$axios
.delete(`/api/user/transactionDraft/${id}`)
.then(res => {
this.$message({
type: 'success',
message: res.data.message
})
})
.catch(() => {
this.$message({
type: 'error',
message: 'مشکلی در حذف پیشنویس پیش آمده'
})
})
})
.catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
})
})
}
}
}
</script>
+203
View File
@@ -0,0 +1,203 @@
<template>
<user-dashboard-container page-class="factor" panel-title="فاکتور">
<div id="factor-layout">
<div class="pageHeader">
<div class="row1">
<h2>
<span>سیستم جاری</span>
<br />
<span>فاکتور گارانتی</span>
</h2>
</div>
<div class="row2">
<p>
<span>شماره حواله: </span>
<span>{{ factorInfo.TransNumber }}</span>
</p>
<p>
<span>تاریخ حواله: </span>
<span>{{ $jDate(factorInfo.TransDate) }}</span>
</p>
</div>
</div>
<div class="factor">
<div class="factorInfo">
<div class="row1">
<p>
<span>کد شخص: </span>
<span>{{ userBusinessCode }}</span>
</p>
<p>
<span>طرف حساب: </span>
<span>{{ user.first_name + ' ' + user.last_name }}</span>
</p>
<p>
<span>شماره پذیرش: </span>
<span>{{ $route.query.atn }}</span>
</p>
</div>
<div class="row2">
<p>
<span>آدرس: </span>
<span>{{ factorInfo.cAddress1 }}</span>
</p>
</div>
<div class="row3">
<p>
<span>شماره تماس: </span>
<span>{{ factorInfo.cTel1 }}</span>
</p>
</div>
<div class="row4">
<p>
<span>شرح حواله: </span>
<span>{{ factorInfo.Description || '---' }}</span>
</p>
</div>
</div>
<div class="table">
<table>
<thead>
<tr>
<th>ردیف</th>
<th>نام کالا</th>
<th>تعداد کل</th>
<th>مرجوع از فروش</th>
<th>مرجوعی/آسیب فیزیکی</th>
<th>مرجوعی/سالم</th>
<th>تعویض</th>
<th>تعمير با هزينه شخصی</th>
<th>تعمير با هزينه شرکت</th>
<th>مانده</th>
<th>توضیحات</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in factor" :key="index + '_tableItems_q_ar'">
<td>{{ index + 1 }}</td>
<td>{{ item.ItemName }}</td>
<td>{{ item.ItemReceptionNQty }}</td>
<td>{{ item.SaleReturn || '-' }}</td>
<td>{{ item.Return_Damaged || '-' }}</td>
<td>{{ item.Return_Healthy || '-' }}</td>
<td>{{ item.Replacement || '-' }}</td>
<td>{{ item.Repair_Self || '-' }}</td>
<td>{{ item.Repair_Company || '-' }}</td>
<td>{{ residual(item) }}</td>
<td>{{ item.ItemReplacementNames || '-' }}</td>
</tr>
<!-- table footer -->
<tr>
<td colspan="2">جمع</td>
<td>{{ sum('ItemReceptionNQty') }}</td>
<td>{{ sum('SaleReturn') }}</td>
<td>{{ sum('Return_Damaged') }}</td>
<td>{{ sum('Return_Healthy') }}</td>
<td>{{ sum('Replacement') }}</td>
<td>{{ sum('Repair_Self') }}</td>
<td>{{ sum('Repair_Company') }}</td>
<td>{{ residualSum() }}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<table-notice />
<button class="btn btn-primary mt-3" @click="print('factor-layout')">چاپ فاکتور</button>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountGuaranteeFactor',
layout: 'user',
async asyncData({ $axios, $auth, query, error }) {
try {
const acceptedTN = query.atn
const host = query.host
const db_name = query.db_name
const user = $auth.user
function businessCode() {
if (db_name === 'verity') return user.verity_businessCode
else if (db_name === 'panatech') return user.panatech_businessCode
else return null
}
if (host === 'ar') {
const factorData = {
url: `/api/GetItemReceptionDetails?BusinessCode=${businessCode()}&ItemReceptionTransNumber=${acceptedTN}`,
db: db_name
}
const factor = await $axios.post('/api/cross/getRouteManager', factorData)
if (factor.data.error || !factor.data.data.length) throw new Error('invalid params')
return {
factor: factor.data.data
}
} else if (host === 'as') {
/// fuctions go here
} else throw new Error('invalid params')
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
transactionItems: null,
factor: null
}
},
computed: {
user() {
return this.$auth.user
},
userBusinessCode() {
const db_name = this.$route.query.db_name
if (db_name === 'verity') return this.user.verity_businessCode
else if (db_name === 'panatech') return this.user.panatech_businessCode
else return '-'
},
factorInfo() {
return this.factor[0]
}
},
methods: {
print(id) {
$(`#${id}`).print()
},
residual(item) {
return (
Number(item.ItemReceptionNQty) -
Number(item.SaleReturn) -
Number(item.Return_Damaged) -
Number(item.Return_Healthy) -
Number(item.Replacement) -
Number(item.Repair_Self) -
Number(item.Repair_Company)
)
},
sum(param) {
let sum = 0
let index = -1
for (const item of this.factor) {
index++
sum += Number(item[param])
if (index === this.factor.length - 1) return sum
}
},
residualSum() {
let sum = 0
let index = -1
for (const item of this.factor) {
index++
sum += Number(this.residual(item))
if (index === this.factor.length - 1) return sum
}
}
}
}
</script>
+191
View File
@@ -0,0 +1,191 @@
<template>
<user-dashboard-container page-class="guarantee" panel-title="لیست گارانتی">
<div class="filter mb-5">
<h4 style="display: inline-block; margin-left: 15px">مشاهده لیست:</h4>
<button class="switchBtns btn" :class="type === 'ttl' && 'btn-primary'" @click="type = 'ttl'">
ارسال شده ها
</button>
<button class="switchBtns btn" :class="type === 'atl' && 'btn-primary'" @click="type = 'atl'">
پذیرش شده ها
</button>
</div>
<div v-loading="fetching" class="tableBox">
<table class="qaurantee" :class="type === 'atl' && 'atl'">
<thead>
<tr>
<th class="index-atl">ردیف</th>
<th>شماره پذیرش موقت</th>
<th>تاریخ ارسال فرم</th>
<template v-if="type === 'atl'">
<th>شماره پذیرش دائم</th>
<th>تاریخ پذیرش</th>
<th>شماره بیجک</th>
<th>نظر سنجی</th>
</template>
<th class="brand">نوع</th>
<th>جزئیات</th>
</tr>
</thead>
<tbody>
<template v-if="filteredList.length">
<tr v-for="(item, index) in filteredList" :key="item._id">
<td class="index-atl">
<span>{{ index + 1 }}</span>
</td>
<td>
<span>{{ item.TempReceiptTransNumber }}</span>
</td>
<td>
<span>{{ $jDate(item.TempReceiptTransDate) }}</span>
</td>
<template v-if="type === 'atl'">
<td>
<span>{{ item.ItemReceptionTransNumber }}</span>
</td>
<td>
<span>{{ $jDate(item.ItemReceptionTransDate) }}</span>
</td>
<td>
<span>{{ item.deliveryCode || '-' }}</span>
</td>
<td>
<span v-if="checkSurveys(item.ItemReceptionTransNumber)" style="color: green">نظر ثبت شده</span>
<span v-else>
<nuxt-link
:to="{ name: 'account-survey', query: { code: item.ItemReceptionTransNumber } }"
style="color: #065495; cursor: pointer"
>
ثبت نظر
</nuxt-link>
</span>
</td>
</template>
<td class="brand">
<i
v-if="item.db_name === 'verity'"
class="fas fa-phone-laptop"
title="لوازم جانبی کامپیوتر و موبایل"
></i>
<i v-if="item.db_name === 'panatech'" class="fas fa-photo-video" title="لوازم صوتی و تصویری خودرو"></i>
</td>
<td>
<nuxt-link
:to="{
name: 'account-guarantee-view',
query: {
ttn: item.TempReceiptTransNumber,
atn: item.ItemReceptionTransNumber || undefined,
host: item.host,
db_name: item.db_name
}
}"
class="btn btn-primary"
>
مشاهده
</nuxt-link>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountGuaranteeList',
layout: 'user',
data() {
return {
verityTransactions: [],
panatechTransactions: [],
agentsTransactions: [],
surveys: [],
fetching: false
}
},
computed: {
type: {
get() {
return this.$route.query.type
},
set(val) {
this.$router.push({ name: 'account-guarantee', query: { type: val } })
}
},
totalItems() {
const totalArray = []
for (const item of this.verityTransactions) {
totalArray.push({ ...item, host: 'ar', db_name: 'verity' })
}
for (const item of this.panatechTransactions) {
totalArray.push({ ...item, host: 'ar', db_name: 'panatech' })
}
for (const item of this.agentsTransactions) {
totalArray.push({ ...item, host: 'as' })
}
return totalArray
},
filteredList() {
return this.totalItems
.filter(item => {
if (this.type === 'ttl') return !item.ItemReceptionTransNumber
else if (this.type === 'atl') return item.ItemReceptionTransNumber
return false
})
.reverse()
}
},
async mounted() {
try {
this.fetching = true
const user = this.$auth.user
const verityData = {
url: `/api/GetItemReceptionInfo?BusinessCode=${user.verity_businessCode}`,
db: 'verity'
}
const panatechData = {
url: `/api/GetItemReceptionInfo?BusinessCode=${user.panatech_businessCode}`,
db: 'panatech'
}
const allData = await Promise.all([
// fetch verityTransactions
this.$axios.post('/api/cross/getRouteManager', verityData),
// fetch panatechTransactions
this.$axios.post('/api/cross/getRouteManager', panatechData),
// fetch agentsTransactions
this.$axios.get('/api/user/transactions'),
// fetch all surveys
this.$axios.get('/api/user/surveys')
])
const verityTransactions = allData[0]
const panatechTransactions = allData[1]
const agentsTransactions = allData[2]
const surveys = allData[3]
this.verityTransactions = verityTransactions.data.data
this.panatechTransactions = panatechTransactions.data.data
this.agentsTransactions = agentsTransactions.data
this.surveys = surveys.data
this.fetching = false
} catch (e) {
this.$arpaError()
}
},
methods: {
checkSurveys(code) {
return this.surveys.find(item => item.code === code)
}
}
}
</script>
@@ -0,0 +1,202 @@
<template>
<user-dashboard-container page-class="factor" panel-title="فاکتور">
<div id="factor-layout">
<div class="pageHeader">
<div class="row1">
<h2>
<span>سیستم جاری</span>
<br />
<span>فاکتور تعمیرات</span>
</h2>
</div>
<div class="row2">
<p>
<span>شماره حواله: </span>
<span>{{ factorInfo.TransNumber }}</span>
</p>
<p>
<span>تاریخ حواله: </span>
<span>{{ $jDate(factorInfo.TransDate) }}</span>
</p>
</div>
</div>
<div class="factor">
<div class="factorInfo">
<div class="row1">
<p>
<span>کد شخص: </span>
<span>{{ userBusinessCode }}</span>
</p>
<p>
<span>طرف حساب: </span>
<span>{{ user.first_name + ' ' + user.last_name }}</span>
</p>
<p>
<span>شماره پذیرش: </span>
<span>{{ $route.query.atn }}</span>
</p>
</div>
<div class="row2">
<p>
<span>آدرس: </span>
<span>{{ factorInfo.cAddress1 }}</span>
</p>
</div>
<div class="row3">
<p>
<span>شماره تماس: </span>
<span>{{ factorInfo.cTel1 }}</span>
</p>
</div>
<div class="row4">
<p>
<span>شرح حواله: </span>
<span>{{ factorInfo.Description || '---' }}</span>
</p>
</div>
</div>
<div class="table">
<table>
<thead>
<tr>
<th>ردیف</th>
<th>کد کالا</th>
<th>نام کالا</th>
<th>تعداد کالا</th>
<th>مبلغ اجرت (ريال)</th>
<th>مبلغ کل (ريال)</th>
<th>معایب</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in factor" :key="index + '_tableItem_g_ar_f'">
<td>{{ index + 1 }}</td>
<td>{{ item.ItemCode }}</td>
<td>{{ item.ItemName }}</td>
<td>{{ item.Repair_Self }}</td>
<td>{{ item.TASPrice.toLocaleString() || '-' }}</td>
<td>{{ totalPrice(item).toLocaleString() }}</td>
<td>{{ item.Note || '-' }}</td>
</tr>
<!-- table footer -->
<tr>
<td colspan="3">جمع</td>
<td>{{ sum('Repair_Self') }}</td>
<!-- <td>{{ sum('TASPrice').toLocaleString() }}</td>-->
<td>-</td>
<td>{{ totalPriceSum().toLocaleString() }}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<table-notice />
<button class="btn btn-primary mt-3" @click="print('factor-layout')">چاپ فاکتور</button>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountGuaranteePaymentFactor',
layout: 'user',
async asyncData({ $axios, $auth, query, error }) {
try {
const acceptedTN = query.atn
const host = query.host
const db_name = query.db_name
const user = $auth.user
function businessCode() {
if (db_name === 'verity') return user.verity_businessCode
else if (db_name === 'panatech') return user.panatech_businessCode
else return null
}
if (host === 'ar') {
const guaranteeFactorData = {
url: `/api/GetItemReceptionDetails?BusinessCode=${businessCode()}&ItemReceptionTransNumber=${acceptedTN}`,
db: db_name
}
const factorData = {
url: `/api/GetCustomizedRepairInfo?BusinessCode=${businessCode()}&TransNumber=${acceptedTN}`,
db: db_name
}
const allData = await Promise.all([
// fetch guaranteeFactor
$axios.post('/api/cross/getRouteManager', guaranteeFactorData),
// fetch factor
$axios.post('/api/cross/getRouteManager', factorData)
])
const guaranteeFactor = allData[0]
const factor = allData[1]
// validate data
if (guaranteeFactor.data.error || !guaranteeFactor.data.data.length) throw new Error('invalid params')
if (factor.data.error || !factor.data.data.length) throw new Error('invalid params')
return {
factor: factor.data.data,
guaranteeFactor: guaranteeFactor.data.data
}
} else if (host === 'as') {
/// functions go here
} else throw new Error('invalid params')
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
transactionItems: null,
factor: null,
guaranteeFactor: null
}
},
computed: {
user() {
return this.$auth.user
},
userBusinessCode() {
const db_name = this.$route.query.db_name
if (db_name === 'verity') return this.user.verity_businessCode
else if (db_name === 'panatech') return this.user.panatech_businessCode
else return '-'
},
factorInfo() {
return this.guaranteeFactor[0]
}
},
methods: {
print(id) {
$(`#${id}`).print()
},
totalPrice(item) {
return Number(item.TASPrice) * Number(item.Repair_Self)
},
sum(param) {
let sum = 0
let index = -1
for (const item of this.factor) {
index++
sum += Number(item[param])
if (index === this.factor.length - 1) return sum
}
},
totalPriceSum() {
let sum = 0
let index = -1
for (const item of this.factor) {
index++
sum += Number(this.totalPrice(item))
if (index === this.factor.length - 1) return sum
}
}
}
}
</script>
+252
View File
@@ -0,0 +1,252 @@
<template>
<user-dashboard-container page-class="post-receipt" panel-title="رسید ارسال برای گارانتی">
<div class="note">
<h2 class="mb-2">توجه:</h2>
<p>
*این رسید به منزله ی دریافت کالا توسط واحد خدمات پس از فروش نمیباشد و در صورت دریافت کالاهای مندرج در این رسید
توسط واحد پذیرش، رسید پذیرش قطعی صادر میگردد.
</p>
</div>
<div class="box-face-receipt">
<div class="receipt">
<div class="receipt-head">
<logo />
<p>بیجک چاپی</p>
</div>
<div class="title">
<p>برای ارسال این بیجک چاپی را روی بسته ارسال بچسبانید.</p>
</div>
<div id="box-face-receipt">
<div class="receipt-body">
<div class="senderInfo">
<div class="row">
<div class="col-12 col-lg-8 order-1 order-lg-0">
<h2>فرستنده:</h2>
<div class="infoRow">
<p>
نام و نام خانوادگی:
{{ user.first_name + ' ' + user.last_name }}
</p>
</div>
<div class="infoRow">
<p>آدرس: {{ transactionInfo.cAddress1 }}</p>
</div>
<div class="infoRow">
<p>شماره تماس: {{ transactionInfo.cTel1 }}</p>
</div>
</div>
<div class="col-12 col-lg-4 order-0 order-lg-1 d-flex justify-content-end flex-wrap align-items-start">
<div class="topLeft">
<b v-if="host === 'ar'">تاریخ صدور: {{ $jDate(transactionInfo.TransDate) }}</b>
<b v-if="host === 'as'">تاریخ صدور: {{ $jDate(transactionInfo.TempReceiptTransDate) }}</b>
</div>
<div class="topLeft">
<b>شماره پذیرش موقت: {{ $route.query.ttn }}</b>
</div>
</div>
</div>
</div>
<hr />
<div class="receiverInfo">
<div class="row">
<div class="col-12 col-lg-8 order-1 order-lg-0">
<h2>گیرنده:</h2>
<div class="infoRow">
<p>نام: {{ receiverInfo.name }}</p>
</div>
<div class="infoRow">
<p>آدرس: {{ receiverInfo.address }}</p>
</div>
<div class="infoRow">
<p>کدپستی: {{ receiverInfo.postalCode }}</p>
</div>
<div class="infoRow">
<p>شماره تماس: {{ receiverInfo.phone }}</p>
</div>
</div>
<div class="col-12 col-lg-4 order-0 order-lg-1 d-flex justify-content-end">
<div class="topLeft" :class="host">
<div>
<logo />
</div>
<dir v-if="host === 'ar'">
<img src="/assets/img/tipaxQR.jpg" alt="tipaxQR Code" />
<p>
<b>1111642</b>
</p>
</dir>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="print-btn">
<button class="btn btn-primary" @click="print('box-face-receipt')">چاپ</button>
</div>
</div>
<div class="box-inner-receipt">
<div class="receipt">
<div class="receipt-head">
<logo />
<p>فهرست اقلام پذیرش موقت شده</p>
</div>
<div class="title">
<p>این فرم را داخل بسته ارسالی برای گارانتی قرار دهید.</p>
</div>
<div id="box-inner-receipt">
<div class="receipt-body">
<div class="topBar row">
<div class="col-12 col-lg-6 logo-side">
<logo />
</div>
<div class="col-12 col-lg-6 d-flex justify-content-end align-items-center">
<div class="topLeft">
<b v-if="host === 'ar'">تاریخ صدور: {{ $jDate(transactionInfo.TransDate) }}</b>
<b v-if="host === 'as'">تاریخ صدور: {{ $jDate(transactionInfo.TempReceiptTransDate) }}</b>
</div>
<div class="topLeft">
<b>شماره پذیرش موقت: {{ $route.query.ttn }}</b>
</div>
</div>
</div>
<hr />
<div class="stuff-list">
<div class="tableBox">
<table>
<thead>
<tr>
<th>ردیف</th>
<th style="min-width: 250px">نام کالا</th>
<th style="">تعداد</th>
<th style="min-width: 150px">سریال گارانتی</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in items" :key="index + '_RecieptItem'">
<td>{{ index + 1 }}</td>
<td v-if="host === 'ar'">{{ item.ItemName }}</td>
<td v-if="host === 'as'">{{ getItemName(item.ItemID) || 'درحال بارگیری ...' }}</td>
<td v-if="host === 'ar'">{{ item.NQty }}</td>
<td v-if="host === 'as'">{{ item.MjQty }}</td>
<td>{{ item.SerialNo1 || '-' }}</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</div>
</div>
</div>
</div>
<div class="print-btn">
<button class="btn btn-primary" @click="print('box-inner-receipt')">چاپ</button>
</div>
</div>
</user-dashboard-container>
</template>
<script>
if (process.client) require('static/assets/js/jQuery.print.min')
export default {
name: 'AccountGuaranteePostReciept',
layout: 'user',
async asyncData({ $axios, $auth, query, error }) {
try {
const tempTN = query?.ttn
const host = query?.host
const db_name = query?.db_name
const user = $auth.user
function businessCode() {
if (db_name === 'verity') return user.verity_businessCode
else if (db_name === 'panatech') return user.panatech_businessCode
else return null
}
if (host === 'ar') {
const transactionItemsData = {
url: `/api/GetTransactionDetails?BusinessCode=${businessCode()}&TransNumber=${tempTN}&DocAliasID=144&WithSerials=1`,
db: db_name
}
const transactionItems = await $axios.post('/api/cross/getRouteManager', transactionItemsData)
if (transactionItems.data.error || !transactionItems.data.data.length) throw new Error('invalid values')
return {
transactionItems: transactionItems.data.data
}
} else if (host === 'as') {
const transaction = await $axios.get(`/api/user/transaction/${tempTN}`)
return {
transaction: transaction.data
}
} else throw new Error('invalid values')
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
transactionItems: null,
transaction: null
}
},
computed: {
user() {
return this.$auth.user
},
receiverInfo() {
const host = this.host
const main = {
name: this.$config.recieverName,
address: this.$config.recieverAddress,
postalCode: this.$config.recieverPostalCode,
phone: this.$config.recieverPhone
}
if (host === 'ar') return main
else {
const agent = this.transaction.agent_id
return {
name: agent?.full_name + ' (نمایندگی ' + agent.city_name + ')',
address: agent?.province_name + '، ' + agent?.city_name + '، ' + agent?.address,
postalCode: agent?.postal_code,
phone: agent?.tel_number + ' - ' + agent?.mobile_number
}
}
},
products() {
if (this.$route.query.db_name === 'verity') return this.$store.state.front.verityProducts
else if (this.$route.query.db_name === 'panatech') return this.$store.state.front.panatechProducts
else return []
},
host() {
return this.$route.query?.host
},
items() {
if (this.host === 'ar') return this.transactionItems
else if (this.host === 'as') return this.transaction.items
else return []
},
transactionInfo() {
if (this.host === 'ar') return this.transactionItems[0]
else if (this.host === 'as') return this.transaction
else return {}
}
},
methods: {
getItemName(ItemID) {
return this.products.find(item => item.ItemID === ItemID)?.ItemName
},
print(id) {
$(`#${id}`).print()
}
}
}
</script>
+240
View File
@@ -0,0 +1,240 @@
<template>
<user-dashboard-container page-class="guarantee-details" panel-title="جزئیات">
<form action="" class="form form_3">
<div class="userInfo">
<div class="formRow">
<label v-if="$route.query.atn">کد پذیرش دائم:</label>
<label v-else>کد پذیرش موقت:</label>
<input type="text" disabled :value="$route.query.atn || $route.query.ttn" />
</div>
<div class="formRow">
<label>شماره تماس:</label>
<input type="text" disabled :value="transactionInfo.cTel1" />
</div>
<div class="formRow">
<label>تاریخ ارسال فرم:</label>
<input
type="text"
disabled
:value="$jDate(host === 'ar' ? transactionInfo.TransDate : transactionInfo.TempReceiptTransDate)"
/>
</div>
</div>
<div class="formRow">
<label>آدرس:</label>
<textarea name="" rows="3" disabled :value="transactionInfo.cAddress1"></textarea>
</div>
<div class="formRow">
<label>توضیحات فرم:</label>
<textarea name="" rows="3" disabled :value="transactionInfo.Description"></textarea>
</div>
</form>
<hr />
<div class="tableBox">
<table class="formItems">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="itemName">نام کالا</th>
<th class="quantity">تعداد</th>
<th class="itemSerial">سریال گارانتی</th>
<th class="date">تاریخ اتمام گارانتی</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in items" :key="index + '_guaranteeItemsList'" :title="item.ItemName">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="itemName">
<span v-if="host === 'ar'" class="singleLineTxt">{{ item.ItemName }}</span>
<span v-if="host === 'as'" class="singleLineTxt">{{
getItemName(item.ItemID) || 'درحال بارگیری ...'
}}</span>
</td>
<td class="quantity">
<span v-if="host === 'ar'">{{ item.NQty }}</span>
<span v-if="host === 'as'">{{ item.MjQty }}</span>
</td>
<td class="itemSerial">
<span>{{ item.SerialNo1 || '-' }}</span>
</td>
<td class="date">
<span>{{ item.GEndDate || '-' }}</span>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
<hr />
<div class="buttons">
<nuxt-link
:to="{
name: 'account-guarantee-receipt',
query: { ttn: $route.query.ttn, host: host, db_name: $route.query.db_name }
}"
class="btn btn-primary"
>مشاهده رسید ها</nuxt-link
>
<nuxt-link
v-if="factor && factor.length"
:to="{
name: 'account-guarantee-factor',
query: { atn: $route.query.atn, host: host, db_name: $route.query.db_name }
}"
class="btn btn-primary"
style="margin-right: 5px"
>
مشاهده فاکتور
</nuxt-link>
</div>
<template v-if="paymentFactor && paymentFactor.length">
<hr />
<div class="paymentFactorBtn mb-5">
<strong
>*در موارد ارسالی شما کالا بدون گارانتی وجود دارد و تعمیرات شامل هزینه میشود.برای مشاهده فاکتور هزینه ها روی
دکمه زیر کلیک کنید و پس از پرداخت هزینه عکس فیش پرداختی را در تیکت برای ادمین بفرستید.(شماره پذیرش مربوطه را
در تیکت مشخص کنید)</strong
>
<nuxt-link
:to="{
name: 'account-guarantee-paymentFactor',
query: { atn: $route.query.atn, host: host, db_name: $route.query.db_name }
}"
class="btn btn-primary"
>مشاهده فاکتور تعمیرات
</nuxt-link>
</div>
</template>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountGuaranteeDetails',
layout: 'user',
async asyncData({ $axios, $auth, query, error }) {
try {
const tempTN = query?.ttn
const acceptedTN = query?.atn
const host = query?.host
const db_name = query?.db_name
const user = $auth.user
function businessCode() {
if (db_name === 'verity') return user.verity_businessCode
else if (db_name === 'panatech') return user.panatech_businessCode
else return null
}
if (host === 'ar') {
// fetch data from arpa
const transactionItemsData = {
url: `/api/GetTransactionDetails?BusinessCode=${businessCode()}&TransNumber=${
acceptedTN || tempTN
}&DocAliasID=${acceptedTN ? 63 : 144}&WithSerials=1`,
db: db_name
}
const transactionItems = await $axios.post('/api/cross/getRouteManager', transactionItemsData)
if (transactionItems.data.error || !transactionItems.data.data.length) throw new Error('invalid params')
return {
transactionItems: transactionItems.data.data
}
} else if (host === 'as') {
// fetch data from asan-service
const transaction = await $axios.get(`/api/user/transaction/${tempTN}`)
return {
transaction: transaction.data
}
} else throw new Error('invalid params')
} catch (e) {
error({ status: 404, message: 'Page not found' })
}
},
data() {
return {
transactionItems: null,
transaction: null,
factor: null,
paymentFactor: null
}
},
computed: {
products() {
if (this.$route.query.db_name === 'verity') return this.$store.state.front.verityProducts
else if (this.$route.query.db_name === 'panatech') return this.$store.state.front.panatechProducts
else return []
},
host() {
return this.$route.query?.host
},
items() {
if (this.host === 'ar') return this.transactionItems
else if (this.host === 'as') return this.transaction.items
else return []
},
transactionInfo() {
if (this.host === 'ar') return this.transactionItems[0]
else if (this.host === 'as') return this.transaction
else return {}
}
},
mounted() {
const host = this.host
const user = this.$auth.user
const db_name = this.$route.query?.db_name
const acceptedTN = this.$route.query?.atn
if (host === 'ar') {
// fetch data from arpa
const paymentData = {
url: `/api/GetCustomizedRepairInfo?BusinessCode=${
db_name === 'verity' ? user.verity_businessCode : db_name === 'panatech' ? user.panatech_businessCode : ''
}&TransNumber=${acceptedTN}`,
db: db_name
}
const factorData = {
url: `/api/GetItemReceptionDetails?BusinessCode=${
db_name === 'verity' ? user.verity_businessCode : db_name === 'panatech' ? user.panatech_businessCode : ''
}&ItemReceptionTransNumber=${acceptedTN}`,
db: db_name
}
if (acceptedTN) {
this.$axios
.post('/api/cross/getRouteManager', factorData)
.then(res => {
this.factor = res.data.data
})
.catch(err => {
console.log(err)
})
this.$axios
.post('/api/cross/getRouteManager', paymentData)
.then(res => {
this.paymentFactor = res.data.data
})
.catch(err => {
console.log(err)
})
}
} else if (host === 'as') {
// fetch data from asan-service
}
},
methods: {
getItemName(ItemID) {
return this.products.find(item => item.ItemID === ItemID)?.ItemName
}
}
}
</script>
+121
View File
@@ -0,0 +1,121 @@
<template>
<user-dashboard-container page-class="guarantee" panel-title="مانده معین مشتری">
<div v-loading="fetching" class="tableBox">
<table class="history">
<thead>
<tr>
<th class="index">ردیف</th>
<th class="date">تاریخ برگه پذیرش</th>
<th class="transID">شناسه برگه پذیرش</th>
<th class="itemID">شناسه کالا</th>
<th class="itemCode">کد کالا</th>
<th class="itemName">نام کالا</th>
<th class="quantity">تعداد پذیرش</th>
<th class="repairCount">تعداد تعمیرات</th>
<th class="remainCount">مانده</th>
</tr>
</thead>
<tbody>
<template v-if="history.length">
<tr v-for="(item, index) in history" :key="item._id" :title="item.ItemName">
<td class="index">
<span>{{ index + 1 }}</span>
</td>
<td class="date">
<span>{{ $jDate(item.TransDate_63) }}</span>
</td>
<td class="transID">
<span>{{ item.TransactionID_63 }}</span>
</td>
<td class="itemID">
<span>{{ item.ItemID }}</span>
</td>
<td class="itemCode">
<span>{{ item.ItemCode }}</span>
</td>
<td class="itemName">
<span class="singleLineTxt">{{ item.ItemName }}</span>
</td>
<td class="quantity">
<span>{{ item.NQty_63 }}</span>
</td>
<td class="repairCount">
<span>{{ item.NQty_115 }}</span>
</td>
<td class="remainCount">
<span>{{ item.RemainQty }}</span>
</td>
</tr>
</template>
<tr v-else>
<td class="noItem">
<span>هیچ اطلاعاتی وجود ندارد</span>
</td>
</tr>
</tbody>
</table>
</div>
<table-notice />
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountUserGuaranteeRemainHistory',
layout: 'user',
data() {
return {
verityHistory: [],
panatechHistory: [],
fetching: false
}
},
computed: {
history() {
return [...this.verityHistory, ...this.panatechHistory]
}
},
async mounted() {
try {
this.fetching = true
const user = this.$auth.user
const verityData = {
url: `/api/GetRemainingReceptionItems?FromBusinessCode=${user.verity_businessCode}&ToBusinessCode=${user.verity_businessCode}`,
db: 'verity'
// url: `/api/GetRemainingReceptionItems?ToBusinessCode=${user.arpa_businessCode}`
}
const panatechData = {
url: `/api/GetRemainingReceptionItems?FromBusinessCode=${user.panatech_businessCode}&ToBusinessCode=${user.panatech_businessCode}`,
db: 'panatech'
// url: `/api/GetRemainingReceptionItems?ToBusinessCode=${user.arpa_businessCode}`
}
const allData = await Promise.all([
// fetch verity data
this.$axios.post('/api/cross/getRouteManager', verityData),
// fetch panatech data
this.$axios.post('/api/cross/getRouteManager', panatechData)
])
const verityHistory = allData[0]
const panatechHistory = allData[1]
this.verityHistory = verityHistory.data.data
this.panatechHistory = panatechHistory.data.data
this.fetching = false
} catch (e) {
this.$arpaError()
}
}
}
</script>
+15
View File
@@ -0,0 +1,15 @@
<template>
<user-dashboard-container page-class="home" panel-title="پنل کاربری">
<h1>
<span> {{ $auth.user.first_name + ' ' + $auth.user.last_name }} </span>
<span>به پنل کاربری خوش آمدید.</span>
</h1>
</user-dashboard-container>
</template>
<script>
export default {
name: 'AccountIndex',
layout: 'user'
}
</script>

Some files were not shown because too many files have changed in this diff Show More