Subscriptions 70% done
This commit is contained in:
parent
2fee1d2ae1
commit
22457bcd79
|
|
@ -1,6 +1,7 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
/TEMP
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<template #button-content>
|
||||
<div class="d-sm-flex d-none user-nav">
|
||||
<p class="user-name font-weight-bolder mb-0">
|
||||
{{ `${userData.first_name} ${userData.last_name}` }}
|
||||
{{ `${userData.first_name} ${userData.last_name}` }}
|
||||
</p>
|
||||
<span class="user-status">{{ userData.role }}</span>
|
||||
</div>
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
<span>Chat</span>
|
||||
</b-dropdown-item> -->
|
||||
|
||||
<b-dropdown-divider />
|
||||
<!-- <b-dropdown-divider /> -->
|
||||
|
||||
<!-- <b-dropdown-item
|
||||
:to="{ name: 'pages-account-setting' }"
|
||||
|
|
@ -119,7 +119,6 @@ import { initialAbility } from '@/libs/acl/config'
|
|||
import useJwt from '@/auth/jwt/useJwt'
|
||||
import { avatarText } from '@core/utils/filter'
|
||||
import { getUserData, logout } from '@/auth/utils'
|
||||
import { Log } from '@/plugins/core'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,17 @@ export const url = extend('url', {
|
|||
message: 'URL is invalid',
|
||||
})
|
||||
|
||||
export const endDate = extend('end-date', {
|
||||
params: ['startDate'],
|
||||
validate(value, { target }) {
|
||||
console.log('validate value', value)
|
||||
console.log('validate target', target)
|
||||
// const StartDate = new Date(value)
|
||||
return true
|
||||
},
|
||||
message: '{_field_} must be before {_target_}.'
|
||||
})
|
||||
|
||||
//==============================================================================
|
||||
// Localization
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// ================================================================================================
|
||||
// ? TIP: It is recommended to use this file for overriding bootstrap variables.
|
||||
// ================================================================================================
|
||||
// ============================================================================
|
||||
// ? TIP: It is recommended to use this file for overriding bootstrap
|
||||
// variables.
|
||||
// ============================================================================
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
<!--
|
||||
CONFIRM MODAL
|
||||
A MODAL THAT ALLOWS THE USER TO CONFIRM OR CANCEL AN OPERATION.
|
||||
|
||||
HOW TO USE:
|
||||
PUT THE COMPONENT IN THE TEMPLATE SECTION, AND THEN USE VB-MODAL BOOTSTRAP-VUE
|
||||
COMPONENT AND PASS IT modal-error ARGUMENT TO OPEN THE MODAL.
|
||||
THE COMPONENT IS GLOBALLY IMPORTED.
|
||||
|
||||
EXAMPLE:
|
||||
<b-button v-b-modal:modal-error>Add New User</b-button>
|
||||
<ConfirmModal />
|
||||
|
||||
-->
|
||||
|
||||
<template>
|
||||
<b-modal
|
||||
id="confirm-modal"
|
||||
v-bind:centered="true"
|
||||
size="xs"
|
||||
v-bind:title="title"
|
||||
ok-title="Delete"
|
||||
ok-variant="danger"
|
||||
v-on:cancel="OnConfirm('cancel')"
|
||||
v-on:ok="OnConfirm('ok')"
|
||||
>
|
||||
<div class="d-flex flex-column justify-content-between align-items-center" style="row-gap: 1rem;">
|
||||
<h5 v-if="message !== ''" class="text-center">{{ message }}</h5>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ConfirmModal',
|
||||
|
||||
props: {
|
||||
message: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'Confirm',
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
OnConfirm(Value)
|
||||
{
|
||||
this.$emit('confirm', Value)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<!--
|
||||
Documentation:
|
||||
ERROR MODAL
|
||||
|
||||
Description:
|
||||
A modal that indicates some operation has been failed
|
||||
A modal that indicates some operation has been failed.
|
||||
|
||||
How to use:
|
||||
First, import the component, put it in the template section, and then use
|
||||
|
|
@ -10,7 +10,7 @@ VBModal bootstrap-vue component and pass it modal-error argument to open the
|
|||
modal.
|
||||
|
||||
Example:
|
||||
<b-button v-b-modal:modal-error>Add New User</b-button>
|
||||
<b-button v-b-modal:error-modal>Add New User</b-button>
|
||||
|
||||
Props:
|
||||
Name Type Description
|
||||
|
|
@ -21,7 +21,7 @@ message String A message to be displayed to the user
|
|||
|
||||
<template>
|
||||
<b-modal
|
||||
id="modal-error"
|
||||
id="error-modal"
|
||||
v-bind:centered="true"
|
||||
size="xs"
|
||||
ok-only
|
||||
|
|
@ -33,14 +33,14 @@ message String A message to be displayed to the user
|
|||
<polyline style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-miterlimit:10;" points="16,34 25,25 34,16"/>
|
||||
<polyline style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-miterlimit:10;" points="16,16 25,25 34,34"/><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g>
|
||||
</svg>
|
||||
<h5 v-if="message !== ''">{{ message }}</h5>
|
||||
<h5 v-if="message !== ''" class="text-center">{{ message }}</h5>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AddUserModalComponent',
|
||||
name: 'ErrorModal',
|
||||
|
||||
props: {
|
||||
message: {
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
<!--
|
||||
Documentation:
|
||||
SUCCESS MODAL
|
||||
|
||||
Description:
|
||||
A modal that indicates some operation has been successful
|
||||
|
||||
How to use:
|
||||
First, import the component, put it in the template section, and then use
|
||||
VBModal bootstrap-vue component and pass it modal-success argument to open the
|
||||
VBModal bootstrap-vue component and pass it success-modal argument to open the
|
||||
modal.
|
||||
|
||||
Example:
|
||||
|
|
@ -21,7 +21,7 @@ message String A message to be displayed to the user
|
|||
|
||||
<template>
|
||||
<b-modal
|
||||
id="modal-success"
|
||||
id="success-modal"
|
||||
v-bind:centered="true"
|
||||
size="xs"
|
||||
ok-only
|
||||
|
|
@ -32,14 +32,14 @@ message String A message to be displayed to the user
|
|||
<circle style="fill:#25ae88;" cx="25" cy="25" r="25"/>
|
||||
<polyline style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" points="38,15 22,33 12,25 "/><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g>
|
||||
</svg>
|
||||
<h5 v-if="message !== ''">{{ message }}</h5>
|
||||
<h5 v-if="message !== ''" class="text-center">{{ message }}</h5>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AddUserModalComponent',
|
||||
name: 'SuccessModal',
|
||||
|
||||
props: {
|
||||
message: {
|
||||
|
|
@ -45,8 +45,8 @@ table-ref ? a reference to the table engine which must be refershed e.g
|
|||
|
||||
<script>
|
||||
import { BFormInput } from 'bootstrap-vue'
|
||||
import SuccessModal from '@/components/ui/SuccessModal.vue'
|
||||
import ErrorModal from '@/components/ui/ErrorModal.vue'
|
||||
import SuccessModal from '@/components/modals/SuccessModal.vue'
|
||||
import ErrorModal from '@/components/modals/ErrorModal.vue'
|
||||
import FullPageLoadingComponent from '@/components/ui/FullPageLoadingComponent.vue'
|
||||
import axios from '@/axios'
|
||||
import { Log } from '@/modules/log'
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
<!--
|
||||
CONFIRM MODAL
|
||||
|
||||
DESCRIPTION:
|
||||
A MODAL THAT ALLOWS THE USER TO CONFIRM OR CANCEL AN OPERATION.
|
||||
|
||||
HOW TO USE:
|
||||
First, import the component, put it in the template section, and then use
|
||||
VBModal bootstrap-vue component and pass it modal-error argument to open the
|
||||
modal.
|
||||
|
||||
EXAMPLE:
|
||||
<b-button v-b-modal:modal-error>Add New User</b-button>
|
||||
<ConfirmModal />
|
||||
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ConfirmModalComponent'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
|
@ -33,6 +33,7 @@ EVENTS:
|
|||
v-bind:label-for="name"
|
||||
v-bind:label-class="labelClass"
|
||||
v-bind:description="description"
|
||||
v-bind:class="{ 'mb-0': description.trim() !== '' }"
|
||||
>
|
||||
<b-form-datepicker
|
||||
v-bind:class="{ 'is-invalid': errors.length > 0 }"
|
||||
|
|
@ -41,8 +42,12 @@ EVENTS:
|
|||
v-on:input="$emit('input', MutableValue_D)"
|
||||
v-bind:readonly="readonly"
|
||||
/>
|
||||
<small class="text-danger" style="white-space: pre;"> {{ errors[0] }}</small>
|
||||
<small v-if="description.trim() === ''" class="text-danger" style="white-space: pre;"> {{ errors[0] }}</small>
|
||||
</b-form-group>
|
||||
<small v-if="description.trim() !== ''" class="text-danger d-block mb-1">
|
||||
<span v-if="errors.length === 0"> </span>
|
||||
{{ errors[0] }}
|
||||
</small>
|
||||
</ValidationProvider>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
<!--
|
||||
DROPDOWN
|
||||
|
||||
DESCRIPTION:
|
||||
ALLOWS SELECTING ONE OF THE PROVIDED OPTIONS, WITH ATTACHED VALIDATION.
|
||||
|
||||
PROPS:
|
||||
-------
|
||||
| Property Name | Type | Default Value | Description |
|
||||
|-----------------|---------|---------------|--------------------------------------------------------------------------|
|
||||
|
||||
EVENTS:
|
||||
--------
|
||||
| Event Name | Description |
|
||||
|------------|--------------------------------|
|
||||
| input | invoked when the input changes |
|
||||
|
||||
-->
|
||||
|
||||
<template>
|
||||
<ValidationProvider v-bind:name="name" v-bind:rules="Rules" v-slot="{ errors }">
|
||||
<b-form-group
|
||||
v-bind:label="label"
|
||||
v-bind:label-for="name"
|
||||
v-bind:label-class="labelClass"
|
||||
v-bind:description="description"
|
||||
v-bind:class="{ 'mb-0': description.trim() !== '' }"
|
||||
>
|
||||
<v-select
|
||||
v-model="MutableValue_D"
|
||||
v-on:input="$emit('input', MutableValue_D)"
|
||||
v-bind:class="{ 'is-invalid': errors.length > 0 }"
|
||||
v-bind:options="options"
|
||||
v-bind:placeholder="placeholder"
|
||||
label="title"
|
||||
v-bind:clearable="false"
|
||||
/>
|
||||
<small v-if="description.trim() === ''" class="text-danger" style="white-space: pre;"> {{ errors[0] }}</small>
|
||||
</b-form-group>
|
||||
<small v-if="description.trim() !== ''" class="text-danger d-block mb-1">
|
||||
<span v-if="errors.length === 0"> </span>
|
||||
{{ errors[0] }}
|
||||
</small>
|
||||
</ValidationProvider>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BFormGroup } from 'bootstrap-vue'
|
||||
import vSelect from 'vue-select'
|
||||
import { required, email, numeric } from '@validations'
|
||||
|
||||
export default {
|
||||
name: 'DropdownComponent',
|
||||
|
||||
props: {
|
||||
// NOTE(pooya): `name` is checked by vee-validate so make sure it's
|
||||
// provided inside @/libs/i18n/vee-validate-locales in the fields
|
||||
// property.
|
||||
|
||||
value: { type: String , required: false , default: '' },
|
||||
rules: { type: String , required: false , default: '' },
|
||||
notRequired: { type: Boolean , required: false , default: false },
|
||||
noValidation: { type: Boolean , required: false , default: false },
|
||||
label: { type: String , required: false , default: '' },
|
||||
labelClass: { type: String , required: false , default: '' },
|
||||
description: { type: String , required: false , default: '' },
|
||||
placeholder: { type: String , required: false , default: '' },
|
||||
name: { type: String , required: false , default: '' },
|
||||
|
||||
// Must be an array value-title objects. For example:
|
||||
// [ {value:0, title: 'Diomand'}, {value:1, title: 'Bronze'} ]
|
||||
options: { type: Array , required: false , default: () => [] },
|
||||
},
|
||||
|
||||
components: {
|
||||
BFormGroup,
|
||||
|
||||
// Vue Select documentation:
|
||||
// https://vue-select.org/api/props.html#appendtobody
|
||||
vSelect,
|
||||
},
|
||||
|
||||
data()
|
||||
{
|
||||
return {
|
||||
MutableValue_D: this.value,
|
||||
|
||||
// validations rules
|
||||
required,
|
||||
email,
|
||||
numeric,
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(NewValue, OldValue)
|
||||
{
|
||||
this.MutableValue_D = NewValue
|
||||
|
||||
// ❓(pooya): Should I emit an input event when the v-model
|
||||
// is changed from the parent component or not?
|
||||
// It logically doesn't make sense but will it lead to bugs?
|
||||
//
|
||||
// this.$emit('input', NewValue)
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
Rules()
|
||||
{
|
||||
if( this.noValidation )
|
||||
return ''
|
||||
|
||||
if( this.notRequired )
|
||||
return (this.rules.trim()) ? `${this.rules}` : ''
|
||||
else
|
||||
return (this.rules.trim()) ? `required|${this.rules}` : 'required'
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -36,6 +36,7 @@ EVENTS:
|
|||
v-bind:label-for="name"
|
||||
v-bind:label-class="labelClass"
|
||||
v-bind:description="description"
|
||||
v-bind:class="{ 'mb-0': description.trim() !== '' }"
|
||||
>
|
||||
<b-form-textarea
|
||||
v-if="multiline"
|
||||
|
|
@ -59,8 +60,12 @@ EVENTS:
|
|||
v-on:input="$emit('input', MutableValue_D)"
|
||||
v-bind:readonly="readonly"
|
||||
/>
|
||||
<small class="text-danger" style="white-space: pre;"> {{ errors[0] }}</small>
|
||||
<small v-if="description.trim() === ''" class="text-danger" style="white-space: pre;"> {{ errors[0] }}</small>
|
||||
</b-form-group>
|
||||
<small v-if="description.trim() !== ''" class="text-danger d-block mb-1">
|
||||
<span v-if="errors.length === 0"> </span>
|
||||
{{ errors[0] }}
|
||||
</small>
|
||||
</ValidationProvider>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -72,85 +72,79 @@
|
|||
|
||||
|
||||
<a-table
|
||||
@change="change"
|
||||
:indentSize="5"
|
||||
:pagination="false"
|
||||
ref="tbl"
|
||||
:locale="locale"
|
||||
:columns="visibleCols"
|
||||
:data-source="data"
|
||||
:row-selection="options.is_row_selection ? { selectedRowKeys: selectedRowKeys, onChange: onChange } : null"
|
||||
@change="change"
|
||||
:indentSize="5"
|
||||
:pagination="false"
|
||||
ref="tbl"
|
||||
:locale="locale"
|
||||
:columns="visibleCols"
|
||||
:data-source="data"
|
||||
:row-selection="options.is_row_selection ? { selectedRowKeys: selectedRowKeys, onChange: onChange } : null"
|
||||
>
|
||||
<template :slot="item" slot-scope="name, record, index" v-for="(item,ind) in customRender">
|
||||
<slot :name="item" :text="name" :record="record" :index="index"></slot>
|
||||
</template>
|
||||
|
||||
<template :slot="item" slot-scope="name, record, index" v-for="(item,ind) in customRender">
|
||||
<slot :name="item" :text="name" :record="record" :index="index"/>
|
||||
</template>
|
||||
<!-- <template slot="expandedRowRender" slot-scope="text, record, index">-->
|
||||
<!-- <slot name="expandedRowRender" :text="text" :record="record" :index="index"/>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- <template slot="expandedRowRender" slot-scope="text, record, index">-->
|
||||
<!-- <slot name="expandedRowRender" :text="text" :record="record" :index="index"/>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<div slot="footer" slot-scope="{item}">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-1">
|
||||
<div v-if="query.total">
|
||||
<span>{{query.total}}</span>
|
||||
Record found.
|
||||
</div>
|
||||
</div>
|
||||
<APagination
|
||||
v-if="is_pagenation"
|
||||
show-size-changer
|
||||
:pageSizeOptions="['5','10','20']"
|
||||
:page-size.sync="query.limit"
|
||||
@change="changePage"
|
||||
@showSizeChange="changePage"
|
||||
:default-current="1" :total="query.total" v-model.sync="query.page">
|
||||
<template slot="buildOptionText" slot-scope="props">
|
||||
<div dir="rtl">
|
||||
<span> {{ props.value }} </span>
|
||||
<span>record</span>
|
||||
</div>
|
||||
</template>
|
||||
</APagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-for="item,index in getColsFilter" :slot="item.scopedSlots.filterDropdown"
|
||||
slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }">
|
||||
<div>
|
||||
|
||||
<TextXTableFilter v-if="item.filterType === 'default'"
|
||||
:column="column"
|
||||
@search="submitFilter"
|
||||
/>
|
||||
|
||||
<SwitchXTableFilter v-if="item.filterType === 'switch'"
|
||||
:column="column"
|
||||
@search="submitFilter"
|
||||
/>
|
||||
|
||||
<NumberXTableFilter v-if="item.filterType === 'number'"
|
||||
:column="column"
|
||||
@search="submitFilter"
|
||||
/>
|
||||
|
||||
<SelectOptionXTableFilter v-if="item.filterType === 'select'" :column="item"
|
||||
:set-selected-keys="setSelectedKeys" :selected-keys="selectedKeys"
|
||||
:confirm="confirm" :clear-filters="clearFilters"/>
|
||||
|
||||
|
||||
<DateXTableFilter v-if="item.filterType === 'date'"
|
||||
:column="column"
|
||||
@search="submitFilter"
|
||||
/>
|
||||
|
||||
|
||||
</div>
|
||||
<a-icon :slot="item.scopedSlots.filterIcon" slot-scope="filtered" type="search"
|
||||
:style="{ color: filtered ? '#108ee9' : undefined }"/>
|
||||
</div>
|
||||
<div slot="footer" slot-scope="{item}">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-1">
|
||||
<div v-if="query.total">
|
||||
<span>{{query.total}}</span>
|
||||
Record found.
|
||||
</div>
|
||||
</div>
|
||||
<APagination
|
||||
v-if="is_pagenation"
|
||||
show-size-changer
|
||||
:pageSizeOptions="['5','10','20']"
|
||||
:page-size.sync="query.limit"
|
||||
@change="changePage"
|
||||
@showSizeChange="changePage"
|
||||
:default-current="1"
|
||||
:total="query.total"
|
||||
v-model.sync="query.page"
|
||||
>
|
||||
<template slot="buildOptionText" slot-scope="props">
|
||||
<div dir="rtl">
|
||||
<span> {{ props.value }} </span>
|
||||
<span>record</span>
|
||||
</div>
|
||||
</template>
|
||||
</APagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-for="item,index in getColsFilter" :slot="item.scopedSlots.filterDropdown"
|
||||
slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }">
|
||||
<div>
|
||||
<TextXTableFilter v-if="item.filterType === 'default'"
|
||||
:column="column"
|
||||
@search="submitFilter"
|
||||
/>
|
||||
<SwitchXTableFilter v-if="item.filterType === 'switch'"
|
||||
:column="column"
|
||||
@search="submitFilter"
|
||||
/>
|
||||
<NumberXTableFilter v-if="item.filterType === 'number'"
|
||||
:column="column"
|
||||
@search="submitFilter"
|
||||
/>
|
||||
<SelectOptionXTableFilter v-if="item.filterType === 'select'" :column="item"
|
||||
:set-selected-keys="setSelectedKeys" :selected-keys="selectedKeys"
|
||||
:confirm="confirm" :clear-filters="clearFilters"
|
||||
/>
|
||||
<DateXTableFilter v-if="item.filterType === 'date'"
|
||||
:column="column"
|
||||
@search="submitFilter"
|
||||
/>
|
||||
</div>
|
||||
<a-icon :slot="item.scopedSlots.filterIcon" slot-scope="filtered" type="search"
|
||||
:style="{ color: filtered ? '#108ee9' : undefined }"/>
|
||||
</div>
|
||||
</a-table>
|
||||
</ASpin>
|
||||
</ACard>
|
||||
|
|
@ -169,7 +163,6 @@ import {openFullscreen, closeFullscreen} from "@/plugins/fullscreen";
|
|||
import NumberXTableFilter from "./NumberXTableFilter";
|
||||
import { BRow, BCol, BInputGroup, BInputGroupAppend, BFormInput, BFormCheckbox, BButton } from 'bootstrap-vue'
|
||||
|
||||
|
||||
const list = [
|
||||
{
|
||||
title: 'emails',
|
||||
|
|
@ -293,23 +286,30 @@ export default {
|
|||
return this.query;
|
||||
},
|
||||
|
||||
refresh($event){
|
||||
refresh ($event)
|
||||
{
|
||||
this.$emit('refresh')
|
||||
this.query.query = []
|
||||
this.query.search = undefined
|
||||
this.fetch()
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
async fetch()
|
||||
{
|
||||
try {
|
||||
this.loading = true;
|
||||
if(this.method == "post"){
|
||||
const {data: {rows, query}} = await axios.post(this.model.url, {...this.requestData()});
|
||||
const {data: {rows, query}} = await axios.post(this.model.url, {
|
||||
...this.requestData(),
|
||||
te: {
|
||||
p: { c: 1, s: 10 }
|
||||
}
|
||||
});
|
||||
this.data = rows;
|
||||
this.query.page = query.page
|
||||
this.query.limit = query.limit;
|
||||
this.query.total = query.total;
|
||||
this.query.max_page = query.max_page;
|
||||
// this.query.page = query.page
|
||||
// this.query.limit = query.limit;
|
||||
// this.query.total = query.total;
|
||||
// this.query.max_page = query.max_page;
|
||||
this.$emit('rows',rows)
|
||||
}else{
|
||||
const {data} = await axios.get(this.model.url);
|
||||
|
|
|
|||
|
|
@ -1,19 +1,26 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
import FeatherIcon from '@core/components/feather-icon/FeatherIcon.vue'
|
||||
import { ValidationObserver, ValidationProvider } from 'vee-validate'
|
||||
import Textbox from '@/components/ui/Textbox.vue'
|
||||
import Checkbox from '@/components/ui/Checkbox.vue'
|
||||
import Datepicker from '@/components/ui/Datepicker.vue'
|
||||
import ConfirmModal from '@/components/ui/ConfirmModal.vue'
|
||||
import Dropdown from '@/components/ui/Dropdown.vue'
|
||||
import ConfirmModal from '@/components/modals/ConfirmModal.vue'
|
||||
import SuccessModal from '@/components/modals/SuccessModal.vue'
|
||||
import ErrorModal from '@/components/modals/ErrorModal.vue'
|
||||
import FullpageLoadingComponent from '@/components/ui/FullPageLoadingComponent.vue'
|
||||
|
||||
// Form Components
|
||||
Vue.component(Textbox.name, Textbox)
|
||||
Vue.component(Checkbox.name, Checkbox)
|
||||
Vue.component(Datepicker.name, Datepicker)
|
||||
Vue.component(Dropdown.name, Dropdown)
|
||||
|
||||
// Modals
|
||||
// Modals/Dialogs
|
||||
Vue.component(ConfirmModal.name, ConfirmModal)
|
||||
Vue.component(SuccessModal.name, SuccessModal)
|
||||
Vue.component(ErrorModal.name, ErrorModal)
|
||||
|
||||
// Validation
|
||||
Vue.component('ValidationObserver', ValidationObserver)
|
||||
|
|
|
|||
|
|
@ -2,10 +2,24 @@
|
|||
"fields": {
|
||||
"title": "Title",
|
||||
"storage_limit": "Storage Limit",
|
||||
"storage_usage": "Storage Usage",
|
||||
"description": "Description",
|
||||
"from_date": "Beginning Date",
|
||||
"from_date": "Starting Date",
|
||||
"to_date": "Ending Date",
|
||||
"is_active": "Active"
|
||||
"months": "Months",
|
||||
"is_active": "Active",
|
||||
"price": "Price",
|
||||
"discounted_price": "Price",
|
||||
"total_price": "Price",
|
||||
"value": "Value",
|
||||
"rule_type": "Rule Type",
|
||||
"amount": "Amount",
|
||||
"payment_dead_line": "Payment Deadline",
|
||||
"allowed_delay_days": "Allowed Delay Days",
|
||||
"installments_count": "Installments Count",
|
||||
"payable_amount": "Payable Amount",
|
||||
"payed_amount": "Payed Amount",
|
||||
"user_limit": "User Limit"
|
||||
},
|
||||
"message": {
|
||||
"title": "Card Title",
|
||||
|
|
@ -31,7 +45,13 @@
|
|||
"Add Law Firm": "Add Law Firm",
|
||||
"Law Firm Reports": "Law Firm Reports",
|
||||
"Subscriptions": "Subscriptions",
|
||||
"Subscription Plans": "Subscription Plans",
|
||||
"Subscription Plans": "Plans",
|
||||
"Subscription Contracts": "Contracts",
|
||||
"Subscription Rules": "Rules",
|
||||
"Subscription Subscriptions": "Subscriptions",
|
||||
"Subscription Transactions": "Transactions",
|
||||
"Subscription Payments": "Payments",
|
||||
"Subscription Contract Users": "Contract Users",
|
||||
|
||||
"Users": "Users",
|
||||
"Users List": "Users List",
|
||||
|
|
|
|||
|
|
@ -4,8 +4,12 @@
|
|||
* *
|
||||
* Table of Contents: *
|
||||
* - Number Thousand Separator *
|
||||
* - Format Bytes *
|
||||
* - Logging *
|
||||
*******************************************************************************/
|
||||
* - Sleep *
|
||||
* - View In Fullscreen *
|
||||
* - Close Fullscreen *
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
@ -59,7 +63,67 @@ export function FormatBytes(Bytes, Decimals = 2)
|
|||
*/
|
||||
export function Log(Message, Data = '')
|
||||
{
|
||||
console.log(`%c ${Message} `, 'background:black; color:#bada55; font-family:"PxPlus ToshibaSat 9x16"; font-size: 13px;')
|
||||
console.log(`%c ${Message.toUpperCase()} `, 'background:black; color:#bada55; font-family:"PxPlus ToshibaSat 9x16"; font-size: 13px; border-radius: 4px; padding: 1px 3px;')
|
||||
if( Data !== '' )
|
||||
console.log(Data)
|
||||
}
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
| Sleep
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
||||
| Suspends execution for an specified number of milliseconds.
|
||||
|
|
||||
| Usage Example:
|
||||
|
|
||||
| await Sleep(1000) // sleep for 1 second
|
||||
|
|
||||
|
|
||||
| Reference:stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep/39914235#39914235
|
||||
|
|
||||
*/
|
||||
export function Sleep(Milliseconds)
|
||||
{
|
||||
return new Promise(Resolve => setTimeout(Resolve, Milliseconds))
|
||||
}
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
| View In Fullscreen
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
||||
| Renders the specified HTML element in fullscreen.
|
||||
|
|
||||
*/
|
||||
export function OpenFullscreen(Element)
|
||||
{
|
||||
if( Element.requestFullscreen )
|
||||
Element.requestFullscreen()
|
||||
else if( Element.mozRequestFullScreen ) /* Firefox */
|
||||
Element.mozRequestFullScreen()
|
||||
else if( Element.webkitRequestFullscreen ) /* Chrome, Safari and Opera */
|
||||
Element.webkitRequestFullscreen()
|
||||
else if( Element.msRequestFullscreen ) /* IE/Edge */
|
||||
Element.msRequestFullscreen()
|
||||
}
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
| Close Fullscreen
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
||||
| Closes fullscreen view if it's already open.
|
||||
|
|
||||
*/
|
||||
export function closeFullscreen()
|
||||
{
|
||||
if( document.exitFullscreen )
|
||||
document.exitFullscreen()
|
||||
else if( document.mozCancelFullScreen ) /* Firefox */
|
||||
document.mozCancelFullScreen()
|
||||
else if( document.webkitExitFullscreen ) /* Chrome, Safari and Opera */
|
||||
document.webkitExitFullscreen()
|
||||
else if( document.msExitFullscreen ) /* IE/Edge */
|
||||
document.msExitFullscreen()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,30 @@ export default [
|
|||
title: 'Subscription Plans',
|
||||
route: 'subscription-plans',
|
||||
},
|
||||
{
|
||||
title: 'Subscription Contracts',
|
||||
route: 'subscription-contracts',
|
||||
},
|
||||
{
|
||||
title: 'Subscription Rules',
|
||||
route: 'subscription-rules',
|
||||
},
|
||||
{
|
||||
title: 'Subscription Subscriptions',
|
||||
route: 'subscription-subscriptions',
|
||||
},
|
||||
{
|
||||
title: 'Subscription Transactions',
|
||||
route: 'subscription-transactions',
|
||||
},
|
||||
{
|
||||
title: 'Subscription Payments',
|
||||
route: 'subscription-payments',
|
||||
},
|
||||
// {
|
||||
// title: 'Subscription Contract Users',
|
||||
// route: 'subscription-contractusers',
|
||||
// },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Core *
|
||||
* Contains various javascript utilities. *
|
||||
* *
|
||||
* Table of Contents: *
|
||||
* - Number Thousand Separator *
|
||||
* - Format Bytes *
|
||||
* - Logging *
|
||||
* - Is Number *
|
||||
* - Sleep *
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
| Number Thousand Separator
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
||||
| A function which takes a number and a character and returns a string
|
||||
| containing that number with the given character as thousands
|
||||
| separators.
|
||||
|
|
||||
*/
|
||||
export function SeparateNumberByThousands(Num, Separator = ',')
|
||||
{
|
||||
return Num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, Separator)
|
||||
|
||||
// P.S: Thanks Github Copilot for saving me numerous hours of stackoverflowing 🙂
|
||||
}
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
| Format Bytes
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
||||
| Converts bytes to the equivalent kilobytes, megabytes, gigabytes, etc.
|
||||
|
|
||||
*/
|
||||
export function FormatBytes(Bytes, Decimals = 2)
|
||||
{
|
||||
if( Bytes === 0 ) return '0 Bytes'
|
||||
|
||||
const K = 1024
|
||||
const Dm = (Decimals < 0) ? 0 : Decimals
|
||||
const Sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
|
||||
const I = Math.floor(Math.log(Bytes) / Math.log(K))
|
||||
|
||||
return parseFloat((Bytes / Math.pow(K, I)).toFixed(Dm)) + ' ' + Sizes[I]
|
||||
}
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
| Logging
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
||||
| Logs a message to the browser console.
|
||||
| This function is provided to abstract all your logging calls, so you
|
||||
| can change the style of all of them at once. It is useful to make the
|
||||
| logs of your application look different so you can find them easier
|
||||
| when there are hundreds of logs in the console.
|
||||
|
|
||||
*/
|
||||
export function Log(Message, Data = '')
|
||||
{
|
||||
console.log(
|
||||
`%c ${Message.toUpperCase()} `,
|
||||
'background:black; color:#bada55; font-family:"PxPlus ToshibaSat 9x16"; font-size: 13px; border-radius: 4px; padding: 1px 3px;')
|
||||
if( Data !== '' )
|
||||
console.log(Data)
|
||||
}
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
| Is Number
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
||||
| Takes a string and determines whether it is a valid number or not.
|
||||
| This function shields against common bugs like whitespace, implicit
|
||||
| partial parsing, radix, coercion of arrays, etc.
|
||||
|
|
||||
| Reference: stackoverflow.com/questions/175739/how-can-i-check-if-a-string-is-a-valid-number
|
||||
|
|
||||
*/
|
||||
export function IsNumber(TheString)
|
||||
{
|
||||
if( typeof str != "string" ) return false // we only process strings!
|
||||
return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
|
||||
!isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
|
||||
}
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------
|
||||
| Sleep
|
||||
|-----------------------------------------------------------------------
|
||||
|
|
||||
| Hangs execution for the specified milliseconds.
|
||||
|
|
||||
| Reference: stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep/39914235#39914235
|
||||
|
|
||||
*/
|
||||
export async function Sleep(Milliseconds)
|
||||
{
|
||||
await new Promise(r => setTimeout(r, Milliseconds))
|
||||
}
|
||||
|
|
@ -138,6 +138,36 @@ export default [
|
|||
{
|
||||
path: '/subscriptions/plans',
|
||||
name: 'subscription-plans',
|
||||
component: () => import('@/views/Subscriptions/PlansList.vue'),
|
||||
component: () => import('@/views/Subscriptions/Plans.vue'),
|
||||
},
|
||||
{
|
||||
path: '/subscriptions/contracts',
|
||||
name: 'subscription-contracts',
|
||||
component: () => import('@/views/Subscriptions/Contracts.vue'),
|
||||
},
|
||||
{
|
||||
path: '/subscriptions/rules',
|
||||
name: 'subscription-rules',
|
||||
component: () => import('@/views/Subscriptions/Rules.vue'),
|
||||
},
|
||||
{
|
||||
path: '/subscriptions/subscriptions',
|
||||
name: 'subscription-subscriptions',
|
||||
component: () => import('@/views/Subscriptions/Subscriptions.vue'),
|
||||
},
|
||||
{
|
||||
path: '/subscriptions/transactions',
|
||||
name: 'subscription-transactions',
|
||||
component: () => import('@/views/Subscriptions/Transactions.vue'),
|
||||
},
|
||||
{
|
||||
path: '/subscriptions/payments',
|
||||
name: 'subscription-payments',
|
||||
component: () => import('@/views/Subscriptions/Payments.vue'),
|
||||
},
|
||||
{
|
||||
path: '/subscriptions/contract-users',
|
||||
name: 'subscription-contractusers',
|
||||
component: () => import('@/views/Subscriptions/ContractUsers.vue'),
|
||||
},
|
||||
]
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
<template>
|
||||
<!-- <div v-bind:class="{ 'page--main': Model_D === null }"> -->
|
||||
<div class="page--main">
|
||||
<FullpageLoadingComponent v-bind:show="Loading_D" />
|
||||
|
||||
<!------------------------------ Title ------------------------------>
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>Subscription Plans</h3>
|
||||
<div v-if="Model_D !== null" class="sx2">
|
||||
<!-- <b-button variant="danger" v-ripple.400="'rgba(255, 255, 255, 0.15)'">Remove</b-button> -->
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add
|
||||
</b-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------- Body ------------------------------>
|
||||
<b-card class="mt-1 position-relative" style="min-height: 95%;" body-class="p-0">
|
||||
|
||||
<!-- No Plans Exist -->
|
||||
<div id="no-plans--container" v-if="Model_D === null" class="d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="@/assets/svg/hero.svg" alt="no-users-found">
|
||||
<h4 class="mt-2" style="text-align: center;">You haven't created any subscription plans.</h4>
|
||||
<!-- <p style="text-align: center;">Click the following button to create a new plan.</p> -->
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add Subscription Plan
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<!-- List of Users -->
|
||||
<div v-else>
|
||||
<XTable ref="Table" v-bind:model="Model_D">
|
||||
<template v-slot:storage_limit="{ record }">
|
||||
{{ record.storage_limit }} KB
|
||||
</template>
|
||||
<template v-slot:from_date="{ record }">
|
||||
{{ (new Date(record.from_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:to_date="{ record }">
|
||||
{{ (new Date(record.to_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:is_active="{ record }">
|
||||
<feather-icon v-if="record.is_active" icon="CheckIcon" size="22" />
|
||||
<feather-icon v-else icon="XIcon" size="22" />
|
||||
</template>
|
||||
<template v-slot:actions="{ record }">
|
||||
<span class="d-inline-flex" style="column-gap: 1rem;">
|
||||
<feather-icon
|
||||
icon="EditIcon"
|
||||
size="16"
|
||||
color="blue"
|
||||
class="cursor-pointer"
|
||||
v-on:click="OpenEditModal(record)"
|
||||
/>
|
||||
<feather-icon
|
||||
icon="Trash2Icon"
|
||||
size="16"
|
||||
color="crimson"
|
||||
class="cursor-pointer"
|
||||
v-b-modal.confirm-modal
|
||||
v-on:click="RecordId_D = record.id"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
</XTable>
|
||||
</div>
|
||||
</b-card>
|
||||
|
||||
<EditPlanModal
|
||||
ref="EditModal"
|
||||
v-bind:initData="EditModalInitialData_D"
|
||||
v-bind:editing="IsEditing_D"
|
||||
v-on:submit="OnModalSubmitted"
|
||||
/>
|
||||
<SuccessModal v-bind:message="SuccessMessage_D" />
|
||||
<ErrorModal message="Operation failed." />
|
||||
<ConfirmModal
|
||||
title="Confirm Deletion"
|
||||
message="Are you sure you want to delete this plan?"
|
||||
v-on:confirm="OnDeleteConfirmed"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard, BButton, VBModal } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import EditPlanModal from './components/EditPlanModal'
|
||||
import * as TableCol from "./tables/contractUsersTbl"
|
||||
import XTable from "@/components/x-table/XTable"
|
||||
|
||||
export default {
|
||||
name: 'SubscriptionContractUsersView',
|
||||
|
||||
components: {
|
||||
BCard,
|
||||
BButton,
|
||||
EditPlanModal,
|
||||
XTable,
|
||||
},
|
||||
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
Ripple,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Model_D: null,
|
||||
Loading_D: false,
|
||||
SuccessMessage_D: '',
|
||||
RecordId_D: null, // The id for update or delete APIs
|
||||
|
||||
// The data to initialize the edit modal with.
|
||||
EditModalInitialData_D: undefined,
|
||||
|
||||
// Whether we're editing or creating a new plan
|
||||
IsEditing_D: null,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OpenEditModal(Record)
|
||||
{
|
||||
if( Boolean(Record) )
|
||||
{
|
||||
this.IsEditing_D = true
|
||||
this.RecordId_D = Record.id
|
||||
}
|
||||
else this.IsEditing_D = false
|
||||
|
||||
this.EditModalInitialData_D = Record
|
||||
this.$bvModal.show('modal-edit-plan')
|
||||
},
|
||||
|
||||
async OnModalSubmitted(Event)
|
||||
{
|
||||
// TODO(pooya): Remove this check when flow is checked.
|
||||
if( this.IsEditing_D === null )
|
||||
{
|
||||
console.error('INTERNAL ERROR: IsEditing is null')
|
||||
this.RecordId_D = null
|
||||
return
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
|
||||
if( this.IsEditing_D )
|
||||
{
|
||||
await this.$http.put(`admin/subscription-plan/${this.RecordId_D}`, Event)
|
||||
this.SuccessMessage_D = "Subscription plan was updated successfully."
|
||||
}
|
||||
else // creating a new plan
|
||||
{
|
||||
await this.$http.post('admin/create/subscription-plan', Event)
|
||||
this.SuccessMessage_D = "Subscription plan was added successfully."
|
||||
}
|
||||
|
||||
this.$refs.Table.refresh()
|
||||
this.$refs.EditModal.Clear()
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
console.log('Error', Err)
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.IsEditing_D = null
|
||||
this.RecordId_D = null
|
||||
}
|
||||
},
|
||||
|
||||
async OnDeleteConfirmed(Event)
|
||||
{
|
||||
if( Event === 'ok' )
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
await this.$http.delete(`admin/subscription-plan/${this.RecordId_D}`)
|
||||
this.$refs.Table.refresh()
|
||||
this.SuccessMessage_D = "Subscription plan deleted successfully."
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.RecordId_D = null
|
||||
}
|
||||
else if( Event === 'cancel' )
|
||||
this.RecordId_D = null
|
||||
},
|
||||
},
|
||||
|
||||
created()
|
||||
{
|
||||
this.Model_D = TableCol.default
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#no-plans--container {
|
||||
position: absolute;
|
||||
bottom: -2.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 0.25rem;
|
||||
padding: 2rem;
|
||||
|
||||
img {
|
||||
width: 280px; // 100%
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
<template>
|
||||
<!-- <div v-bind:class="{ 'page--main': Model_D === null }"> -->
|
||||
<div class="page--main">
|
||||
<FullpageLoadingComponent v-bind:show="Loading_D" />
|
||||
|
||||
<!------------------------------ Title ------------------------------>
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>Subscription Contracts</h3>
|
||||
<div v-if="Model_D !== null" class="sx2">
|
||||
<!-- <b-button variant="danger" v-ripple.400="'rgba(255, 255, 255, 0.15)'">Remove</b-button> -->
|
||||
<!-- <b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add
|
||||
</b-button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------- Body ------------------------------>
|
||||
<b-card class="mt-1 position-relative" style="min-height: 95%;" body-class="p-0">
|
||||
|
||||
<!-- No Plans Exist -->
|
||||
<div id="no-contracts--container" v-if="Model_D === null" class="d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="@/assets/svg/hero.svg" alt="no-users-found">
|
||||
<h4 class="mt-2" style="text-align: center;">You haven't created any subscription contracts.</h4>
|
||||
<!-- <p style="text-align: center;">Click the following button to create a new law firm.</p> -->
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add Subscription Contract
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<!-- List of Users -->
|
||||
<div v-else>
|
||||
<XTable ref="Table" v-bind:model="Model_D">
|
||||
<template v-slot:storage_limit="{ record }">
|
||||
{{ record.storage_limit }} KB
|
||||
</template>
|
||||
<template v-slot:from_date="{ record }">
|
||||
{{ (new Date(record.from_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:to_date="{ record }">
|
||||
{{ (new Date(record.to_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:actions="{ record }">
|
||||
<span class="d-inline-flex" style="column-gap: 1rem;">
|
||||
<feather-icon
|
||||
icon="EditIcon"
|
||||
size="16"
|
||||
color="blue"
|
||||
class="cursor-pointer"
|
||||
v-on:click="OpenEditModal(record)"
|
||||
/>
|
||||
<feather-icon
|
||||
icon="Trash2Icon"
|
||||
size="16"
|
||||
color="crimson"
|
||||
class="cursor-pointer"
|
||||
v-b-modal.confirm-modal
|
||||
v-on:click="RecordId_D = record.id"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
</XTable>
|
||||
</div>
|
||||
</b-card>
|
||||
|
||||
<EditContractModal
|
||||
ref="EditModal"
|
||||
v-bind:initData="EditModalInitialData_D"
|
||||
v-bind:editing="IsEditing_D"
|
||||
v-on:submit="OnModalSubmitted"
|
||||
/>
|
||||
<SuccessModal v-bind:message="SuccessMessage_D" />
|
||||
<ErrorModal message="Operation failed." />
|
||||
<ConfirmModal
|
||||
title="Confirm Deletion"
|
||||
message="Are you sure you want to delete this contract?"
|
||||
v-on:confirm="OnDeleteConfirmed"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard, BButton, VBModal } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import EditContractModal from './components/EditContractModal.vue'
|
||||
import * as TableCol from "./tables/contractsTbl"
|
||||
import XTable from "@/components/x-table/XTable"
|
||||
|
||||
export default {
|
||||
name: 'UsersListView',
|
||||
|
||||
components: {
|
||||
BCard,
|
||||
BButton,
|
||||
EditContractModal,
|
||||
XTable,
|
||||
},
|
||||
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
Ripple,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Model_D: null,
|
||||
Loading_D: false,
|
||||
SuccessMessage_D: '',
|
||||
RecordId_D: null, // The id for update or delete APIs
|
||||
|
||||
// The data to initialize the edit modal with.
|
||||
EditModalInitialData_D: undefined,
|
||||
|
||||
// Whether we're editing or creating a new plan
|
||||
IsEditing_D: null,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OpenEditModal(Record)
|
||||
{
|
||||
if( Boolean(Record) )
|
||||
{
|
||||
this.IsEditing_D = true
|
||||
this.RecordId_D = Record.id
|
||||
}
|
||||
else this.IsEditing_D = false
|
||||
|
||||
this.EditModalInitialData_D = Record
|
||||
this.$bvModal.show('modal-edit-plan')
|
||||
},
|
||||
|
||||
async OnModalSubmitted(Event)
|
||||
{
|
||||
// TODO(pooya): Remove this check when flow is checked.
|
||||
if( this.IsEditing_D === null )
|
||||
{
|
||||
console.error('INTERNAL ERROR: IsEditing is null')
|
||||
this.RecordId_D = null
|
||||
return
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
|
||||
if( this.IsEditing_D )
|
||||
{
|
||||
await this.$http.put(`admin/subscription-contract/${this.RecordId_D}`, Event)
|
||||
this.SuccessMessage_D = "Subscription contract was updated successfully."
|
||||
}
|
||||
else // creating a new contract
|
||||
{
|
||||
await this.$http.post('admin/create/subscription-contract', Event)
|
||||
this.SuccessMessage_D = "Subscription contract was added successfully."
|
||||
}
|
||||
|
||||
this.$refs.Table.refresh()
|
||||
this.$refs.EditModal.Clear()
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
console.log('Error', Err)
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.IsEditing_D = null
|
||||
this.RecordId_D = null
|
||||
}
|
||||
},
|
||||
|
||||
async OnDeleteConfirmed(Event)
|
||||
{
|
||||
if( Event === 'ok' )
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
await this.$http.delete(`admin/subscription-contract/${this.RecordId_D}`)
|
||||
this.$refs.Table.refresh()
|
||||
this.SuccessMessage_D = "Subscription contract deleted successfully."
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.RecordId_D = null
|
||||
}
|
||||
else if( Event === 'cancel' )
|
||||
this.RecordId_D = null
|
||||
},
|
||||
},
|
||||
|
||||
created()
|
||||
{
|
||||
this.Model_D = TableCol.default
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#no-contracts--container {
|
||||
position: absolute;
|
||||
bottom: -2.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 0.25rem;
|
||||
padding: 2rem;
|
||||
|
||||
img {
|
||||
width: 280px; // 100%
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
<template>
|
||||
<!-- <div v-bind:class="{ 'page--main': Model_D === null }"> -->
|
||||
<div class="page--main">
|
||||
<FullpageLoadingComponent v-bind:show="Loading_D" />
|
||||
|
||||
<!------------------------------ Title ------------------------------>
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>Subscription Payments</h3>
|
||||
<div v-if="Model_D !== null" class="sx2">
|
||||
<!-- <b-button variant="danger" v-ripple.400="'rgba(255, 255, 255, 0.15)'">Remove</b-button> -->
|
||||
<!-- <b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add
|
||||
</b-button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------- Body ------------------------------>
|
||||
<b-card class="mt-1 position-relative" style="min-height: 95%;" body-class="p-0">
|
||||
|
||||
<!-- No Plans Exist -->
|
||||
<div id="no-payments--container" v-if="Model_D === null" class="d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="@/assets/svg/hero.svg" alt="no-payments-found">
|
||||
<h4 class="mt-2" style="text-align: center;">You haven't created any subscription payments.</h4>
|
||||
<!-- <p style="text-align: center;">Click the following button to create a new plan.</p> -->
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add Subscription Payment
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<!-- List of Users -->
|
||||
<div v-else>
|
||||
<XTable ref="Table" v-bind:model="Model_D">
|
||||
<template v-slot:payed_at="{ record }">
|
||||
{{ (new Date(record.payed_at)).toLocaleString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:payment_dead_line="{ record }">
|
||||
{{ (new Date(record.payment_dead_line)).toLocaleString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:actions="{ record }">
|
||||
<span class="d-inline-flex" style="column-gap: 1rem;">
|
||||
<feather-icon
|
||||
icon="EditIcon"
|
||||
size="16"
|
||||
color="blue"
|
||||
class="cursor-pointer"
|
||||
v-on:click="OpenEditModal(record)"
|
||||
/>
|
||||
<feather-icon
|
||||
icon="Trash2Icon"
|
||||
size="16"
|
||||
color="crimson"
|
||||
class="cursor-pointer"
|
||||
v-b-modal.confirm-modal
|
||||
v-on:click="RecordId_D = record.id"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
</XTable>
|
||||
</div>
|
||||
</b-card>
|
||||
|
||||
<EditPaymentModal
|
||||
ref="EditModal"
|
||||
v-bind:initData="EditModalInitialData_D"
|
||||
v-bind:editing="IsEditing_D"
|
||||
v-on:submit="OnModalSubmitted"
|
||||
/>
|
||||
<SuccessModal v-bind:message="SuccessMessage_D" />
|
||||
<ErrorModal message="Operation failed." />
|
||||
<ConfirmModal
|
||||
title="Confirm Deletion"
|
||||
message="Are you sure you want to delete this plan?"
|
||||
v-on:confirm="OnDeleteConfirmed"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard, BButton, VBModal } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import EditPaymentModal from './components/EditPaymentModal'
|
||||
import * as TableCol from "./tables/paymentsTbl"
|
||||
import XTable from "@/components/x-table/XTable"
|
||||
|
||||
export default {
|
||||
name: 'UsersListView',
|
||||
|
||||
components: {
|
||||
BCard,
|
||||
BButton,
|
||||
EditPaymentModal,
|
||||
XTable,
|
||||
},
|
||||
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
Ripple,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Model_D: null,
|
||||
Loading_D: false,
|
||||
SuccessMessage_D: '',
|
||||
RecordId_D: null, // The id for update or delete APIs
|
||||
|
||||
// The data to initialize the edit modal with.
|
||||
EditModalInitialData_D: undefined,
|
||||
|
||||
// Whether we're editing or creating a new plan
|
||||
IsEditing_D: null,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OpenEditModal(Record)
|
||||
{
|
||||
if( Boolean(Record) )
|
||||
{
|
||||
this.IsEditing_D = true
|
||||
this.RecordId_D = Record.id
|
||||
}
|
||||
else this.IsEditing_D = false
|
||||
|
||||
this.EditModalInitialData_D = Record
|
||||
this.$bvModal.show('modal-edit-payment')
|
||||
},
|
||||
|
||||
async OnModalSubmitted(Event)
|
||||
{
|
||||
// TODO(pooya): Remove this check when flow is checked.
|
||||
if( this.IsEditing_D === null )
|
||||
{
|
||||
console.error('INTERNAL ERROR: IsEditing is null')
|
||||
this.RecordId_D = null
|
||||
return
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
|
||||
if( this.IsEditing_D )
|
||||
{
|
||||
await this.$http.put(`admin/subscription-payment/${this.RecordId_D}`, Event)
|
||||
this.SuccessMessage_D = "Subscription plan was updated successfully."
|
||||
}
|
||||
else // creating a new plan
|
||||
{
|
||||
await this.$http.post('admin/create/subscription-plan', Event)
|
||||
this.SuccessMessage_D = "Subscription plan was added successfully."
|
||||
}
|
||||
|
||||
this.$refs.Table.refresh()
|
||||
this.$refs.EditModal.Clear()
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
console.log('Error', Err)
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.IsEditing_D = null
|
||||
this.RecordId_D = null
|
||||
}
|
||||
},
|
||||
|
||||
async OnDeleteConfirmed(Event)
|
||||
{
|
||||
if( Event === 'ok' )
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
await this.$http.delete(`admin/subscription-payment/${this.RecordId_D}`)
|
||||
this.$refs.Table.refresh()
|
||||
this.SuccessMessage_D = "Subscription payment deleted successfully."
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.RecordId_D = null
|
||||
}
|
||||
else if( Event === 'cancel' )
|
||||
this.RecordId_D = null
|
||||
},
|
||||
},
|
||||
|
||||
created()
|
||||
{
|
||||
this.Model_D = TableCol.default
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#no-payments--container {
|
||||
position: absolute;
|
||||
bottom: -2.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 0.25rem;
|
||||
padding: 2rem;
|
||||
|
||||
img {
|
||||
width: 280px; // 100%
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
<template>
|
||||
<!-- <div v-bind:class="{ 'page--main': Model_D === null }"> -->
|
||||
<div class="page--main">
|
||||
<FullpageLoadingComponent v-bind:show="Loading_D" />
|
||||
|
||||
<!------------------------------ Title ------------------------------>
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>Subscription Plans</h3>
|
||||
<div v-if="Model_D !== null" class="sx2">
|
||||
<!-- <b-button variant="danger" v-ripple.400="'rgba(255, 255, 255, 0.15)'">Remove</b-button> -->
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add
|
||||
</b-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------- Body ------------------------------>
|
||||
<b-card class="mt-1 position-relative" style="min-height: 95%;" body-class="p-0">
|
||||
|
||||
<!-- No Plans Exist -->
|
||||
<div id="no-plans--container" v-if="Model_D === null" class="d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="@/assets/svg/hero.svg" alt="no-users-found">
|
||||
<h4 class="mt-2" style="text-align: center;">You haven't created any subscription plans.</h4>
|
||||
<!-- <p style="text-align: center;">Click the following button to create a new plan.</p> -->
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add Subscription Plan
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<!-- List of Users -->
|
||||
<div v-else>
|
||||
<XTable ref="Table" v-bind:model="Model_D">
|
||||
<template v-slot:storage_limit="{ record }">
|
||||
{{ record.storage_limit }} KB
|
||||
</template>
|
||||
<template v-slot:from_date="{ record }">
|
||||
{{ (new Date(record.from_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:to_date="{ record }">
|
||||
{{ (new Date(record.to_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:is_active="{ record }">
|
||||
<feather-icon v-if="record.is_active" icon="CheckIcon" size="22" />
|
||||
<feather-icon v-else icon="XIcon" size="22" />
|
||||
</template>
|
||||
<template v-slot:actions="{ record }">
|
||||
<span class="d-inline-flex" style="column-gap: 1rem;">
|
||||
<feather-icon
|
||||
icon="EditIcon"
|
||||
size="16"
|
||||
color="blue"
|
||||
class="cursor-pointer"
|
||||
v-on:click="OpenEditModal(record)"
|
||||
/>
|
||||
<feather-icon
|
||||
icon="Trash2Icon"
|
||||
size="16"
|
||||
color="crimson"
|
||||
class="cursor-pointer"
|
||||
v-b-modal.confirm-modal
|
||||
v-on:click="RecordId_D = record.id"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
</XTable>
|
||||
</div>
|
||||
</b-card>
|
||||
|
||||
<EditPlanModal
|
||||
ref="EditModal"
|
||||
v-bind:initData="EditModalInitialData_D"
|
||||
v-bind:editing="IsEditing_D"
|
||||
v-on:submit="OnModalSubmitted"
|
||||
/>
|
||||
<SuccessModal v-bind:message="SuccessMessage_D" />
|
||||
<ErrorModal message="Operation failed." />
|
||||
<ConfirmModal
|
||||
title="Confirm Deletion"
|
||||
message="Are you sure you want to delete this plan?"
|
||||
v-on:confirm="OnDeleteConfirmed"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard, BButton, VBModal } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import EditPlanModal from './components/EditPlanModal'
|
||||
import * as TableCol from "./tables/plansTbl"
|
||||
import XTable from "@/components/x-table/XTable"
|
||||
|
||||
export default {
|
||||
name: 'UsersListView',
|
||||
|
||||
components: {
|
||||
BCard,
|
||||
BButton,
|
||||
EditPlanModal,
|
||||
XTable,
|
||||
},
|
||||
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
Ripple,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Model_D: null,
|
||||
Loading_D: false,
|
||||
SuccessMessage_D: '',
|
||||
RecordId_D: null, // The id for update or delete APIs
|
||||
|
||||
// The data to initialize the edit modal with.
|
||||
EditModalInitialData_D: undefined,
|
||||
|
||||
// Whether we're editing or creating a new plan
|
||||
IsEditing_D: null,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OpenEditModal(Record)
|
||||
{
|
||||
if( Boolean(Record) )
|
||||
{
|
||||
this.IsEditing_D = true
|
||||
this.RecordId_D = Record.id
|
||||
}
|
||||
else this.IsEditing_D = false
|
||||
|
||||
this.EditModalInitialData_D = Record
|
||||
this.$bvModal.show('modal-edit-plan')
|
||||
},
|
||||
|
||||
async OnModalSubmitted(Event)
|
||||
{
|
||||
// TODO(pooya): Remove this check when flow is checked.
|
||||
if( this.IsEditing_D === null )
|
||||
{
|
||||
console.error('INTERNAL ERROR: IsEditing is null')
|
||||
this.RecordId_D = null
|
||||
return
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
|
||||
if( this.IsEditing_D )
|
||||
{
|
||||
await this.$http.put(`admin/subscription-plan/${this.RecordId_D}`, Event)
|
||||
this.SuccessMessage_D = "Subscription plan was updated successfully."
|
||||
}
|
||||
else // creating a new plan
|
||||
{
|
||||
await this.$http.post('admin/create/subscription-plan', Event)
|
||||
this.SuccessMessage_D = "Subscription plan was added successfully."
|
||||
}
|
||||
|
||||
this.$refs.Table.refresh()
|
||||
this.$refs.EditModal.Clear()
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
console.log('Error', Err)
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.IsEditing_D = null
|
||||
this.RecordId_D = null
|
||||
}
|
||||
},
|
||||
|
||||
async OnDeleteConfirmed(Event)
|
||||
{
|
||||
if( Event === 'ok' )
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
await this.$http.delete(`admin/subscription-plan/${this.RecordId_D}`)
|
||||
this.$refs.Table.refresh()
|
||||
this.SuccessMessage_D = "Subscription plan deleted successfully."
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.RecordId_D = null
|
||||
}
|
||||
else if( Event === 'cancel' )
|
||||
this.RecordId_D = null
|
||||
},
|
||||
},
|
||||
|
||||
created()
|
||||
{
|
||||
this.Model_D = TableCol.default
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#no-plans--container {
|
||||
position: absolute;
|
||||
bottom: -2.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 0.25rem;
|
||||
padding: 2rem;
|
||||
|
||||
img {
|
||||
width: 280px; // 100%
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
<template>
|
||||
<div v-bind:class="{ 'page--main': Model_D === null }">
|
||||
<FullpageLoadingComponent v-bind:show="Loading_D" />
|
||||
|
||||
<!----------------------------- Title ----------------------------->
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>Subscription Plans</h3>
|
||||
<div v-if="Model_D !== null" class="sx2">
|
||||
<b-button variant="danger" v-ripple.400="'rgba(255, 255, 255, 0.15)'">Remove</b-button>
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-b-modal:modal-edit-plan
|
||||
>
|
||||
Add
|
||||
</b-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------ Body ----------------------------->
|
||||
<b-card class="mt-1 position-relative" style="min-height: 95%;" body-class="p-0">
|
||||
|
||||
<!-- No Plans Exist -->
|
||||
<div id="no-plans--container" v-if="Model_D === null" class="d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="@/assets/svg/hero.svg" alt="no-users-found">
|
||||
<h4 class="mt-2" style="text-align: center;">You haven't created any law firms.</h4>
|
||||
<p style="text-align: center;">Click the following button to create a new law firm.</p>
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-b-modal:modal-edit-plan
|
||||
>
|
||||
Add Subscription Plan
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<!-- List of Users -->
|
||||
<div v-else>
|
||||
<XTable v-bind:model="Model_D">
|
||||
<template v-slot:storage_limit="{ record }">
|
||||
{{ record.storage_limit }} KB
|
||||
</template>
|
||||
<template v-slot:from_date="{ record }">
|
||||
{{ (new Date(record.from_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:to_date="{ record }">
|
||||
{{ (new Date(record.to_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:is_active="{ record }">
|
||||
<feather-icon v-if="record.is_active" icon="CheckIcon" size="22" />
|
||||
<feather-icon v-else icon="XIcon" size="22" />
|
||||
</template>
|
||||
<template v-slot:actions="{ record }">
|
||||
<span class="d-inline-flex" style="column-gap: 1rem;">
|
||||
<feather-icon
|
||||
icon="EditIcon"
|
||||
size="16"
|
||||
color="blue"
|
||||
class="cursor-pointer"
|
||||
/>
|
||||
<feather-icon
|
||||
icon="Trash2Icon"
|
||||
size="16"
|
||||
color="crimson"
|
||||
class="cursor-pointer"
|
||||
v-on:click="onDeleteRecord(record.id)"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
</XTable>
|
||||
</div>
|
||||
</b-card>
|
||||
|
||||
<EditPlanModal v-on:submit="HandleNewPlanAdded" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard, BButton, VBModal } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import EditPlanModal from './components/EditPlanModal'
|
||||
import * as TableCol from "./tables/plansTbl"
|
||||
import XTable from "@/components/x-table/XTable"
|
||||
|
||||
export default {
|
||||
name: 'UsersListView',
|
||||
|
||||
components: {
|
||||
BCard,
|
||||
BButton,
|
||||
EditPlanModal,
|
||||
XTable,
|
||||
},
|
||||
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
Ripple,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Model_D: null,
|
||||
Loading_D: false,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async HandleNewPlanAdded(event)
|
||||
{
|
||||
// if create
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
// const { data } = this.$http.post('', this.Payload_D)
|
||||
}
|
||||
catch
|
||||
{}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
}
|
||||
|
||||
// if edit
|
||||
console.log('event is', event)
|
||||
},
|
||||
|
||||
async OnDeleteRecord(RecordId)
|
||||
{
|
||||
},
|
||||
},
|
||||
|
||||
created()
|
||||
{
|
||||
this.Model_D = TableCol.default
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#no-plans--container {
|
||||
position: absolute;
|
||||
bottom: -2.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 0.25rem;
|
||||
padding: 2rem;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
<template>
|
||||
<!-- <div v-bind:class="{ 'page--main': Model_D === null }"> -->
|
||||
<div class="page--main">
|
||||
<FullpageLoadingComponent v-bind:show="Loading_D" />
|
||||
|
||||
<!------------------------------ Title ------------------------------>
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>Subscription Rules</h3>
|
||||
<div v-if="Model_D !== null" class="sx2">
|
||||
<!-- <b-button variant="danger" v-ripple.400="'rgba(255, 255, 255, 0.15)'">Remove</b-button> -->
|
||||
<!-- <b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add
|
||||
</b-button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------- Body ------------------------------>
|
||||
<b-card class="mt-1 position-relative" style="min-height: 95%;" body-class="p-0">
|
||||
|
||||
<!-- No Plans Exist -->
|
||||
<div id="no-rules--container" v-if="Model_D === null" class="d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="@/assets/svg/hero.svg" alt="no-users-found">
|
||||
<h4 class="mt-2" style="text-align: center;">You haven't created any subscription rules.</h4>
|
||||
<!-- <p style="text-align: center;">Click the following button to create a new plan.</p> -->
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add Subscription Rule
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<!-- List of Users -->
|
||||
<div v-else>
|
||||
<XTable ref="Table" v-bind:model="Model_D">
|
||||
<template v-slot:storage_limit="{ record }">
|
||||
{{ record.storage_limit }} KB
|
||||
</template>
|
||||
<template v-slot:from_date="{ record }">
|
||||
{{ (new Date(record.from_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:to_date="{ record }">
|
||||
{{ (new Date(record.to_date)).toLocaleDateString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:is_active="{ record }">
|
||||
<feather-icon v-if="record.is_active" icon="CheckIcon" size="22" />
|
||||
<feather-icon v-else icon="XIcon" size="22" />
|
||||
</template>
|
||||
<template v-slot:actions="{ record }">
|
||||
<span class="d-inline-flex" style="column-gap: 1rem;">
|
||||
<feather-icon
|
||||
icon="EditIcon"
|
||||
size="16"
|
||||
color="blue"
|
||||
class="cursor-pointer"
|
||||
v-on:click="OpenEditModal(record)"
|
||||
/>
|
||||
<feather-icon
|
||||
icon="Trash2Icon"
|
||||
size="16"
|
||||
color="crimson"
|
||||
class="cursor-pointer"
|
||||
v-b-modal.confirm-modal
|
||||
v-on:click="RecordId_D = record.id"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
</XTable>
|
||||
</div>
|
||||
</b-card>
|
||||
|
||||
<EditRuleModal
|
||||
ref="EditModal"
|
||||
v-bind:initData="EditModalInitialData_D"
|
||||
v-bind:plans="Plans_D"
|
||||
v-bind:editing="IsEditing_D"
|
||||
v-on:submit="OnModalSubmitted"
|
||||
/>
|
||||
<SuccessModal v-bind:message="SuccessMessage_D" />
|
||||
<ErrorModal message="Operation failed." />
|
||||
<ConfirmModal
|
||||
title="Confirm Deletion"
|
||||
message="Are you sure you want to delete this plan?"
|
||||
v-on:confirm="OnDeleteConfirmed"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard, BButton, VBModal } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import EditRuleModal from './components/EditRuleModal'
|
||||
import * as TableCol from "./tables/rulesTbl"
|
||||
import XTable from "@/components/x-table/XTable"
|
||||
|
||||
export default {
|
||||
name: 'UsersListView',
|
||||
|
||||
components: {
|
||||
BCard,
|
||||
BButton,
|
||||
EditRuleModal,
|
||||
XTable,
|
||||
},
|
||||
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
Ripple,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Model_D: null,
|
||||
Loading_D: false,
|
||||
SuccessMessage_D: '',
|
||||
RecordId_D: null, // The id for update or delete APIs
|
||||
Plans_D: [],
|
||||
|
||||
// The data to initialize the edit modal with.
|
||||
EditModalInitialData_D: undefined,
|
||||
|
||||
// Whether we're editing or creating a new plan
|
||||
IsEditing_D: null,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OpenEditModal(Record)
|
||||
{
|
||||
if( Boolean(Record) )
|
||||
{
|
||||
this.IsEditing_D = true
|
||||
this.RecordId_D = Record.id
|
||||
}
|
||||
else this.IsEditing_D = false
|
||||
|
||||
this.EditModalInitialData_D = Record
|
||||
this.$bvModal.show('modal-edit-plan')
|
||||
},
|
||||
|
||||
async OnModalSubmitted(Event)
|
||||
{
|
||||
// TODO(pooya): Remove this check when flow is checked.
|
||||
if( this.IsEditing_D === null )
|
||||
{
|
||||
console.error('INTERNAL ERROR: IsEditing is null')
|
||||
this.RecordId_D = null
|
||||
return
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
|
||||
if( this.IsEditing_D )
|
||||
{
|
||||
await this.$http.put(`admin/subscription-rule/${this.RecordId_D}`, Event)
|
||||
this.SuccessMessage_D = "Subscription rule was updated successfully."
|
||||
}
|
||||
else // creating a new rule
|
||||
{
|
||||
await this.$http.post('admin/create/subscription-rule', Event)
|
||||
this.SuccessMessage_D = "Subscription rule was added successfully."
|
||||
}
|
||||
|
||||
this.$refs.Table.refresh()
|
||||
this.$refs.EditModal.Clear()
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
console.log('Error', Err)
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.IsEditing_D = null
|
||||
this.RecordId_D = null
|
||||
}
|
||||
},
|
||||
|
||||
async OnDeleteConfirmed(Event)
|
||||
{
|
||||
if( Event === 'ok' )
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
await this.$http.delete(`admin/subscription-rule/${this.RecordId_D}`)
|
||||
this.$refs.Table.refresh()
|
||||
this.SuccessMessage_D = "Subscription rule deleted successfully."
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.RecordId_D = null
|
||||
}
|
||||
else if( Event === 'cancel' )
|
||||
this.RecordId_D = null
|
||||
},
|
||||
},
|
||||
|
||||
created()
|
||||
{
|
||||
this.Model_D = TableCol.default
|
||||
},
|
||||
|
||||
async mounted()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
const { data } = await this.$http.post('admin/list/subscription-plan', {
|
||||
te: {
|
||||
p: {c: 1, s: 100}
|
||||
}
|
||||
})
|
||||
this.Plans_D = data.rows
|
||||
console.log('plans', this.Plans_D)
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#no-rules--container {
|
||||
position: absolute;
|
||||
bottom: -2.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 0.25rem;
|
||||
padding: 2rem;
|
||||
|
||||
img {
|
||||
width: 280px; // 100%
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
<template>
|
||||
<!-- <div v-bind:class="{ 'page--main': Model_D === null }"> -->
|
||||
<div class="page--main">
|
||||
<FullpageLoadingComponent v-bind:show="Loading_D" />
|
||||
|
||||
<!------------------------------ Title ------------------------------>
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>Subscriptions</h3>
|
||||
<div v-if="Model_D !== null" class="sx2">
|
||||
<!-- <b-button variant="danger" v-ripple.400="'rgba(255, 255, 255, 0.15)'">Remove</b-button> -->
|
||||
<!-- <b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add
|
||||
</b-button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------- Body ------------------------------>
|
||||
<b-card class="mt-1 position-relative" style="min-height: 95%;" body-class="p-0">
|
||||
|
||||
<!-- No Plans Exist -->
|
||||
<div id="no-plans--container" v-if="Model_D === null" class="d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="@/assets/svg/hero.svg" alt="no-users-found">
|
||||
<h4 class="mt-2" style="text-align: center;">You haven't created any subscription plans.</h4>
|
||||
<!-- <p style="text-align: center;">Click the following button to create a new plan.</p> -->
|
||||
<b-button
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OpenEditModal()"
|
||||
>
|
||||
Add Subscription Plan
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<!-- List of Users -->
|
||||
<div v-else>
|
||||
<XTable ref="Table" v-bind:model="Model_D">
|
||||
<template v-slot:last_deposit_date="{ record }">
|
||||
{{ (new Date(record.last_deposit_date)).toLocaleString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:actions="{ record }">
|
||||
<span class="d-inline-flex" style="column-gap: 1rem;">
|
||||
<feather-icon
|
||||
icon="EditIcon"
|
||||
size="16"
|
||||
color="blue"
|
||||
class="cursor-pointer"
|
||||
v-on:click="OpenEditModal(record)"
|
||||
/>
|
||||
<feather-icon
|
||||
icon="Trash2Icon"
|
||||
size="16"
|
||||
color="crimson"
|
||||
class="cursor-pointer"
|
||||
v-b-modal.confirm-modal
|
||||
v-on:click="RecordId_D = record.id"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
</XTable>
|
||||
</div>
|
||||
</b-card>
|
||||
|
||||
<EditPlanModal
|
||||
ref="EditModal"
|
||||
v-bind:initData="EditModalInitialData_D"
|
||||
v-bind:editing="IsEditing_D"
|
||||
v-on:submit="OnModalSubmitted"
|
||||
/>
|
||||
<SuccessModal v-bind:message="SuccessMessage_D" />
|
||||
<ErrorModal message="Operation failed." />
|
||||
<ConfirmModal
|
||||
title="Confirm Deletion"
|
||||
message="Are you sure you want to delete this plan?"
|
||||
v-on:confirm="OnDeleteConfirmed"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard, BButton, VBModal } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import EditPlanModal from './components/EditPlanModal'
|
||||
import * as TableCol from "./tables/subscriptionsTbl"
|
||||
import XTable from "@/components/x-table/XTable"
|
||||
|
||||
export default {
|
||||
name: 'UsersListView',
|
||||
|
||||
components: {
|
||||
BCard,
|
||||
BButton,
|
||||
EditPlanModal,
|
||||
XTable,
|
||||
},
|
||||
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
Ripple,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Model_D: null,
|
||||
Loading_D: false,
|
||||
SuccessMessage_D: '',
|
||||
RecordId_D: null, // The id for update or delete APIs
|
||||
|
||||
// The data to initialize the edit modal with.
|
||||
EditModalInitialData_D: undefined,
|
||||
|
||||
// Whether we're editing or creating a new plan
|
||||
IsEditing_D: null,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OpenEditModal(Record)
|
||||
{
|
||||
if( Boolean(Record) )
|
||||
{
|
||||
this.IsEditing_D = true
|
||||
this.RecordId_D = Record.id
|
||||
}
|
||||
else this.IsEditing_D = false
|
||||
|
||||
this.EditModalInitialData_D = Record
|
||||
this.$bvModal.show('modal-edit-plan')
|
||||
},
|
||||
|
||||
async OnModalSubmitted(Event)
|
||||
{
|
||||
// TODO(pooya): Remove this check when flow is checked.
|
||||
if( this.IsEditing_D === null )
|
||||
{
|
||||
console.error('INTERNAL ERROR: IsEditing is null')
|
||||
this.RecordId_D = null
|
||||
return
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
|
||||
if( this.IsEditing_D )
|
||||
{
|
||||
await this.$http.put(`admin/subscription-plan/${this.RecordId_D}`, Event)
|
||||
this.SuccessMessage_D = "Subscription plan was updated successfully."
|
||||
}
|
||||
else // creating a new plan
|
||||
{
|
||||
await this.$http.post('admin/create/subscription-plan', Event)
|
||||
this.SuccessMessage_D = "Subscription plan was added successfully."
|
||||
}
|
||||
|
||||
this.$refs.Table.refresh()
|
||||
this.$refs.EditModal.Clear()
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
console.log('Error', Err)
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.IsEditing_D = null
|
||||
this.RecordId_D = null
|
||||
}
|
||||
},
|
||||
|
||||
async OnDeleteConfirmed(Event)
|
||||
{
|
||||
if( Event === 'ok' )
|
||||
try
|
||||
{
|
||||
this.Loading_D = true
|
||||
await this.$http.delete(`admin/subscription-plan/${this.RecordId_D}`)
|
||||
this.$refs.Table.refresh()
|
||||
this.SuccessMessage_D = "Subscription plan deleted successfully."
|
||||
this.$bvModal.show('success-modal')
|
||||
}
|
||||
catch( Err )
|
||||
{
|
||||
this.$bvModal.show('error-modal')
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Loading_D = false
|
||||
this.RecordId_D = null
|
||||
}
|
||||
else if( Event === 'cancel' )
|
||||
this.RecordId_D = null
|
||||
},
|
||||
},
|
||||
|
||||
created()
|
||||
{
|
||||
this.Model_D = TableCol.default
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#no-plans--container {
|
||||
position: absolute;
|
||||
bottom: -2.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 0.25rem;
|
||||
padding: 2rem;
|
||||
|
||||
img {
|
||||
width: 280px; // 100%
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<!-- <div v-bind:class="{ 'page--main': Model_D === null }"> -->
|
||||
<div class="page--main">
|
||||
<!------------------------------ Title ------------------------------>
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>Subscription Transactions</h3>
|
||||
</div>
|
||||
|
||||
<!------------------------------- Body ------------------------------>
|
||||
<b-card class="mt-1 position-relative" style="min-height: 95%;" body-class="p-0">
|
||||
|
||||
<!-- No Plans Exist -->
|
||||
<div id="no-plans--container" v-if="Model_D === null" class="d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="@/assets/svg/hero.svg" alt="no-transactions-found">
|
||||
<h4 class="mt-2" style="text-align: center;">There's no transaction yet.</h4>
|
||||
</div>
|
||||
|
||||
<!-- List of Users -->
|
||||
<div v-else>
|
||||
<XTable ref="Table" v-bind:model="Model_D">
|
||||
<template v-slot:created_at="{ record }">
|
||||
{{ (new Date(record.created_at)).toLocaleString('en-US') }}
|
||||
</template>
|
||||
<template v-slot:is_active="{ record }">
|
||||
<feather-icon v-if="record.is_active" icon="CheckIcon" size="22" />
|
||||
<feather-icon v-else icon="XIcon" size="22" />
|
||||
</template>
|
||||
</XTable>
|
||||
</div>
|
||||
</b-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard } from 'bootstrap-vue'
|
||||
import * as TableCol from "./tables/transactionsTbl"
|
||||
import XTable from "@/components/x-table/XTable"
|
||||
|
||||
export default {
|
||||
name: 'UsersListView',
|
||||
|
||||
components: {
|
||||
BCard,
|
||||
XTable,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Model_D: null,
|
||||
}
|
||||
},
|
||||
|
||||
created()
|
||||
{
|
||||
this.Model_D = TableCol.default
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#no-transactions--container {
|
||||
position: absolute;
|
||||
bottom: -2.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 0.25rem;
|
||||
padding: 2rem;
|
||||
|
||||
img {
|
||||
width: 280px; // 100%
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
<template>
|
||||
<b-modal id="modal-edit-plan" v-bind:centered="true" size="lg" body-class="pb-0">
|
||||
<!-- Header -->
|
||||
<template v-slot:modal-header="{ close }">
|
||||
<h2 class="text-primary m-0">
|
||||
<span v-if="editing">Edit Contract</span>
|
||||
<span v-else>Add Contract</span>
|
||||
</h2>
|
||||
<img class="cursor-pointer" src="@/assets/svg/cross.svg" alt="close-icon" v-on:click="close()">
|
||||
</template>
|
||||
|
||||
<!-- Body -->
|
||||
<template v-slot:default>
|
||||
<ValidationObserver ref="form" v-slot="{}">
|
||||
<b-form class="d-flex flex-column" v-on:submit.prevent>
|
||||
<b-row>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.allowed_delay_days"
|
||||
label="Allowed Delay Days"
|
||||
name="allowed_delay_days"
|
||||
placeholder="0"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.installments_count"
|
||||
label="Installments Count"
|
||||
name="installments_count"
|
||||
placeholder="0"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.total_price"
|
||||
label="Price"
|
||||
name="total_price"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.discounted_price"
|
||||
label="Discounted Price"
|
||||
name="discounted_price"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.payable_amount"
|
||||
label="Payable Amount"
|
||||
name="payable_amount"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.payed_amount"
|
||||
label="Payed Amount"
|
||||
name="payed_amount"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.storage_limit"
|
||||
label="Storage Limit (KB)"
|
||||
name="storage_limit"
|
||||
placeholder="10"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.user_limit"
|
||||
label="User Limit"
|
||||
name="user_limit"
|
||||
placeholder="10"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<DatepickerComponent
|
||||
v-model="Payload_D.from_date"
|
||||
label="From"
|
||||
name="from_date"
|
||||
description="The contract is available to clients from this date"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<DatepickerComponent
|
||||
v-model="Payload_D.to_date"
|
||||
label="To"
|
||||
name="to_date"
|
||||
description="To this date"
|
||||
/>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-form>
|
||||
</ValidationObserver>
|
||||
</template>
|
||||
|
||||
<!-- Footer -->
|
||||
<template v-slot:modal-footer="{ hide }">
|
||||
<b-button
|
||||
class="mr-1"
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OnSubmit(hide)"
|
||||
>
|
||||
<span v-if="editing">Update Contract</span>
|
||||
<span v-else>Save Contract</span>
|
||||
</b-button>
|
||||
or
|
||||
<a class="text-primary" v-on:click="hide()">Cancel</a>
|
||||
</template>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BForm, BButton, BRow, BCol } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
|
||||
export default {
|
||||
name: 'EditPlanModalComponent',
|
||||
|
||||
components: {
|
||||
BForm,
|
||||
BButton,
|
||||
BRow,
|
||||
BCol,
|
||||
},
|
||||
|
||||
directives: {
|
||||
Ripple,
|
||||
},
|
||||
|
||||
props: {
|
||||
// The initial data to fill the inputs with.
|
||||
initData: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({
|
||||
allowed_delay_days: '',
|
||||
installments_count: '',
|
||||
total_price: '',
|
||||
discounted_price: '',
|
||||
payable_amount: '',
|
||||
payed_amount: '',
|
||||
storage_limit: '',
|
||||
// storage_usage: '',
|
||||
from_date: '',
|
||||
to_date: '',
|
||||
user_limit: '',
|
||||
})
|
||||
},
|
||||
|
||||
// Whether we're in editing mode or create mode.
|
||||
// It's type is Boolean | null.
|
||||
editing: {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Payload_D: this.initData,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OnSubmit(Hide)
|
||||
{
|
||||
this.$refs.form.validate().then(async success => {
|
||||
if( success )
|
||||
{
|
||||
// NOTE(pooya): Interestingly, if you remove the
|
||||
// following line, the payload will be passed as empty!
|
||||
const tmp = Object.assign({}, this.Payload_D)
|
||||
|
||||
this.$emit('submit', tmp)
|
||||
Hide()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
Clear()
|
||||
{
|
||||
this.Payload_D.allowed_delay_days = ''
|
||||
this.Payload_D.discounted_price = ''
|
||||
this.Payload_D.total_price = ''
|
||||
this.Payload_D.payable_amount = ''
|
||||
this.Payload_D.payed_amount = ''
|
||||
this.Payload_D.storage_limit = ''
|
||||
this.Payload_D.from_date = ''
|
||||
this.Payload_D.to_date = ''
|
||||
this.Payload_D.user_limit = ''
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
initData: function(NewValue) {
|
||||
if( NewValue === undefined ) this.Clear()
|
||||
else
|
||||
{
|
||||
this.Payload_D.title = NewValue.title
|
||||
this.Payload_D.storage_limit = NewValue.storage_limit.toString()
|
||||
this.Payload_D.description = NewValue.description
|
||||
this.Payload_D.from_date = NewValue.from_date
|
||||
this.Payload_D.to_date = NewValue.to_date
|
||||
this.Payload_D.months = NewValue.months.toString()
|
||||
this.Payload_D.is_active = NewValue.is_active
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
<template>
|
||||
<b-modal id="modal-edit-payment" v-bind:centered="true" size="lg" body-class="pb-0">
|
||||
<!-- Header -->
|
||||
<template v-slot:modal-header="{ close }">
|
||||
<h2 class="text-primary m-0">
|
||||
<span v-if="editing">Edit Plan</span>
|
||||
<span v-else>Add Plan</span>
|
||||
</h2>
|
||||
<img class="cursor-pointer" src="@/assets/svg/cross.svg" alt="close-icon" v-on:click="close()">
|
||||
</template>
|
||||
|
||||
<!-- Body -->
|
||||
<template v-slot:default>
|
||||
<ValidationObserver ref="form" v-slot="{}">
|
||||
<b-form class="d-flex flex-column" v-on:submit.prevent>
|
||||
<b-row>
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.amount"
|
||||
label="Amount"
|
||||
name="amount"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<DatepickerComponent
|
||||
v-model="Payload_D.payment_dead_line"
|
||||
label="Payment Deadline"
|
||||
name="payment_dead_line"
|
||||
/>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-form>
|
||||
</ValidationObserver>
|
||||
</template>
|
||||
|
||||
<!-- Footer -->
|
||||
<template v-slot:modal-footer="{ hide }">
|
||||
<b-button
|
||||
class="mr-1"
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OnSubmit(hide)"
|
||||
>
|
||||
<span v-if="editing">Update Plan</span>
|
||||
<span v-else>Save Plan</span>
|
||||
</b-button>
|
||||
or
|
||||
<a class="text-primary" v-on:click="hide()">Cancel</a>
|
||||
</template>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BForm, BButton, BRow, BCol } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
|
||||
export default {
|
||||
name: 'EditPlanModalComponent',
|
||||
|
||||
components: {
|
||||
BForm,
|
||||
BButton,
|
||||
BRow,
|
||||
BCol,
|
||||
},
|
||||
|
||||
directives: {
|
||||
Ripple,
|
||||
},
|
||||
|
||||
props: {
|
||||
// The initial data to fill the inputs with.
|
||||
initData: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({
|
||||
amount: '',
|
||||
// payed_at: '',
|
||||
payment_dead_line: '',
|
||||
// tracking_code: '',
|
||||
})
|
||||
},
|
||||
|
||||
// Whether we're in editing mode or create mode.
|
||||
// It's type is Boolean | null.
|
||||
editing: {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Payload_D: this.initData,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OnSubmit(Hide)
|
||||
{
|
||||
this.$refs.form.validate().then(async success => {
|
||||
if( success )
|
||||
{
|
||||
// NOTE(pooya): Interestingly, if you remove the
|
||||
// following line, the payload will be passed as empty!
|
||||
const tmp = Object.assign({}, this.Payload_D)
|
||||
|
||||
this.$emit('submit', tmp)
|
||||
Hide()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
Clear()
|
||||
{
|
||||
this.Payload_D.title = ''
|
||||
this.Payload_D.storage_limit = ''
|
||||
this.Payload_D.description = ''
|
||||
this.Payload_D.from_date = ''
|
||||
this.Payload_D.to_date = ''
|
||||
this.Payload_D.months = '1'
|
||||
this.Payload_D.is_active = true
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
initData: function(NewValue) {
|
||||
if( NewValue === undefined ) this.Clear()
|
||||
else
|
||||
{
|
||||
this.Payload_D.title = NewValue.title
|
||||
this.Payload_D.storage_limit = NewValue.storage_limit.toString()
|
||||
this.Payload_D.description = NewValue.description
|
||||
this.Payload_D.from_date = NewValue.from_date
|
||||
this.Payload_D.to_date = NewValue.to_date
|
||||
this.Payload_D.months = NewValue.months.toString()
|
||||
this.Payload_D.is_active = NewValue.is_active
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
|
@ -1,29 +1,11 @@
|
|||
<!--
|
||||
Documentation:
|
||||
|
||||
Description:
|
||||
A modal that prompts for a subscription plan.
|
||||
|
||||
How to use:
|
||||
Import the component, put it in the template section, then use VBModal
|
||||
bootstrap-vue component and pass it modal-edit-plan argument to open the modal.
|
||||
|
||||
Example:
|
||||
<b-button v-b-modal:modal-edit-plan>Add New Plan</b-button>
|
||||
<EditPlanModal v-on:submit="HandleNewPlanAdded" />
|
||||
|
||||
Events
|
||||
Name Parameters Description
|
||||
-------- ----------- ----------------------------------------------------------
|
||||
submit payload called when the submit button (the button in the footer) is clicked
|
||||
|
||||
-->
|
||||
|
||||
<template>
|
||||
<b-modal id="modal-edit-plan" v-bind:centered="true" size="lg" body-class="pb-0">
|
||||
<!-- Header -->
|
||||
<template v-slot:modal-header="{ close }">
|
||||
<h2 class="text-primary m-0">Add Plan</h2>
|
||||
<h2 class="text-primary m-0">
|
||||
<span v-if="editing">Edit Plan</span>
|
||||
<span v-else>Add Plan</span>
|
||||
</h2>
|
||||
<img class="cursor-pointer" src="@/assets/svg/cross.svg" alt="close-icon" v-on:click="close()">
|
||||
</template>
|
||||
|
||||
|
|
@ -64,6 +46,7 @@ submit payload called when the submit button (the button in the footer
|
|||
v-model="Payload_D.from_date"
|
||||
label="From"
|
||||
name="from_date"
|
||||
description="The plan is available to clients from this date"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
|
|
@ -71,9 +54,20 @@ submit payload called when the submit button (the button in the footer
|
|||
v-model="Payload_D.to_date"
|
||||
label="To"
|
||||
name="to_date"
|
||||
description="To this date"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="12">
|
||||
<b-col md="6">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.months"
|
||||
label="Months"
|
||||
name="months"
|
||||
placeholder="12"
|
||||
description="How many months the plan will be active"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<CheckboxComponent
|
||||
v-model="Payload_D.is_active"
|
||||
label="Is Active"
|
||||
|
|
@ -93,7 +87,8 @@ submit payload called when the submit button (the button in the footer
|
|||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OnSubmit(hide)"
|
||||
>
|
||||
Save Plan
|
||||
<span v-if="editing">Update Plan</span>
|
||||
<span v-else>Save Plan</span>
|
||||
</b-button>
|
||||
or
|
||||
<a class="text-primary" v-on:click="hide()">Cancel</a>
|
||||
|
|
@ -102,7 +97,7 @@ submit payload called when the submit button (the button in the footer
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { BForm, BButton, BRow, BCol, BFormGroup, BFormDatepicker } from 'bootstrap-vue'
|
||||
import { BForm, BButton, BRow, BCol } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
|
||||
export default {
|
||||
|
|
@ -113,30 +108,38 @@ export default {
|
|||
BButton,
|
||||
BRow,
|
||||
BCol,
|
||||
BFormGroup,
|
||||
BFormDatepicker,
|
||||
},
|
||||
|
||||
directives: {
|
||||
Ripple,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Payload_D: {
|
||||
props: {
|
||||
// The initial data to fill the inputs with.
|
||||
initData: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({
|
||||
title: '',
|
||||
storage_limit: '',
|
||||
description: '',
|
||||
from_date: '',
|
||||
to_date: '',
|
||||
months: '1',
|
||||
is_active: true,
|
||||
},
|
||||
PlanOptions_D: [
|
||||
{ value: 0, title: 'Diamond' },
|
||||
{ value: 1, title: 'Gold' },
|
||||
{ value: 2, title: 'Silver' },
|
||||
{ value: 3, title: 'Bronze' },
|
||||
],
|
||||
})
|
||||
},
|
||||
|
||||
// Whether we're in editing mode or create mode.
|
||||
// It's type is Boolean | null.
|
||||
editing: {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Payload_D: this.initData,
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -144,13 +147,44 @@ export default {
|
|||
OnSubmit(Hide)
|
||||
{
|
||||
this.$refs.form.validate().then(async success => {
|
||||
if (success)
|
||||
if( success )
|
||||
{
|
||||
this.$emit('submit', this.Payload_D)
|
||||
// NOTE(pooya): Interestingly, if you remove the
|
||||
// following line, the payload will be passed as empty!
|
||||
const tmp = Object.assign({}, this.Payload_D)
|
||||
|
||||
this.$emit('submit', tmp)
|
||||
Hide()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
Clear()
|
||||
{
|
||||
this.Payload_D.title = ''
|
||||
this.Payload_D.storage_limit = ''
|
||||
this.Payload_D.description = ''
|
||||
this.Payload_D.from_date = ''
|
||||
this.Payload_D.to_date = ''
|
||||
this.Payload_D.months = '1'
|
||||
this.Payload_D.is_active = true
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
initData: function(NewValue) {
|
||||
if( NewValue === undefined ) this.Clear()
|
||||
else
|
||||
{
|
||||
this.Payload_D.title = NewValue.title
|
||||
this.Payload_D.storage_limit = NewValue.storage_limit.toString()
|
||||
this.Payload_D.description = NewValue.description
|
||||
this.Payload_D.from_date = NewValue.from_date
|
||||
this.Payload_D.to_date = NewValue.to_date
|
||||
this.Payload_D.months = NewValue.months.toString()
|
||||
this.Payload_D.is_active = NewValue.is_active
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
<template>
|
||||
<b-modal id="modal-edit-plan" v-bind:centered="true" size="lg" body-class="pb-0">
|
||||
<!-- Header -->
|
||||
<template v-slot:modal-header="{ close }">
|
||||
<h2 class="text-primary m-0">
|
||||
<span v-if="editing">Edit Rules</span>
|
||||
<span v-else>Add Rule</span>
|
||||
</h2>
|
||||
<img class="cursor-pointer" src="@/assets/svg/cross.svg" alt="close-icon" v-on:click="close()">
|
||||
</template>
|
||||
|
||||
<!-- Body -->
|
||||
<template v-slot:default>
|
||||
<ValidationObserver ref="form" v-slot="{}">
|
||||
<b-form class="d-flex flex-column" v-on:submit.prevent>
|
||||
<b-row>
|
||||
<b-col md="4">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.price"
|
||||
label="Price"
|
||||
name="price"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="4">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.discounted_price"
|
||||
label="Discounted Price"
|
||||
name="discounted_price"
|
||||
rules="numeric"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="4">
|
||||
<TextboxComponent
|
||||
v-model="Payload_D.value"
|
||||
label="Description"
|
||||
name="description"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col md="4">
|
||||
<DropdownComponent
|
||||
v-model="Payload_D.rule_type"
|
||||
label="Rule Type"
|
||||
name="rule_type"
|
||||
v-bind:options="RuleTypeOptions_D"
|
||||
placeholder="Select a rule type"
|
||||
/>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-form>
|
||||
{{ Payload_D }}
|
||||
</ValidationObserver>
|
||||
</template>
|
||||
|
||||
<!-- Footer -->
|
||||
<template v-slot:modal-footer="{ hide }">
|
||||
<b-button
|
||||
class="mr-1"
|
||||
variant="primary"
|
||||
v-ripple.400="'rgba(255, 255, 255, 0.15)'"
|
||||
v-on:click="OnSubmit(hide)"
|
||||
>
|
||||
<span v-if="editing">Update Rule</span>
|
||||
<span v-else>Save Rule</span>
|
||||
</b-button>
|
||||
or
|
||||
<a class="text-primary" v-on:click="hide()">Cancel</a>
|
||||
</template>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BForm, BButton, BRow, BCol } from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
|
||||
export default {
|
||||
name: 'EditPlanModalComponent',
|
||||
|
||||
components: {
|
||||
BForm,
|
||||
BButton,
|
||||
BRow,
|
||||
BCol,
|
||||
},
|
||||
|
||||
directives: {
|
||||
Ripple,
|
||||
},
|
||||
|
||||
props: {
|
||||
// The initial data to fill the inputs with.
|
||||
initData: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({
|
||||
price: '',
|
||||
discounted_price: '',
|
||||
value: '',
|
||||
rule_type: '',
|
||||
plan_id: '1',
|
||||
})
|
||||
},
|
||||
|
||||
// Whether we're in editing mode or create mode.
|
||||
// It's type is Boolean | null.
|
||||
editing: {
|
||||
required: true,
|
||||
},
|
||||
|
||||
plans: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Payload_D: this.initData,
|
||||
|
||||
RuleTypeOptions_D: [
|
||||
{ value: 1, title: 'General' },
|
||||
{ value: 2, title: 'Admin' },
|
||||
{ value: 3, title: 'User' },
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OnSubmit(Hide)
|
||||
{
|
||||
this.$refs.form.validate().then(async success => {
|
||||
if( success )
|
||||
{
|
||||
// NOTE(pooya): Interestingly, if you remove the
|
||||
// following line, the payload will be passed as empty!
|
||||
const tmp = Object.assign({}, this.Payload_D)
|
||||
|
||||
this.$emit('submit', tmp)
|
||||
Hide()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
Clear()
|
||||
{
|
||||
this.Payload_D.price = ''
|
||||
this.Payload_D.discounted_price = ''
|
||||
this.Payload_D.value = ''
|
||||
this.Payload_D.rule_type = '1'
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
initData: function(NewValue) {
|
||||
if( NewValue === undefined ) this.Clear()
|
||||
else
|
||||
{
|
||||
this.Payload_D.price = NewValue.price
|
||||
this.Payload_D.discounted_price = NewValue.discounted_price
|
||||
this.Payload_D.value = NewValue.value
|
||||
this.Payload_D.rule_type = NewValue.rule_type
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import XTbl, { Xtc } from '@/components/x-table/index'
|
||||
|
||||
const tbl = new XTbl('admin/list/subscription-contract-user', 'Subscription Contract Users')
|
||||
// tbl.add(new Xtc('title', 'Title'))
|
||||
// tbl.add(new Xtc('description', 'Description'))
|
||||
// tbl.add(new Xtc('storage_limit', 'Storage Limit').noSort().renderSlot('storage_limit'))
|
||||
// tbl.add(new Xtc('from_date', 'From').noSort().renderSlot('from_date'))
|
||||
// tbl.add(new Xtc('to_date', 'To').noSort().renderSlot('to_date'))
|
||||
// tbl.add(new Xtc('months', 'Active Months'))
|
||||
tbl.add(new Xtc('action', 'Actions').noSort().renderSlot('actions'))
|
||||
|
||||
export default tbl
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import XTbl, { Xtc } from '@/components/x-table/index'
|
||||
|
||||
const tbl = new XTbl('admin/list/subscription-contract', 'Subscription Contracts')
|
||||
tbl.add(new Xtc('allowed_delay_days', 'Allowed Delay Days'))
|
||||
tbl.add(new Xtc('installments_count', 'Installments Count'))
|
||||
tbl.add(new Xtc('total_price', 'Price'))
|
||||
tbl.add(new Xtc('discounted_price', 'Discounted Price'))
|
||||
tbl.add(new Xtc('payable_amount', 'Payable Amount'))
|
||||
tbl.add(new Xtc('payed_amount', 'Payed Amount'))
|
||||
tbl.add(new Xtc('storage_limit', 'Storage Limit').noSort().renderSlot('storage_limit'))
|
||||
tbl.add(new Xtc('storage_usage', 'Storage Usage').noSort())
|
||||
tbl.add(new Xtc('from_date', 'From').noSort().renderSlot('from_date'))
|
||||
tbl.add(new Xtc('to_date', 'To').noSort().renderSlot('to_date'))
|
||||
tbl.add(new Xtc('user_limit', 'User Limit'))
|
||||
// tbl.add(new Xtc('action', 'Actions').noSort().renderSlot('actions'))
|
||||
|
||||
export default tbl
|
||||
|
||||
|
||||
|
||||
// What are the following?
|
||||
// installments_count: 1
|
||||
// status: 2
|
||||
// type: 3
|
||||
// user_usage: 1
|
||||
|
||||
// owner_id: 14
|
||||
// plan_id: null
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import XTbl, { Xtc } from '@/components/x-table/index'
|
||||
|
||||
const tbl = new XTbl('admin/list/subscription-payment', 'Subscription Payments')
|
||||
tbl.add(new Xtc('amount', 'Amount'))
|
||||
tbl.add(new Xtc('payed_at', 'Payed At').noSort().renderSlot('payed_at'))
|
||||
tbl.add(new Xtc('payment_dead_line', 'Payment Deadline').noSort().renderSlot('payment_dead_line'))
|
||||
tbl.add(new Xtc('tracking_code', 'Tracking_Code'))
|
||||
// tbl.add(new Xtc('action', 'Actions').noSort().renderSlot('actions'))
|
||||
|
||||
export default tbl
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
import XTbl, { Xtc } from '@/components/x-table/index'
|
||||
|
||||
const tbl = new XTbl('admin/list/subscription-plan', 'Law Firms')
|
||||
const tbl = new XTbl('admin/list/subscription-plan', 'Subscription Plans')
|
||||
tbl.add(new Xtc('title', 'Title'))
|
||||
tbl.add(new Xtc('description', 'Description'))
|
||||
tbl.add(new Xtc('storage_limit', 'Storage Limit').noSort().renderSlot('storage_limit'))
|
||||
tbl.add(new Xtc('from_date', 'From').noSort().renderSlot('from_date'))
|
||||
tbl.add(new Xtc('to_date', 'To').noSort().renderSlot('to_date'))
|
||||
tbl.add(new Xtc('months', 'Active Months'))
|
||||
tbl.add(new Xtc('is_active', 'Is Active').noSort().renderSlot('is_active'))
|
||||
tbl.add(new Xtc('action', 'Actions').noSort().renderSlot('actions'))
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
import XTbl, { Xtc } from '@/components/x-table/index'
|
||||
|
||||
const tbl = new XTbl('admin/list/subscription-rule', 'Subscription Plans')
|
||||
tbl.add(new Xtc('price', 'Price'))
|
||||
tbl.add(new Xtc('discounted_price', 'Discounted Price'))
|
||||
tbl.add(new Xtc('value', 'Value'))
|
||||
tbl.add(new Xtc('plan_id', 'Plan'))
|
||||
tbl.add(new Xtc('priority', 'Priority'))
|
||||
tbl.add(new Xtc('rule_type', 'Rule Type'))
|
||||
// tbl.add(new Xtc('action', 'Actions').noSort().renderSlot('actions'))
|
||||
|
||||
export default tbl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// plan_id: 1
|
||||
// priority: 1
|
||||
// rule_type: 1
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import XTbl, { Xtc } from '@/components/x-table/index'
|
||||
|
||||
const tbl = new XTbl('admin/list/subscription', 'Subscriptions')
|
||||
tbl.add(new Xtc('charge', 'Charge'))
|
||||
// tbl.add(new Xtc('storage_limit', 'Storage Limit').noSort().renderSlot('storage_limit'))
|
||||
tbl.add(new Xtc('last_deposit_date', 'Last Deposit').noSort().renderSlot('last_deposit_date'))
|
||||
// tbl.add(new Xtc('to_date', 'To').noSort().renderSlot('to_date'))
|
||||
// tbl.add(new Xtc('months', 'Active Months'))
|
||||
// tbl.add(new Xtc('action', 'Actions').noSort().renderSlot('actions'))
|
||||
|
||||
export default tbl
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import XTbl, { Xtc } from '@/components/x-table/index'
|
||||
|
||||
const tbl = new XTbl('admin/list/subscription-transaction', 'Subscription Transactions')
|
||||
tbl.add(new Xtc('amount', 'Amount'))
|
||||
tbl.add(new Xtc('object_obj.title', 'Plan'))
|
||||
tbl.add(new Xtc('created_at', 'Transaction Date').noSort().renderSlot('created_at'))
|
||||
tbl.add(new Xtc('request_body.currency', 'Currency'))
|
||||
tbl.add(new Xtc('request_body.merchant_code', 'Merchant Code'))
|
||||
tbl.add(new Xtc('request_body.user_name', 'User'))
|
||||
tbl.add(new Xtc('request_body.user_email', "User's Email"))
|
||||
|
||||
export default tbl
|
||||
|
|
@ -193,7 +193,6 @@ import { required, email } from '@validations'
|
|||
import { togglePasswordVisibility } from '@core/mixins/ui/forms'
|
||||
import store from '@/store/index'
|
||||
import { login, setAccessToken, setUserData, getHomeRouteForLoggedInUser } from '@/auth/utils'
|
||||
import { Log } from '@/plugins/core'
|
||||
|
||||
import ToastificationContent from '@core/components/toastification/ToastificationContent.vue'
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue