mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-28 11:00:39 +00:00
- Flat fee implementation
- Fixed/Metered plan pages
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div class="card shadow-card">
|
||||
<div class="mb-6">
|
||||
<router-link :to="{name: 'PlanCreate'}">
|
||||
<router-link :to="{name: createPlanRoute}">
|
||||
<MobileActionButton icon="plus">
|
||||
{{ $t('admin_page_plans.create_plan_button') }}
|
||||
</MobileActionButton>
|
||||
@@ -12,12 +12,48 @@
|
||||
<!--Datatable-->
|
||||
<DatatableWrapper @data="plans = $event" @init="isLoading = false" api="/api/subscriptions/admin/plans" :paginator="true" :columns="columns">
|
||||
<template slot-scope="{ row }">
|
||||
<tr class="border-b dark:border-opacity-5 border-light border-dashed">
|
||||
|
||||
<!--Metered subscription-->
|
||||
<tr v-if="config.subscriptionType === 'metered'" class="border-b dark:border-opacity-5 border-light border-dashed">
|
||||
<td>
|
||||
<router-link class="text-sm font-bold" :to="{name: 'PlanMeteredSettings', params: {id: row.data.id}}">
|
||||
{{ row.data.attributes.name }}
|
||||
</router-link>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-sm font-bold">
|
||||
{{ row.data.attributes.currency }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-sm font-bold capitalize">
|
||||
{{ row.data.attributes.interval }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-sm font-bold">
|
||||
{{ row.data.attributes.subscribers }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex space-x-2 w-full justify-end">
|
||||
<router-link class="flex items-center justify-center w-8 h-8 rounded-md hover:bg-green-100 dark:bg-2x-dark-foreground bg-light-background transition-colors" :to="{name: 'PlanSettings', params: {id: row.data.id}}">
|
||||
<Edit2Icon size="15" class="opacity-75" />
|
||||
</router-link>
|
||||
<router-link class="flex items-center justify-center w-8 h-8 rounded-md hover:bg-red-100 dark:bg-2x-dark-foreground bg-light-background transition-colors" :to="{name: 'PlanDelete', params: {id: row.data.id}}">
|
||||
<Trash2Icon size="15" class="opacity-75" />
|
||||
</router-link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!--Fixed subscription-->
|
||||
<tr v-if="config.subscriptionType === 'fixed'" class="border-b dark:border-opacity-5 border-light border-dashed">
|
||||
<td class="py-4">
|
||||
<SwitchInput @input="$updateInput(`/subscriptions/admin/plans/${row.data.id}`, 'visible', row.data.attributes.visible)" v-model="row.data.attributes.visible" :state="row.data.attributes.visible" class="switch"/>
|
||||
</td>
|
||||
<td>
|
||||
<router-link class="text-sm font-bold" :to="{name: 'PlanSettings', params: {id: row.data.id}}">
|
||||
<router-link class="text-sm font-bold" :to="{name: 'PlanFixedSettings', params: {id: row.data.id}}">
|
||||
{{ row.data.attributes.name }}
|
||||
</router-link>
|
||||
</td>
|
||||
@@ -63,7 +99,7 @@
|
||||
:title="$t('admin_page_plans.empty.title')"
|
||||
:description="$t('admin_page_plans.empty.description')"
|
||||
>
|
||||
<router-link :to="{name: 'PlanCreate'}" tag="p">
|
||||
<router-link :to="{name: 'CreateFixedPlan'}" tag="p">
|
||||
<ButtonBase button-style="theme">{{ $t('admin_page_plans.empty.button') }}</ButtonBase>
|
||||
</router-link>
|
||||
</EmptyPageContent>-->
|
||||
@@ -116,51 +152,80 @@
|
||||
isEmptyPlans() {
|
||||
return ! this.isLoading && this.plans.length === 0 && this.config.stripe_public_key
|
||||
},
|
||||
stripeIsNotConfigured() {
|
||||
return ! this.config.stripe_public_key
|
||||
},
|
||||
stripeConfiguredWithPlans() {
|
||||
return ! this.isLoading && this.config.stripe_public_key
|
||||
}
|
||||
createPlanRoute() {
|
||||
return {
|
||||
metered: 'CreateMeteredPlan',
|
||||
fixed: 'CreateFixedPlan',
|
||||
}[this.config.subscriptionType]
|
||||
},
|
||||
columns() {
|
||||
return {
|
||||
metered: [
|
||||
{
|
||||
label: this.$t('Name'),
|
||||
field: 'name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Currency'),
|
||||
field: 'currency',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Interval'),
|
||||
field: 'interval',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_plans.table.subscribers'),
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
sortable: false
|
||||
},
|
||||
],
|
||||
fixed: [
|
||||
{
|
||||
label: this.$t('Visibility'),
|
||||
field: 'visible',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Name'),
|
||||
field: 'name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Price'),
|
||||
field: 'amount',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Interval'),
|
||||
field: 'interval',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_plans.table.subscribers'),
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
label: this.$t('Storage'),
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
sortable: false
|
||||
},
|
||||
],
|
||||
}[this.config.subscriptionType]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
plans: [],
|
||||
columns: [
|
||||
{
|
||||
label: this.$t('Visibility'),
|
||||
field: 'visible',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Name'),
|
||||
field: 'name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Price'),
|
||||
field: 'amount',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Interval'),
|
||||
field: 'interval',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_plans.table.subscribers'),
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
label: this.$t('Storage'),
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
sortable: false
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
+2
-2
@@ -81,7 +81,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppInputText from "../../../components/Admin/AppInputText";
|
||||
import AppInputText from "../../../../components/Admin/AppInputText";
|
||||
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
|
||||
import SelectInput from '/resources/js/components/Others/Forms/SelectInput'
|
||||
import ImageInput from '/resources/js/components/Others/Forms/ImageInput'
|
||||
@@ -97,7 +97,7 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'PlanCreate',
|
||||
name: 'CreateFixedPlan',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<ValidationObserver @submit.prevent="createPlan" ref="createPlan" v-slot="{ invalid }" tag="form">
|
||||
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('Details') }}
|
||||
</FormLabel>
|
||||
|
||||
<!--Name-->
|
||||
<ValidationProvider tag="div" mode="passive" name="Name" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('admin_page_plans.form.name')">
|
||||
<input v-model="plan.name" :placeholder="$t('admin_page_plans.form.name_plac')" type="text" :class="{'border-red-700': errors[0]}" class="focus-border-theme input-dark" />
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<!--Description-->
|
||||
<ValidationProvider tag="div" mode="passive" name="Description" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('admin_page_plans.form.description')">
|
||||
<textarea v-model="plan.description" :placeholder="$t('admin_page_plans.form.description_plac')" :class="{'border-red-700': errors[0]}" class="focus-border-theme input-dark"></textarea>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<!--Currency-->
|
||||
<ValidationProvider tag="div" mode="passive" name="Currency" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('Currency')" class="w-full" :is-last="true">
|
||||
<SelectInput v-model="plan.currency" :options="currencyList" :placeholder="$t('Select plan currency')" :isError="errors[0]" />
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('Pricing') }}
|
||||
</FormLabel>
|
||||
|
||||
<div class="flex space-x-4">
|
||||
<!--Price-->
|
||||
<ValidationProvider tag="div" mode="passive" name="Price" rules="required" v-slot="{ errors }" class="w-full">
|
||||
<AppInputText :title="$t('admin_page_plans.form.price')" class="w-full">
|
||||
<input v-model="plan.amount" :placeholder="$t('admin_page_plans.form.price_plac')" type="number" step="0.01" min="1" max="999999999999" :class="{'border-red-700': errors[0]}" class="focus-border-theme input-dark" />
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('Features') }}
|
||||
</FormLabel>
|
||||
|
||||
<!--Storage Capacity-->
|
||||
<ValidationProvider tag="div" mode="passive" name="Max Storage Capacity" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('admin_page_plans.form.storage')" :description="$t('admin_page_plans.form.storage_helper')">
|
||||
<input v-model="plan.features.max_storage_amount" :placeholder="$t('admin_page_plans.form.storage_plac')" type="number" min="1" max="999999999" :class="{'border-red-700': errors[0]}" class="focus-border-theme input-dark" />
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<!--Team Members-->
|
||||
<ValidationProvider tag="div" mode="passive" name="Max Team Members" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('Team Members')" :description="$t('To set unlimited team members, type -1 into form')" :is-last="true">
|
||||
<input v-model="plan.features.max_team_members" :placeholder="$t('Add max team members in number')" type="number" min="1" max="999999999" :class="{'border-red-700': errors[0]}" class="focus-border-theme input-dark" />
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<InfoBox v-if="isError" type="error" style="margin-top: 40px">
|
||||
<p>{{ errorMessage }}</p>
|
||||
</InfoBox>
|
||||
|
||||
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit">
|
||||
{{ $t('admin_page_plans.create_plan_button') }}
|
||||
</ButtonBase>
|
||||
</ValidationObserver>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppInputText from "../../../../components/Admin/AppInputText";
|
||||
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
|
||||
import SelectInput from '/resources/js/components/Others/Forms/SelectInput'
|
||||
import ImageInput from '/resources/js/components/Others/Forms/ImageInput'
|
||||
import MobileHeader from '/resources/js/components/Mobile/MobileHeader'
|
||||
import FormLabel from '/resources/js/components/Others/Forms/FormLabel'
|
||||
import SectionTitle from '/resources/js/components/Others/SectionTitle'
|
||||
import ButtonBase from '/resources/js/components/FilesView/ButtonBase'
|
||||
import PageHeader from '/resources/js/components/Others/PageHeader'
|
||||
import InfoBox from '/resources/js/components/Others/Forms/InfoBox'
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '/resources/js/bus'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'CreateMeteredPlan',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
SectionTitle,
|
||||
AppInputText,
|
||||
MobileHeader,
|
||||
SelectInput,
|
||||
ButtonBase,
|
||||
ImageInput,
|
||||
PageHeader,
|
||||
FormLabel,
|
||||
required,
|
||||
InfoBox,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'currencyList',
|
||||
'intervalList',
|
||||
])
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
errorMessage: undefined,
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
plan: {
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
interval: undefined,
|
||||
amount: undefined,
|
||||
currency: undefined,
|
||||
features: {
|
||||
max_storage_amount: undefined,
|
||||
max_team_members: undefined,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async createPlan() {
|
||||
|
||||
// Validate fields
|
||||
const isValid = await this.$refs.createPlan.validate();
|
||||
|
||||
if (!isValid) return;
|
||||
|
||||
// Start loading
|
||||
this.isLoading = true
|
||||
|
||||
axios
|
||||
.post('/api/subscriptions/plans', this.plan)
|
||||
.then(response => {
|
||||
|
||||
// Show toaster
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: this.$t('toaster.plan_created'),
|
||||
})
|
||||
|
||||
// Go to User page
|
||||
this.$router.push({name: 'PlanSettings', params: {id: response.data.data.id}})
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
// Validation errors
|
||||
if (error.response.status === 422) {
|
||||
|
||||
if (error.response.data.errors['max_storage_amount']) {
|
||||
this.$refs.createPlan.setErrors({
|
||||
'Max Storage Capacity': this.$t('errors.capacity_digit')
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (error.response.status === 500) {
|
||||
this.isError = true
|
||||
this.errorMessage = error.response.data.message
|
||||
}
|
||||
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
+5
-5
@@ -11,7 +11,7 @@
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<CardNavigation :pages="pages" class="-mx-3.5" />
|
||||
<CardNavigation :pages="pages" class="-mx-1.5" />
|
||||
</div>
|
||||
|
||||
<router-view v-if="! isLoading" :plan="plan" />
|
||||
@@ -28,7 +28,7 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'Plan',
|
||||
name: 'FixedPlan',
|
||||
components: {
|
||||
CardNavigation,
|
||||
Spinner,
|
||||
@@ -40,15 +40,15 @@
|
||||
pages: [
|
||||
{
|
||||
title: this.$t('admin_page_plans.tabs.settings'),
|
||||
route: 'PlanSettings',
|
||||
route: 'PlanFixedSettings',
|
||||
},
|
||||
{
|
||||
title: this.$t('admin_page_plans.tabs.subscribers'),
|
||||
route: 'PlanSubscribers',
|
||||
route: 'PlanFixedSubscribers',
|
||||
},
|
||||
{
|
||||
title: this.$t('admin_page_plans.tabs.delete'),
|
||||
route: 'PlanDelete',
|
||||
route: 'PlanFixedDelete',
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="plan" class="card shadow-card pb-0 sticky top-0 z-10">
|
||||
|
||||
<div class="mb-2">
|
||||
<h1 class="font-bold text-xl">
|
||||
{{ plan.attributes.name }}
|
||||
</h1>
|
||||
<small class="text-sm font-bold text-gray-500">
|
||||
{{ $t('30 Days intervals') }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<CardNavigation :pages="pages" class="-mx-1.5" />
|
||||
</div>
|
||||
|
||||
<router-view v-if="! isLoading" :plan="plan" />
|
||||
|
||||
<div id="loader" v-if="isLoading">
|
||||
<Spinner></Spinner>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CardNavigation from "../../../components/Admin/CardNavigation"
|
||||
import Spinner from '/resources/js/components/FilesView/Spinner'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'MeteredPlan',
|
||||
components: {
|
||||
CardNavigation,
|
||||
Spinner,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
plan: undefined,
|
||||
pages: [
|
||||
{
|
||||
title: this.$t('admin_page_plans.tabs.settings'),
|
||||
route: 'PlanMeteredSettings',
|
||||
},
|
||||
{
|
||||
title: this.$t('admin_page_plans.tabs.subscribers'),
|
||||
route: 'PlanMeteredSubscribers',
|
||||
},
|
||||
{
|
||||
title: this.$t('admin_page_plans.tabs.delete'),
|
||||
route: 'PlanMeteredDelete',
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get('/api/subscriptions/admin/plans/' + this.$route.params.id)
|
||||
.then(response => {
|
||||
this.plan = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('Details') }}
|
||||
</FormLabel>
|
||||
|
||||
<!--Visible-->
|
||||
<AppInputSwitch :title="$t('admin_page_plans.form.status')" :description="$t('admin_page_plans.form.status_help')">
|
||||
<SwitchInput @input="$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'visible', plan.attributes.visible)" v-model="plan.attributes.visible" class="switch" :state="plan.attributes.visible"/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<!--Name-->
|
||||
<AppInputText :title="$t('admin_page_plans.form.name')">
|
||||
<input @input="$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'name', plan.attributes.name)" v-model="plan.attributes.name" :placeholder="$t('admin_page_plans.form.name_plac')" type="text" class="focus-border-theme input-dark"/>
|
||||
</AppInputText>
|
||||
|
||||
<!--Description-->
|
||||
<AppInputText :title="$t('admin_page_plans.form.description')">
|
||||
<textarea @input="$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'description', plan.attributes.description)" v-model="plan.attributes.description" :placeholder="$t('admin_page_plans.form.description_plac')" class="focus-border-theme input-dark"></textarea>
|
||||
</AppInputText>
|
||||
|
||||
<InfoBox style="margin-bottom: 0">
|
||||
<p>{{ $t('Price change is not possible. If you would like to change your price or currency, please feel free to create a new plan.') }}</p>
|
||||
</InfoBox>
|
||||
</div>
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('Features') }}
|
||||
</FormLabel>
|
||||
|
||||
<!--Storage Capacity-->
|
||||
<AppInputText :title="$t('admin_page_plans.form.storage')" :description="$t('admin_page_plans.form.storage_helper')">
|
||||
<input @input="$updateInput(`/subscriptions/plans/${$route.params.id}/features`, 'max_storage_amount', plan.attributes.features.max_storage_amount)" v-model="plan.attributes.features.max_storage_amount" :placeholder="$t('admin_page_plans.form.storage_plac')" type="number" min="1" max="999999999" class="focus-border-theme input-dark"/>
|
||||
</AppInputText>
|
||||
|
||||
<!--Team Members-->
|
||||
<AppInputText :title="$t('Max Team Members')" is-last="true">
|
||||
<input @input="$updateInput(`/subscriptions/plans/${$route.params.id}/features`, 'max_team_members', plan.attributes.features.max_team_members)" v-model="plan.attributes.features.max_team_members" :placeholder="$t('Add max team members in number')" type="number" min="1" max="999999999" class="focus-border-theme input-dark"/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SwitchInput from '/resources/js/components/Others/Forms/SwitchInput'
|
||||
import SelectInput from '/resources/js/components/Others/Forms/SelectInput'
|
||||
import AppInputSwitch from "../../../../components/Admin/AppInputSwitch"
|
||||
import FormLabel from '/resources/js/components/Others/Forms/FormLabel'
|
||||
import AppInputText from "../../../../components/Admin/AppInputText"
|
||||
import InfoBox from '/resources/js/components/Others/Forms/InfoBox'
|
||||
|
||||
export default {
|
||||
name: 'PlanSettings',
|
||||
props: [
|
||||
'plan'
|
||||
],
|
||||
components: {
|
||||
AppInputSwitch,
|
||||
AppInputText,
|
||||
SwitchInput,
|
||||
SelectInput,
|
||||
FormLabel,
|
||||
InfoBox,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: undefined
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.visible = this.plan.attributes.visible
|
||||
}
|
||||
}
|
||||
</script>
|
||||
+87
-33
@@ -4,7 +4,34 @@
|
||||
|
||||
<!--Table data content-->
|
||||
<template slot-scope="{ row }">
|
||||
<tr class="border-b dark:border-opacity-5 border-light border-dashed">
|
||||
<tr v-if="config.subscriptionType === 'metered'" class="border-b dark:border-opacity-5 border-light border-dashed">
|
||||
<td>
|
||||
<router-link class="flex items-center" :to="{name: 'UserDetail', params: {id: row.data.relationships.user.data.id}}">
|
||||
<MemberAvatar
|
||||
:is-border="false"
|
||||
:size="36"
|
||||
:member="row.data.relationships.user"
|
||||
/>
|
||||
<div class="ml-3">
|
||||
<b class="text-sm font-bold block max-w-1 overflow-hidden overflow-ellipsis whitespace-nowrap" style="max-width: 155px;">
|
||||
{{ row.data.relationships.user.data.attributes.name }}
|
||||
</b>
|
||||
<span class="block text-xs dark:text-gray-500 text-gray-600">
|
||||
{{ row.data.relationships.user.data.attributes.email }}
|
||||
</span>
|
||||
</div>
|
||||
</router-link>
|
||||
</td>
|
||||
<td class="py-5">
|
||||
<span class="text-sm font-bold">
|
||||
{{ row.data.attributes.renews_at }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<img class="inline-block max-h-5" :src="$getPaymentLogo(row.data.attributes.driver)" :alt="row.data.attributes.driver">
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="config.subscriptionType === 'fixed'" class="border-b dark:border-opacity-5 border-light border-dashed">
|
||||
<td>
|
||||
<router-link class="flex items-center" :to="{name: 'UserDetail', params: {id: row.data.relationships.user.data.id}}">
|
||||
<MemberAvatar
|
||||
@@ -69,6 +96,7 @@
|
||||
import PageTab from '/resources/js/components/Others/Layout/PageTab'
|
||||
import InfoBox from '/resources/js/components/Others/Forms/InfoBox'
|
||||
import axios from 'axios'
|
||||
import {mapGetters} from "vuex";
|
||||
|
||||
export default {
|
||||
name: 'PlanSubscribers',
|
||||
@@ -84,42 +112,68 @@
|
||||
PageTab,
|
||||
InfoBox,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'config'
|
||||
]),
|
||||
columns() {
|
||||
return {
|
||||
metered: [
|
||||
{
|
||||
label: this.$t('admin_page_user.table.name'),
|
||||
field: 'user_id',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Renews At'),
|
||||
field: 'created_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Service'),
|
||||
field: 'driver',
|
||||
sortable: true
|
||||
},
|
||||
],
|
||||
fixed: [
|
||||
{
|
||||
label: this.$t('admin_page_user.table.name'),
|
||||
field: 'user_id',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Status'),
|
||||
field: 'status',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Note'),
|
||||
field: 'plan.name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Renews At'),
|
||||
field: 'created_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Ends At'),
|
||||
field: 'ends_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Service'),
|
||||
field: 'driver',
|
||||
sortable: true
|
||||
},
|
||||
]
|
||||
}[this.config.subscriptionType]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
subscribers: undefined,
|
||||
isLoading: true,
|
||||
columns: [
|
||||
{
|
||||
label: this.$t('admin_page_user.table.name'),
|
||||
field: 'user_id',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Status'),
|
||||
field: 'status',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Note'),
|
||||
field: 'plan.name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Renews At'),
|
||||
field: 'created_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Ends At'),
|
||||
field: 'ends_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('Service'),
|
||||
field: 'driver',
|
||||
sortable: true
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -68,7 +68,7 @@
|
||||
:title="$t('admin_page_plans.empty.title')"
|
||||
:description="$t('admin_page_plans.empty.description')"
|
||||
>
|
||||
<router-link :to="{name: 'PlanCreate'}" tag="p">
|
||||
<router-link :to="{name: 'CreateFixedPlan'}" tag="p">
|
||||
<ButtonBase button-style="theme">{{ $t('admin_page_plans.empty.button') }}</ButtonBase>
|
||||
</router-link>
|
||||
</EmptyPageContent>-->
|
||||
|
||||
Reference in New Issue
Block a user