| Server IP : 34.87.99.72 / Your IP : 216.73.217.31 Web Server : Apache/2.4.46 (Unix) OpenSSL/1.1.1n System : Linux zlock-bitnami-lamp-prod-v2-vm 4.19.0-16-cloud-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64 User : bitnami ( 1000) PHP Version : 7.4.18 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /opt/bitnami/apache/htdocs/app/resources/js/views/LockerBoxes/ |
Upload File : |
<template>
<v-container fluid>
<v-row align="center" justify="end">
<v-col cols="auto" align-self="end">
<div v-if="$authUser.isAdmin()">
<v-btn
x-small color="error"
class="text-capitalize py-3"
@click="confirmOpenBox({
id: '00',
locker_id: locker.id
})"
>
Open All Boxes
</v-btn>
<v-btn
x-small color="blue"
class="text-capitalize white--text py-3 ml-3"
@click="confirmCloseBox({
id: '00',
locker_id: locker.id
})"
>
Force Close All Boxes
</v-btn>
<v-btn
x-small color="warning"
class="text-capitalize white--text py-3 ml-3"
@click="confirmRestartLocker({
id: locker.id
})"
>
Restart Locker App
</v-btn>
<v-btn
x-small color="green"
class="text-capitalize white--text py-3 ml-3"
@click="confirmSyncLocker({
id: locker.id
})"
>
Sync Locker
</v-btn>
<!-- <v-btn
x-small color="blue"
class="text-capitalize py-3 white--text ml-3"
@click="syncLocker({
terminal_id: locker.terminal_id
})"
>
Sync Locker
</v-btn> -->
</div>
<div class="caption grey--text">Locker Last Sync : {{ locker.last_echo_at }}</div>
</v-col>
<v-spacer></v-spacer>
<v-col cols="auto">
<w-action-btn-group
:items="action_btn_group_items()"
></w-action-btn-group>
</v-col>
</v-row>
<v-card class="mt-4" color="transparent" flat>
<v-data-table
ref="dataTable"
:headers="table_headers"
:items="resourceDataSet_"
:options.sync="settings_"
:server-items-length="totalData_"
:footer-props="{
'items-per-page-options': [5, 10, 25, 50]
}"
:loading="model_loading_"
disable-sort
:item-class="row_classes_"
>
<template #[`item.box_type`]="{ item }">
{{ item.box_type ? item.box_type.title : 'N/A' }}
</template>
<template #[`item.status`]="{ item }">
<!-- <span class="pr-1">
<v-icon
v-if="!(item.occupied_box_inventory.length > 0) && !!item.box_type && item.is_open == 0 && item.is_deleted == null"
color="primary" size="18"
title="Available for booking"
>
mdi-lightbulb-on
</v-icon>
<v-icon
v-else
color="grey" size="18"
title="Not Available for booking"
>
mdi-lightbulb-outline
</v-icon>
</span> -->
<span class="pr-1">
<v-icon
v-if="item.is_open > 0"
color="error" size="18"
title="Door Open"
>
mdi-door-open
</v-icon>
<v-icon
v-else
color="grey" size="18"
title="Door Close"
>
mdi-door-open
</v-icon>
</span>
<span class="pr-1">
<v-icon
v-if="item.occupied_box_inventory.length > 0 || item.occupied_box_delivery.length > 0"
color="orange" size="18"
title="Order"
>
mdi-calendar-remove
</v-icon>
<v-icon
v-else
color="grey" size="18"
title="No Order"
>
mdi-calendar-remove
</v-icon>
</span>
<span class="pr-1">
<v-icon
v-if="item.not_empty_box_inventory.length > 0 || item.not_empty_box_delivery.length > 0"
color="blue" size="18"
title="Item"
>
mdi-archive-alert
</v-icon>
<v-icon
v-else
color="grey" size="18"
title="Empty"
>
mdi-archive-alert
</v-icon>
</span>
</template>
<template #[`item.created_at`]="{ item }">
{{ $dayjs(item.created_at).format('YYYY-MM-DD hh:mma') }}
</template>
<template #[`item.action`]="{ item }">
<!-- <v-btn icon small @click="viewMore_(item)">
<v-icon small>mdi-eye</v-icon>
</v-btn> -->
<w-dropdown-menu
left bottom
:items="menu_items(item)"
></w-dropdown-menu>
</template>
</v-data-table>
</v-card>
<!-- form dialog -->
<v-dialog v-model="form_dialog_" max-width="550px" persistent>
<LockerBoxForm
:item="form_item_" :action="form_action_" :visible.sync="form_dialog_"
:available-box-types="available_box_types"
@initialize="emitIntialize()"
></LockerBoxForm>
</v-dialog>
<!-- filter dialog -->
<w-side-dialog
v-model="filter_dialog"
title="Filters"
clearable
@clear="initFilters()"
>
<template #default>
<v-row dense>
<template v-for="(filter,i) in filter_options">
<v-col :key="i" cols="12">
<v-select
v-model="filters_[filter.model]"
:label="filter.label"
:items="filter.items"
class="caption"
outlined
dense hide-details
>
<template #item="{ item }">
<v-list>
<v-list-item-content>
<v-list-item-title v-text="item.text"></v-list-item-title>
<v-list-item-subtitle v-text="item.subtext"></v-list-item-subtitle>
</v-list-item-content>
</v-list>
</template>
</v-select>
</v-col>
</template>
</v-row>
</template>
<template #actions>
<div class="text-right">
<v-btn
rounded block color="primary"
@click="searchData_()"
>
Apply
</v-btn>
</div>
</template>
</w-side-dialog>
<!-- model info dialog -->
<v-navigation-drawer
v-model="view_dialog_"
floating
app
right
temporary
:style="$vuetify.breakpoint.mdAndUp ? 'min-width: 350px;' : '' "
>
<v-card height="100%">
<pre>{{ view_item_.occupied_box_inventory }}</pre>
<!-- <v-btn @click="openLockerBox(view_item_)">openBox</v-btn> -->
</v-card>
</v-navigation-drawer>
</v-container>
</template>
<script>
import LockerBoxForm from './LockerBoxForm'
import WActionBtnGroup from "@components/WActionBtnGroup"
import WDropdownMenu from "@components/WDropdownMenu"
import WSideDialog from "@components/WSideDialog"
import { errorHandlerMixin } from "@/js/mixins/ErrorHandlerMixin"
import { formActionMixin } from "@/js/mixins/FormActionMixin"
import { resourceMixin } from "@/js/mixins/ResourceMixin"
export default{
components:{
LockerBoxForm,
WActionBtnGroup,
WDropdownMenu,
WSideDialog,
},
mixins: [
resourceMixin,
formActionMixin,
errorHandlerMixin
],
props:{
locker: {
type: Object,
default: ()=>{
return {}
}
},
},
data(){
return {
table_headers: [],
filter_dialog: false,
filter_options:[],
sort_options:[],
available_box_types: [],
}
},
watch:{
'locker.available_box_types':{
handler(){
this.available_box_types.push(...this.locker.available_box_types)
this.available_box_types.push(...this.locker.courierBagId)
if(this.locker.available_box_types){
this.setupFilterBar()
}
},
immediate: true,
},
},
created(){
this.options_.activity = this.getActivityRefs_()
this.getAllRefs_([
]).then(()=>{
this.setupFilterBar()
this.initFilters()
this.initTableHeader()
}).then(()=>{
this.initialize_()
})
},
methods:{
emitIntialize(){
this.$emit('initialize')
this.initialize_()
},
initFilters(){
this.filters_ = {
activity : 2,
locker_id : this.locker.id || 0,
locker_box_type_id : null,
}
},
archiveModel_(item){
let payload = {
id : item.id
}
this.$api.archiveLockerBox(payload).then((res) => {
this.initialize_();
this.$toast.success(res.data.message)
}).catch((err) => {
this.errorHandler_(err)
})
},
getResourceData_(){
let payload = {
...this.setPagination_(),
...this.search_,
...this.filters_,
...this.sort_,
}
this.model_loading_ = true
this.$api.getLockerBoxList(payload).then((res)=>{
let { data, total } = res.data.result
this.resourceDataSet_ = data
this.totalData_ = total
}).catch((err)=>{
this.errorHandler_(err)
}).finally(()=>{
this.model_loading_ = false
})
},
menu_items(item){
return [
// {
// icon: "mdi-eye", title: "View More",
// action: ()=>{ this.viewMore_(item) }
// },
{
icon: "mdi-square-edit-outline", title: "Edit",
action: () => { this.editItem_(item) }
},
{
icon: "mdi-open-in-app", title: "Open Box", icon_class: "mdi-rotate-90",
action: () => { this.confirmOpenBox({
id: item.id,
locker_id: item.locker_id
});}
},
{
icon: (item.deleted_at ? "mdi-delete-off" : "mdi-delete"),
title: (item.deleted_at ? "Activate" : "Deactivate"),
icon_class: "red--text",
title_class: "red--text",
action: () => { this.archiveModel_(item) }
},
]
},
action_btn_group_items(){
return [
{
icon: "mdi-refresh",
disabled: this.model_loading_,
action: () => { this.searchData_();this.emitIntialize() }
},
{
icon: "mdi-filter-outline",
action: () => { this.filter_dialog = true }
},
]
},
setupFilterBar(){
let available_box_types = this.available_box_types.map((item)=>{
return {
value: item.id,
text: item.title,
subtext: item.dimension_text
}
})
this.filter_options = [
{
cols: 12,
model: "locker_box_type_id",
label: "Box Type",
items: [ { value: null, text: "All" }, ...available_box_types ],
},
{
cols: 12,
model: "activity",
label: "Activity",
items: this.options_.activity,
},
]
},
async confirmOpenBox(item){
let text = `<div class="pt-2">
<div class="mb-2 font-weight-bold">Are you sure to continue?</div>
<div class="caption font-italic">
All Locker's Compartment will be opened. Please get staff <strong>READY</strong> before proceed.
</div>
</div>`
if(item.id != '00')
text = `<div class="pt-2">
<div class="mb-2 font-weight-bold">Are you sure to continue?</div>
<div class="caption font-italic">
This locker's box will be opened. Please get staff <strong>READY</strong> before proceed.
</div>
</div>`
const res = await this.$dialog.confirm({
color: 'red',
text: text,
title: 'Warning'
})
if(res){
this.openLockerBox(item)
}
},
async confirmCloseBox(item){
let text = `<div class="pt-2">
<div class="mb-2 font-weight-bold">Are you sure to continue?</div>
<div class="caption font-italic">
All Locker's Compartment will be treated as closed, but this does not mean the locker boxes are ACTUALLY CLOSED.
</div>
</div>`
if(item.id != '00')
text = `<div class="pt-2">
<div class="mb-2 font-weight-bold">Are you sure to continue?</div>
<div class="caption font-italic">
This locker's box will be treated as close, but this does not mean the locker box is ACTUALLY CLOSED.
</div>
</div>`
const res = await this.$dialog.confirm({
color: 'red',
text: text,
title: 'Warning'
})
if(res){
this.closeLockerBox(item)
}
},
async confirmRestartLocker(item){
let text = `<div class="pt-2">
<div class="mb-2 font-weight-bold">Are you sure to continue?</div>
<div class="caption font-italic">
The locker app will be restarted after you have confirm the action. Are you sure?
</div>
</div>`
const res = await this.$dialog.confirm({
color: 'red',
text: text,
title: 'Warning'
})
if(res){
this.restartLocker(item)
}
},
async confirmSyncLocker(item){
let text = `<div class="pt-2">
<div class="mb-2 font-weight-bold">Are you sure to continue?</div>
<div class="caption font-italic">
Backend will synchronize with this locker after you have confirm the action. Are you sure?
</div>
</div>`
const res = await this.$dialog.confirm({
color: 'red',
text: text,
title: 'Warning'
})
if(res){
this.syncLocker(item)
}
},
openLockerBox(item){
let payload = {
id: item.id,
locker_id : item.locker_id,
}
this.$api.openLockerBox(payload).then(()=>{
this.emitIntialize()
}).catch((err)=>{
this.errorHandler_(err)
})
},
closeLockerBox(item){
let payload = {
id: item.id,
locker_id : item.locker_id,
}
this.$api.closeLockerBox(payload).then(()=>{
this.emitIntialize()
}).catch((err)=>{
this.errorHandler_(err)
})
},
restartLocker(item){
let payload = {
id : item.id
}
this.$api.restartLocker(payload).then((res) => {
this.initialize_();
this.$toast.success(res.data.result)
}).catch((err) => {
this.errorHandler_(err)
})
},
syncLocker(item){
let payload = {
id : item.id,
}
this.$api.syncLocker(payload).then((res)=>{
this.initialize_();
this.$toast.success(res.data.result)
}).catch((err)=>{
this.errorHandler_(err)
})
},
initTableHeader()
{
this.table_headers = [
{ text: '#', value: 'id' },
{ text: 'Box No.', value: 'box_no' },
{ text: 'Type', value: 'box_type' },
{ text: 'Status', value: 'status', align: 'center' },
// { text: 'Door Open', value: 'is_open', align: 'center' },
// { text: 'Under Booking', value: 'is_in_use', align: 'center' },
// { text: 'Ready to Book', value: 'is_available', align: 'center' },
]
if(this.$authUser.isAdmin())
{
this.table_headers = [
...this.table_headers,
{ text: 'Actions', value: 'action', class: 'text-center' },
]
}
}
}
}
</script>