mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-18 00:02:15 +00:00
frontend/backend update
This commit is contained in:
@@ -125,6 +125,7 @@
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
font-size: 16px;
|
||||
text-decoration: none;
|
||||
color: #1b2539;
|
||||
}
|
||||
|
||||
#auth {
|
||||
|
||||
@@ -38,6 +38,15 @@
|
||||
background: rgba($theme, .1);
|
||||
}
|
||||
|
||||
&.theme-solid {
|
||||
color: white;
|
||||
background: $theme;
|
||||
|
||||
path {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
&.danger {
|
||||
color: $danger;
|
||||
background: rgba($danger, .1);
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
color: $yellow;
|
||||
background: rgba($yellow, 0.1);
|
||||
}
|
||||
|
||||
&.green {
|
||||
color: $theme;
|
||||
background: rgba($theme, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
|
||||
145
resources/js/components/Others/PlanPricingTables.vue
Normal file
145
resources/js/components/Others/PlanPricingTables.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div class="plans-wrapper">
|
||||
<article class="plan" v-for="(plan, i) in plans" :key="i">
|
||||
<div class="plan-wrapper">
|
||||
<header class="plan-header">
|
||||
<div class="icon">
|
||||
<hard-drive-icon size="26"></hard-drive-icon>
|
||||
</div>
|
||||
<h1 class="title">{{ plan.data.attributes.name }}</h1>
|
||||
<h2 class="description">{{ plan.data.attributes.description }}</h2>
|
||||
</header>
|
||||
<section class="plan-features">
|
||||
<b class="storage-size">{{ plan.data.attributes.capacity_formatted }}</b>
|
||||
<span class="storage-description">Of Storage Capacity</span>
|
||||
</section>
|
||||
<footer class="plan-footer">
|
||||
<b class="price">
|
||||
{{ plan.data.attributes.price }} USD/Mo.
|
||||
</b>
|
||||
<ButtonBase @click.native="selectPlan(plan)" type="submit" button-style="secondary" class="sign-in-button">
|
||||
Sign Up
|
||||
</ButtonBase>
|
||||
</footer>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import {HardDriveIcon} from "vue-feather-icons"
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'PlanPricingTables',
|
||||
components: {
|
||||
HardDriveIcon,
|
||||
ButtonBase,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
plans: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectPlan(plan) {
|
||||
this.$emit('selected-plan', plan)
|
||||
this.$router.push({name: 'UpgradeBilling'})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get('/api/public/pricing')
|
||||
.then(response => {
|
||||
this.plans = response.data.data
|
||||
this.$emit('load', false)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.plan {
|
||||
text-align: center;
|
||||
flex: 0 0 33%;
|
||||
padding: 0 25px;
|
||||
|
||||
.plan-wrapper {
|
||||
box-shadow: 0 7px 20px 5px hsla(220, 36%, 16%, 0.03);
|
||||
padding: 25px;
|
||||
border-radius: 8px;
|
||||
@include transition;
|
||||
|
||||
&:hover {
|
||||
@include transform(translateY(-20px) scale(1.05));
|
||||
box-shadow: 0 15px 25px 5px hsla(220, 36%, 16%, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.plan-header {
|
||||
|
||||
.icon {
|
||||
path, line, polyline, rect, circle {
|
||||
color: $theme;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
@include font-size(22);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include font-size(14);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.plan-features {
|
||||
margin: 65px 0;
|
||||
|
||||
.storage-size {
|
||||
@include font-size(48);
|
||||
font-weight: 900;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.storage-description {
|
||||
display: block;
|
||||
@include font-size(15);
|
||||
font-weight: 800;
|
||||
}
|
||||
}
|
||||
|
||||
.plan-footer {
|
||||
|
||||
.sign-in-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.price {
|
||||
color: $theme;
|
||||
@include font-size(18);
|
||||
display: block;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.plans-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -25px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
span, a.page-link {
|
||||
@include font-size(15);
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
padding: 10px 35px 10px 0;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.content-sidebar {
|
||||
background: linear-gradient(0deg, rgba(246, 245, 241, 0.4) 0%, rgba(243, 244, 246, 0.4) 100%);
|
||||
//background: linear-gradient(0deg, rgba(246, 245, 241, 0.4) 0%, rgba(243, 244, 246, 0.4) 100%);
|
||||
background: rgba($light_background, 0.6);
|
||||
user-select: none;
|
||||
padding-top: 25px;
|
||||
overflow-y: auto;
|
||||
|
||||
@@ -106,7 +106,8 @@
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.menu-bar {
|
||||
background: linear-gradient(180deg, rgba(246, 245, 241, 0.8) 0%, rgba(243, 244, 246, 0.8) 100%);
|
||||
//background: linear-gradient(180deg, rgba(246, 245, 241, 0.8) 0%, rgba(243, 244, 246, 0.8) 100%);
|
||||
background: $light_background;
|
||||
user-select: none;
|
||||
padding-top: 25px;
|
||||
display: grid;
|
||||
|
||||
78
resources/js/router.js
vendored
78
resources/js/router.js
vendored
@@ -10,14 +10,19 @@ import ForgottenPassword from './views/Auth/ForgottenPassword'
|
||||
import CreateNewPassword from './views/Auth/CreateNewPassword'
|
||||
|
||||
import Settings from './views/Profile'
|
||||
import Profile from './views/User/Settings'
|
||||
import Storage from './views/User/Storage'
|
||||
import Profile from './views/User/Settings'
|
||||
import Invoice from './views/User/Invoices'
|
||||
import Password from './views/User/Password'
|
||||
import Subscription from './views/User/Subscription'
|
||||
|
||||
import Trash from './views/FilePages/Trash'
|
||||
import Files from './views/FilePages/Files'
|
||||
import Password from './views/User/Password'
|
||||
import SharedFiles from './views/FilePages/SharedFiles'
|
||||
|
||||
import UpgradePlan from './views/Upgrade/UpgradePlan'
|
||||
import UpgradeBilling from './views/Upgrade/UpgradeBilling'
|
||||
|
||||
import AdminMobileMenu from './views/Mobile/AdminMobileMenu'
|
||||
|
||||
import Admin from './views/Admin'
|
||||
@@ -35,7 +40,7 @@ import Plan from './views/Admin/Plans/Plan'
|
||||
import PlanCreate from './views/Admin/Plans/PlanCreate'
|
||||
import PlanDelete from './views/Admin/Plans/PlanTabs/PlanDelete'
|
||||
import PlanSettings from './views/Admin/Plans/PlanTabs/PlanSettings'
|
||||
import PlanTransactions from './views/Admin/Plans/PlanTabs/PlanTransactions'
|
||||
import PlanSubscribers from './views/Admin/Plans/PlanTabs/PlanSubscribers'
|
||||
|
||||
// Users
|
||||
import Users from './views/Admin/Users'
|
||||
@@ -214,12 +219,12 @@ const routesAdmin = [
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'PlanTransactions',
|
||||
path: '/admin/plan/:id/transactions',
|
||||
component: PlanTransactions,
|
||||
name: 'PlanSubscribers',
|
||||
path: '/admin/plan/:id/subscribers',
|
||||
component: PlanSubscribers,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
title: 'Plan Transactions'
|
||||
title: 'Plan Subscribers'
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -271,14 +276,6 @@ const routesShared = [
|
||||
requiresAuth: false
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SharedFiles',
|
||||
path: '/shared-files',
|
||||
component: SharedFiles,
|
||||
meta: {
|
||||
requiresAuth: true
|
||||
},
|
||||
},
|
||||
]
|
||||
const routesAuth = [
|
||||
{
|
||||
@@ -315,6 +312,30 @@ const routesAuth = [
|
||||
},
|
||||
]
|
||||
const routesUser = [
|
||||
{
|
||||
name: 'Files',
|
||||
path: '/files',
|
||||
component: Files,
|
||||
meta: {
|
||||
requiresAuth: true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SharedFiles',
|
||||
path: '/shared-files',
|
||||
component: SharedFiles,
|
||||
meta: {
|
||||
requiresAuth: true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Trash',
|
||||
path: '/trash',
|
||||
component: Trash,
|
||||
meta: {
|
||||
requiresAuth: true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Settings',
|
||||
path: '/settings',
|
||||
@@ -359,22 +380,33 @@ const routesUser = [
|
||||
title: 'Invoices'
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Subscription',
|
||||
path: '/settings/subscription',
|
||||
component: Subscription,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
title: 'Subscription'
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Files',
|
||||
path: '/files',
|
||||
component: Files,
|
||||
name: 'UpgradePlan',
|
||||
path: '/upgrade/plan',
|
||||
component: UpgradePlan,
|
||||
meta: {
|
||||
requiresAuth: true
|
||||
requiresAuth: true,
|
||||
title: 'Upgrade Plan'
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Trash',
|
||||
path: '/trash',
|
||||
component: Trash,
|
||||
name: 'UpgradeBilling',
|
||||
path: '/upgrade/billing',
|
||||
component: UpgradeBilling,
|
||||
meta: {
|
||||
requiresAuth: true
|
||||
requiresAuth: true,
|
||||
title: 'Upgrade Billing'
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
9
resources/js/store/modules/app.js
vendored
9
resources/js/store/modules/app.js
vendored
@@ -6,6 +6,7 @@ const defaultState = {
|
||||
config: undefined,
|
||||
authorized: undefined,
|
||||
homeDirectory: undefined,
|
||||
requestedPlan: undefined,
|
||||
roles: [
|
||||
{
|
||||
label: i18n.t('roles.admin'),
|
||||
@@ -57,14 +58,18 @@ const mutations = {
|
||||
CHANGE_PREVIEW(state, type) {
|
||||
state.FilePreviewType = type
|
||||
},
|
||||
STORE_REQUESTED_PLAN(state, plan) {
|
||||
state.requestedPlan = plan
|
||||
},
|
||||
}
|
||||
const getters = {
|
||||
fileInfoVisible: state => state.fileInfoPanelVisible,
|
||||
FilePreviewType: state => state.FilePreviewType,
|
||||
roles: state => state.roles,
|
||||
homeDirectory: state => state.homeDirectory,
|
||||
requestedPlan: state => state.requestedPlan,
|
||||
api: state => state.config.api,
|
||||
config: state => state.config,
|
||||
homeDirectory: state => state.homeDirectory,
|
||||
roles: state => state.roles,
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="single-page">
|
||||
<div id="page-content" class="medium-width" v-if="! isLoading">
|
||||
<div id="page-content" v-if="! isLoading">
|
||||
<MobileHeader :title="$router.currentRoute.meta.title"/>
|
||||
<PageHeader :can-back="true" :title="$router.currentRoute.meta.title"/>
|
||||
|
||||
|
||||
@@ -3,23 +3,26 @@
|
||||
<ValidationObserver v-if="gateway.attributes.slug === 'paypal'" ref="personalInformation" v-slot="{ invalid }" tag="form" class="form block-form">
|
||||
|
||||
<PageTabGroup>
|
||||
<b class="form-group-label">Settings</b>
|
||||
<div class="block-wrapper">
|
||||
<div class="input-wrapper">
|
||||
<div class="inline-wrapper">
|
||||
<label class="input-label">Status:</label>
|
||||
<div class="switch-label">
|
||||
<label class="input-label">Status:</label>
|
||||
<small class="input-help">Status of your payment gateway on website.</small>
|
||||
</div>
|
||||
<SwitchInput @input="$updateText('/gateways/paypal', 'status', paymentGateway.attributes.status)" v-model="paymentGateway.attributes.status" class="switch" :state="paymentGateway.attributes.status"/>
|
||||
</div>
|
||||
<small class="input-help">Status of your payment gateway on website.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<div class="input-wrapper">
|
||||
<div class="inline-wrapper">
|
||||
<label class="input-label">Sandbox Mode:</label>
|
||||
<div class="switch-label">
|
||||
<label class="input-label">Sandbox Mode:</label>
|
||||
<small class="input-help">With sandbox mode on, you can test your payment process on you website.</small>
|
||||
</div>
|
||||
<SwitchInput @input="$updateText('/gateways/paypal', 'sandbox', paymentGateway.attributes.sandbox)" v-model="paymentGateway.attributes.sandbox" class="switch" :state="paymentGateway.attributes.sandbox"/>
|
||||
</div>
|
||||
<small class="input-help">With sandbox mode on, you can test your payment process on you website.</small>
|
||||
</div>
|
||||
</div>
|
||||
</PageTabGroup>
|
||||
@@ -60,23 +63,26 @@
|
||||
|
||||
<ValidationObserver v-if="gateway.attributes.slug === 'stripe'" ref="personalInformation" v-slot="{ invalid }" tag="form" class="form block-form">
|
||||
<PageTabGroup>
|
||||
<b class="form-group-label">Settings</b>
|
||||
<div class="block-wrapper">
|
||||
<div class="input-wrapper">
|
||||
<div class="inline-wrapper">
|
||||
<label class="input-label">Status:</label>
|
||||
<div class="switch-label">
|
||||
<label class="input-label">Status:</label>
|
||||
<small class="input-help">Status of your payment gateway on website.</small>
|
||||
</div>
|
||||
<SwitchInput @input="$updateText('/gateways/stripe', 'status', paymentGateway.attributes.status)" v-model="paymentGateway.attributes.status" class="switch" :state="paymentGateway.attributes.status"/>
|
||||
</div>
|
||||
<small class="input-help">Status of your payment gateway on website.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<div class="input-wrapper">
|
||||
<div class="inline-wrapper">
|
||||
<label class="input-label">Sandbox Mode:</label>
|
||||
<div class="switch-label">
|
||||
<label class="input-label">Sandbox Mode:</label>
|
||||
<small class="input-help">With sandbox mode on, you can test your payment process on you website.</small>
|
||||
</div>
|
||||
<SwitchInput @input="$updateText('/gateways/stripe', 'sandbox', paymentGateway.attributes.sandbox)" v-model="paymentGateway.attributes.sandbox" class="switch" :state="paymentGateway.attributes.sandbox"/>
|
||||
</div>
|
||||
<small class="input-help">With sandbox mode on, you can test your payment process on you website.</small>
|
||||
</div>
|
||||
</div>
|
||||
</PageTabGroup>
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
},
|
||||
methods: {
|
||||
changeStatus(val, id) {
|
||||
this.$updateText('/plans/' + id + '/update', 'status', val)
|
||||
this.$updateText('/plans/' + id + '/update', 'is_active', val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="single-page">
|
||||
<div id="page-content" class="medium-width" v-if="! isLoading">
|
||||
<div id="page-content" v-if="! isLoading">
|
||||
<MobileHeader :title="$router.currentRoute.meta.title"/>
|
||||
<PageHeader :can-back="true" :title="$router.currentRoute.meta.title"/>
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link replace :to="{name: 'PlanTransactions', params: {id: plan.id}}"
|
||||
<router-link replace :to="{name: 'PlanSubscribers', params: {id: plan.id}}"
|
||||
class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<credit-card-icon size="17"></credit-card-icon>
|
||||
<users-icon size="17"></users-icon>
|
||||
</div>
|
||||
<div class="label">
|
||||
Transactions
|
||||
Subscribers
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
@@ -50,20 +50,19 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {CreditCardIcon, SettingsIcon, Trash2Icon} from 'vue-feather-icons'
|
||||
import {UsersIcon, SettingsIcon, Trash2Icon} from 'vue-feather-icons'
|
||||
import MobileHeader from '@/components/Mobile/MobileHeader'
|
||||
import SectionTitle from '@/components/Others/SectionTitle'
|
||||
import PageHeader from '@/components/Others/PageHeader'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import {mapGetters} from 'vuex'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'Gateway',
|
||||
components: {
|
||||
UsersIcon,
|
||||
Trash2Icon,
|
||||
SettingsIcon,
|
||||
CreditCardIcon,
|
||||
SectionTitle,
|
||||
MobileHeader,
|
||||
PageHeader,
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
<div class="block-wrapper">
|
||||
<div class="input-wrapper">
|
||||
<div class="inline-wrapper">
|
||||
<label class="input-label">Status:</label>
|
||||
<div class="switch-label">
|
||||
<label class="input-label">Status:</label>
|
||||
<small class="input-help">Status of your payment gateway on website.</small>
|
||||
</div>
|
||||
<SwitchInput @input="changeStatus" class="switch" :state="plan.attributes.status"/>
|
||||
</div>
|
||||
<small class="input-help">Status of your payment gateway on website.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -91,7 +93,7 @@
|
||||
},
|
||||
methods: {
|
||||
changeStatus(val) {
|
||||
this.$updateText('/plans/' + this.$route.params.id + '/update', 'status', val)
|
||||
this.$updateText('/plans/' + this.$route.params.id + '/update', 'is_active', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
118
resources/js/views/Admin/Plans/PlanTabs/PlanSubscribers.vue
Normal file
118
resources/js/views/Admin/Plans/PlanTabs/PlanSubscribers.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<PageTab v-if="subscribers">
|
||||
<PageTabGroup>
|
||||
<DatatableWrapper :paginator="true" :columns="columns" :data="subscribers" class="table">
|
||||
<template scope="{ row }">
|
||||
<tr>
|
||||
<td>
|
||||
<router-link :to="{name: 'UserDetail', params: {id: row.data.id}}">
|
||||
<DatatableCellImage
|
||||
image-size="small"
|
||||
:image="row.data.attributes.avatar"
|
||||
:title="row.data.attributes.name"
|
||||
/>
|
||||
</router-link>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.relationships.storage.data.attributes.used }}%
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.relationships.subscription.data.attributes.ends_at }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-icons">
|
||||
<router-link :to="{name: 'UserDetail', params: {id: row.data.id}}">
|
||||
<edit-2-icon size="15" class="icon icon-edit"></edit-2-icon>
|
||||
</router-link>
|
||||
<router-link :to="{name: 'UserDelete', params: {id: row.data.id}}">
|
||||
<trash2-icon size="15" class="icon icon-trash"></trash2-icon>
|
||||
</router-link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</DatatableWrapper>
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatatableCellImage from '@/components/Others/Tables/DatatableCellImage'
|
||||
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
|
||||
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
|
||||
import PageTab from '@/components/Others/Layout/PageTab'
|
||||
import {DownloadCloudIcon, Edit2Icon, Trash2Icon} from "vue-feather-icons";
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'PlanSubscribers',
|
||||
components: {
|
||||
DatatableCellImage,
|
||||
DownloadCloudIcon,
|
||||
DatatableWrapper,
|
||||
PageTabGroup,
|
||||
PageTab,
|
||||
Edit2Icon,
|
||||
Trash2Icon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
subscribers: undefined,
|
||||
columns: [
|
||||
{
|
||||
label: 'User',
|
||||
field: 'data.attributes.plan',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.storage_used'),
|
||||
field: 'data.storage.attributes.storage.used',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Expire At',
|
||||
field: 'data.subscription.data.attributes.ends_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
field: 'data.action',
|
||||
sortable: false
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get('/api/plans/' + this.$route.params.id + '/subscribers')
|
||||
.then(response => {
|
||||
this.subscribers = response.data.data
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.block-form {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,304 +0,0 @@
|
||||
<template>
|
||||
<PageTab>
|
||||
<PageTabGroup>
|
||||
<DatatableWrapper :paginator="true" :columns="columns" :data="invoices" class="table">
|
||||
<template scope="{ row }">
|
||||
<tr>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
${{ row.attributes.total }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<router-link :to="{name: 'UserInvoices', params: {id: row.relationships.user.data.id}}">
|
||||
<DatatableCellImage
|
||||
image-size="small"
|
||||
:image="row.relationships.user.data.attributes.avatar"
|
||||
:title="row.relationships.user.data.attributes.name"
|
||||
/>
|
||||
</router-link>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.attributes.created_at_formatted }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-icons">
|
||||
<download-cloud-icon size="15" class="icon"></download-cloud-icon>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</DatatableWrapper>
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatatableCellImage from '@/components/Others/Tables/DatatableCellImage'
|
||||
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
|
||||
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
|
||||
import PageTab from '@/components/Others/Layout/PageTab'
|
||||
import {DownloadCloudIcon} from "vue-feather-icons";
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'PlanTransactions',
|
||||
components: {
|
||||
DatatableCellImage,
|
||||
DownloadCloudIcon,
|
||||
DatatableWrapper,
|
||||
PageTabGroup,
|
||||
PageTab,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
invoices: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 9.99,
|
||||
plan: 'Starter Plan',
|
||||
created_at: '30. April. 2020',
|
||||
created_at_formatted: '30. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
relationships: {
|
||||
user: {
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'users',
|
||||
attributes: {
|
||||
avatar: '/avatars/6osmoXJo-avatar-01.png',
|
||||
name: 'Jane Doe',
|
||||
email: 'howdy@hi5ve.digital',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 9.99,
|
||||
plan: 'Starter Plan',
|
||||
created_at: '30. April. 2020',
|
||||
created_at_formatted: '30. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
relationships: {
|
||||
user: {
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'users',
|
||||
attributes: {
|
||||
avatar: '/avatars/dSMRCbwF-69299654_2418248648259454_4545563304688353280_o.jpg',
|
||||
name: 'Peter Papp',
|
||||
email: 'peterpapp@makingcg.com',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 49.99,
|
||||
plan: 'Business Plan',
|
||||
created_at: '31. April. 2020',
|
||||
created_at_formatted: '31. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
relationships: {
|
||||
user: {
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'users',
|
||||
attributes: {
|
||||
avatar: '/assets/images/default-avatar.png',
|
||||
name: 'Pavel Svintsitskiy',
|
||||
email: 'pashaUSA@gmail.com',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 29.99,
|
||||
plan: 'Professional Plan',
|
||||
created_at: '31. April. 2020',
|
||||
created_at_formatted: '31. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
relationships: {
|
||||
user: {
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'users',
|
||||
attributes: {
|
||||
avatar: '/avatars/lTksMdJM-6D3529EF-5D8C-4959-BEC2-4BDE80A051C2.jpeg',
|
||||
name: 'Torsten',
|
||||
email: 'torsten.hoegel@go-on-net.de',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 9.99,
|
||||
plan: 'Starter Plan',
|
||||
created_at: '30. April. 2020',
|
||||
created_at_formatted: '30. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
relationships: {
|
||||
user: {
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'users',
|
||||
attributes: {
|
||||
avatar: '/avatars/6osmoXJo-avatar-01.png',
|
||||
name: 'Jane Doe',
|
||||
email: 'howdy@hi5ve.digital',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 9.99,
|
||||
plan: 'Starter Plan',
|
||||
created_at: '30. April. 2020',
|
||||
created_at_formatted: '30. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
relationships: {
|
||||
user: {
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'users',
|
||||
attributes: {
|
||||
avatar: '/avatars/dSMRCbwF-69299654_2418248648259454_4545563304688353280_o.jpg',
|
||||
name: 'Peter Papp',
|
||||
email: 'peterpapp@makingcg.com',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 49.99,
|
||||
plan: 'Business Plan',
|
||||
created_at: '31. April. 2020',
|
||||
created_at_formatted: '31. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
relationships: {
|
||||
user: {
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'users',
|
||||
attributes: {
|
||||
avatar: '/assets/images/default-avatar.png',
|
||||
name: 'Pavel Svintsitskiy',
|
||||
email: 'pashaUSA@gmail.com',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
type: 'invoices',
|
||||
attributes: {
|
||||
total: 29.99,
|
||||
plan: 'Professional Plan',
|
||||
created_at: '31. April. 2020',
|
||||
created_at_formatted: '31. April. 2020',
|
||||
download: 'https://vuefilemanager.com/',
|
||||
},
|
||||
relationships: {
|
||||
user: {
|
||||
data: {
|
||||
id: '1',
|
||||
type: 'users',
|
||||
attributes: {
|
||||
avatar: '/avatars/lTksMdJM-6D3529EF-5D8C-4959-BEC2-4BDE80A051C2.jpeg',
|
||||
name: 'Torsten',
|
||||
email: 'torsten.hoegel@go-on-net.de',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
label: 'Total',
|
||||
field: 'attributes.total',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'User',
|
||||
field: 'attributes.plan',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Payed',
|
||||
field: 'relationships.user.data.attributes.name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
field: 'data.action',
|
||||
sortable: false
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
/*axios.get('/api/users/' + this.$route.params.id + '/storage')
|
||||
.then(response => {
|
||||
this.storage = response.data.data
|
||||
this.isLoading = false
|
||||
})*/
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.block-form {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -34,6 +34,14 @@
|
||||
{{ row.data.attributes.role }}
|
||||
</ColorLabel>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item" v-if="row.relationships.subscription">
|
||||
{{ row.relationships.subscription.data.attributes.name }}
|
||||
</span>
|
||||
<span class="cell-item" v-else>
|
||||
Free
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.relationships.storage.data.attributes.used }}%
|
||||
@@ -113,6 +121,11 @@
|
||||
field: 'data.attributes.role',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Subscription Plan',
|
||||
field: 'data.attributes.role',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.storage_used'),
|
||||
field: 'data.attributes.storage.used',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="single-page" v-if="app">
|
||||
<div id="page-content" class="medium-width" v-if="! isLoading">
|
||||
<div id="page-content" v-if="! isLoading">
|
||||
<MobileHeader :title="$router.currentRoute.meta.title"/>
|
||||
<PageHeader :can-back="true" :title="$router.currentRoute.meta.title"/>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
<!--Avatar-->
|
||||
<div class="block-wrapper">
|
||||
<label>Avatar</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="avatar" v-slot="{ errors }">
|
||||
<ImageInput v-model="user.avatar" :error="errors[0]" />
|
||||
</ValidationProvider>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
<ValidationObserver ref="deleteUser" @submit.prevent="deleteUser" v-slot="{ invalid }" tag="form"
|
||||
class="form block-form">
|
||||
<ValidationProvider tag="div" class="block-wrapper" v-slot="{ errors }" mode="passive"
|
||||
name="User name" :rules="'required|is:' + user.attributes.name">
|
||||
<label>{{ $t('admin_page_user.label_delete_user', {user: user.attributes.name}) }}:</label>
|
||||
name="User name" :rules="'required|is:' + user.data.attributes.name">
|
||||
<label>{{ $t('admin_page_user.label_delete_user', {user: user.data.attributes.name}) }}:</label>
|
||||
<div class="single-line-form">
|
||||
<input v-model="userName"
|
||||
:placeholder="$t('admin_page_user.placeholder_delete_user')"
|
||||
@@ -101,7 +101,7 @@
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -82,16 +82,16 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>State:</label>
|
||||
<div class="input-wrapper">
|
||||
<input :value="user.relationships.settings.data.attributes.billing_state"
|
||||
type="text"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>State:</label>
|
||||
<div class="input-wrapper">
|
||||
<input :value="user.relationships.settings.data.attributes.billing_state"
|
||||
type="text"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>City:</label>
|
||||
<div class="input-wrapper">
|
||||
|
||||
@@ -7,16 +7,30 @@
|
||||
<div class="content-page">
|
||||
|
||||
<!--User thumbnail-->
|
||||
<div class="user-thumbnail">
|
||||
<div class="avatar">
|
||||
<UserImageInput
|
||||
v-model="avatar"
|
||||
:avatar="profile.data.attributes.avatar"
|
||||
/>
|
||||
<div class="page-detail-headline">
|
||||
<div class="user-thumbnail">
|
||||
<div class="avatar">
|
||||
<UserImageInput
|
||||
v-model="avatar"
|
||||
:avatar="profile.data.attributes.avatar"
|
||||
/>
|
||||
</div>
|
||||
<div class="info">
|
||||
<b class="name">
|
||||
{{ profile.data.attributes.name }}
|
||||
<ColorLabel :color="subscriptionColor">
|
||||
{{ subscriptionStatus }}
|
||||
</ColorLabel>
|
||||
</b>
|
||||
<span class="email">{{ profile.data.attributes.email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info">
|
||||
<b class="name">{{ profile.data.attributes.name }}</b>
|
||||
<span class="email">{{ profile.data.attributes.email }}</span>
|
||||
<div class="headline-actions">
|
||||
<router-link :to="{name: 'UpgradePlan'}">
|
||||
<ButtonBase button-style="secondary" type="button">
|
||||
Upgrade Plan
|
||||
</ButtonBase>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,6 +54,15 @@
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link replace :to="{name: 'Invoice'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<credit-card-icon size="17"></credit-card-icon>
|
||||
</div>
|
||||
<div class="label">
|
||||
Subscription
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link replace :to="{name: 'Invoice'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<file-text-icon size="17"></file-text-icon>
|
||||
@@ -81,11 +104,13 @@
|
||||
<script>
|
||||
import UserImageInput from '@/components/Others/UserImageInput'
|
||||
import MobileHeader from '@/components/Mobile/MobileHeader'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import PageHeader from '@/components/Others/PageHeader'
|
||||
import ColorLabel from '@/components/Others/ColorLabel'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import axios from 'axios'
|
||||
|
||||
import {
|
||||
CreditCardIcon,
|
||||
HardDriveIcon,
|
||||
FileTextIcon,
|
||||
UserIcon,
|
||||
@@ -95,15 +120,26 @@
|
||||
export default {
|
||||
name: 'Settings',
|
||||
components: {
|
||||
ButtonBase,
|
||||
CreditCardIcon,
|
||||
UserImageInput,
|
||||
FileTextIcon,
|
||||
MobileHeader,
|
||||
ColorLabel,
|
||||
PageHeader,
|
||||
Spinner,
|
||||
HardDriveIcon,
|
||||
UserIcon,
|
||||
LockIcon,
|
||||
},
|
||||
computed: {
|
||||
subscriptionStatus() {
|
||||
return this.profile.relationships.subscription ? 'Subscription' : 'Free'
|
||||
},
|
||||
subscriptionColor() {
|
||||
return this.profile.relationships.subscription ? 'green' : 'purple'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
avatar: undefined,
|
||||
@@ -125,6 +161,11 @@
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.page-detail-headline {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.user-thumbnail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
360
resources/js/views/Upgrade/UpgradeBilling.vue
Normal file
360
resources/js/views/Upgrade/UpgradeBilling.vue
Normal file
@@ -0,0 +1,360 @@
|
||||
<template>
|
||||
<div id="single-page">
|
||||
<div id="page-content" class="large-width center-page" v-show="! isLoading">
|
||||
<MobileHeader :title="$router.currentRoute.meta.title"/>
|
||||
|
||||
<div class="content-page">
|
||||
|
||||
<div class="plan-title">
|
||||
<credit-card-icon size="42" class="title-icon"></credit-card-icon>
|
||||
<h1>Choose Payment Method</h1>
|
||||
<h2>Choose plan witch perfect fit your needs. All plans is billed monthly automatically via your
|
||||
credit card.</h2>
|
||||
</div>
|
||||
|
||||
<div class="order">
|
||||
<div class="billing" v-if="billing">
|
||||
<b class="form-group-label">Billing Information:</b>
|
||||
<ValidationObserver ref="order" v-slot="{ invalid }" tag="form" class="form block-form">
|
||||
<div class="form block-form">
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Name:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_name" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_name"
|
||||
placeholder="Type your billing name"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Address:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_address" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_address"
|
||||
placeholder="Type your billing address"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>State:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_state" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_state"
|
||||
placeholder="Type your billing state"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>City:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required" name="billing_city" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_city"
|
||||
placeholder="Type your billing city"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Postal Code:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper"
|
||||
rules="required" name="billing_postal_code"
|
||||
v-slot="{ errors }">
|
||||
<input v-model="billing.billing_postal_code"
|
||||
placeholder="Type your billing postal code"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Country:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_country" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_country"
|
||||
placeholder="Type your billing country"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Phone Number:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" rules="required"
|
||||
name="billing_phone_number" v-slot="{ errors }">
|
||||
<input v-model="billing.billing_phone_number"
|
||||
placeholder="Type your billing phone number"
|
||||
type="text"
|
||||
:class="{'is-error': errors[0]}"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
</ValidationObserver>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<b class="form-group-label">Order Summary:</b>
|
||||
|
||||
<div class="summary-list" v-if="requestedPlan">
|
||||
<div class="row">
|
||||
<div class="cell">
|
||||
<b>{{ requestedPlan.data.attributes.name }}</b>
|
||||
<small>Billed monthly</small>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<b>{{ requestedPlan.data.attributes.price }} USD</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="cell">
|
||||
<b>Total</b>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<b>{{ requestedPlan.data.attributes.price }} USD</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ButtonBase :disabled="isSubmitted" :loading="isSubmitted" @click.native="submitOrder"
|
||||
type="submit" button-style="theme-solid" class="next-submit">
|
||||
Pay Order
|
||||
</ButtonBase>
|
||||
|
||||
<small class="disclaimer">
|
||||
By submit form, you agree to save the payment method and billing information in your
|
||||
VueFileManager account.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="loader" v-if="isLoading">
|
||||
<Spinner></Spinner>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
|
||||
import PlanPricingTables from '@/components/Others/PlanPricingTables'
|
||||
import MobileHeader from '@/components/Mobile/MobileHeader'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import PageHeader from '@/components/Others/PageHeader'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import {CreditCardIcon} from 'vue-feather-icons'
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
import { mapGetters } from 'vuex'
|
||||
import {events} from "@/bus"
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'UpgradePlan',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
PlanPricingTables,
|
||||
CreditCardIcon,
|
||||
MobileHeader,
|
||||
ButtonBase,
|
||||
PageHeader,
|
||||
required,
|
||||
Spinner,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['requestedPlan']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
isSubmitted: false,
|
||||
billing: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async submitOrder() {
|
||||
|
||||
// Validate fields
|
||||
const isValid = await this.$refs.order.validate();
|
||||
|
||||
if (!isValid) return;
|
||||
|
||||
// Start loading
|
||||
this.isSubmitted = true
|
||||
|
||||
// Send order request
|
||||
axios
|
||||
.post('/api/upgrade', {
|
||||
billing: this.billing,
|
||||
plan: this.requestedPlan,
|
||||
})
|
||||
.then(response => {
|
||||
|
||||
// End loading
|
||||
this.isSubmitted = false
|
||||
|
||||
// Show toaster
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: 'Your account was successfully upgraded.',
|
||||
})
|
||||
|
||||
// Go to User page
|
||||
this.$router.push({name: 'Storage'})
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
// End loading
|
||||
this.isSubmitted = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get('/api/profile')
|
||||
.then(response => {
|
||||
|
||||
if (! this.requestedPlan) {
|
||||
this.$router.push({name: 'UpgradePlan'})
|
||||
}
|
||||
|
||||
this.billing = {
|
||||
billing_name: response.data.relationships.settings.data.attributes.billing_name,
|
||||
billing_address: response.data.relationships.settings.data.attributes.billing_address,
|
||||
billing_state: response.data.relationships.settings.data.attributes.billing_state,
|
||||
billing_city: response.data.relationships.settings.data.attributes.billing_city,
|
||||
billing_postal_code: response.data.relationships.settings.data.attributes.billing_postal_code,
|
||||
billing_country: response.data.relationships.settings.data.attributes.billing_country,
|
||||
billing_phone_number: response.data.relationships.settings.data.attributes.billing_phone_number,
|
||||
}
|
||||
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.summary-list {
|
||||
box-shadow: 0 7px 20px 5px hsla(220, 36%, 16%, 0.06);
|
||||
border-radius: 8px;
|
||||
position: sticky;
|
||||
padding: 25px;
|
||||
top: 30px;
|
||||
|
||||
.next-submit {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
@include font-size(12);
|
||||
line-height: 1.6;
|
||||
display: block;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 15px 0;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
border-top: 1px solid $light_mode_border;
|
||||
padding-bottom: 0;
|
||||
|
||||
b {
|
||||
font-weight: 800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cell {
|
||||
b {
|
||||
display: block;
|
||||
@include font-size(18);
|
||||
}
|
||||
|
||||
small {
|
||||
color: $text-muted;
|
||||
@include font-size(12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.order {
|
||||
display: flex;
|
||||
|
||||
.billing {
|
||||
flex: 0 0 65%;
|
||||
padding-right: 30px;
|
||||
|
||||
.form {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.summary {
|
||||
flex: 0 0 34%;
|
||||
}
|
||||
}
|
||||
|
||||
.plan-title {
|
||||
text-align: center;
|
||||
max-width: 600px;
|
||||
margin: 0 auto 80px;
|
||||
|
||||
path, line, polyline, rect, circle {
|
||||
color: $theme;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@include font-size(38);
|
||||
font-weight: 800;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@include font-size(20);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
89
resources/js/views/Upgrade/UpgradePlan.vue
Normal file
89
resources/js/views/Upgrade/UpgradePlan.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div id="single-page">
|
||||
<div id="page-content" class="large-width center-page" v-show="! isLoading">
|
||||
<MobileHeader :title="$router.currentRoute.meta.title"/>
|
||||
|
||||
<div class="content-page">
|
||||
<div class="plan-title">
|
||||
<cloud-icon size="42" class="title-icon"></cloud-icon>
|
||||
<h1>Choose Your Plan</h1>
|
||||
<h2>Choose plan witch perfect fit your needs. All plans is billed monthly automatically via your credit card.</h2>
|
||||
</div>
|
||||
|
||||
<PlanPricingTables @load="onLoadPricingTables" @selected-plan="onSelectTable"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="loader" v-if="isLoading">
|
||||
<Spinner></Spinner>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PlanPricingTables from '@/components/Others/PlanPricingTables'
|
||||
import MobileHeader from '@/components/Mobile/MobileHeader'
|
||||
import PageHeader from '@/components/Others/PageHeader'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import { CloudIcon } from 'vue-feather-icons'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'UpgradePlan',
|
||||
components: {
|
||||
PlanPricingTables,
|
||||
MobileHeader,
|
||||
PageHeader,
|
||||
CloudIcon,
|
||||
Spinner,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onLoadPricingTables(state) {
|
||||
this.isLoading = state
|
||||
},
|
||||
onSelectTable(plan) {
|
||||
this.$store.commit('STORE_REQUESTED_PLAN', plan)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.plan-title {
|
||||
text-align: center;
|
||||
max-width: 600px;
|
||||
margin: 0 auto 80px;
|
||||
|
||||
path, line, polyline, rect, circle {
|
||||
color: $theme;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@include font-size(38);
|
||||
font-weight: 800;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@include font-size(20);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -5,7 +5,7 @@
|
||||
class="form block-form">
|
||||
|
||||
<div class="block-wrapper">
|
||||
<b class="form-group-label">{{ $t('page_create_password.label_new_pass') }}:</b>
|
||||
<label>{{ $t('page_create_password.label_new_pass') }}:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="New Password"
|
||||
rules="required" v-slot="{ errors }">
|
||||
<input v-model="newPassword" :placeholder="$t('page_create_password.label_new_pass')"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<PageTab>
|
||||
<PageTabGroup v-if="userInfo">
|
||||
<div class="form block-form">
|
||||
<b class="form-group-label">{{ $t('admin_page_user.label_person_info') }}</b>
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>{{ $t('page_registration.label_email') }}</label>
|
||||
@@ -50,17 +49,17 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>State:</label>
|
||||
<div class="input-wrapper">
|
||||
<input @keyup="$updateText('/user/relationships/settings', 'billing_state', billingInfo.billing_state)"
|
||||
v-model="billingInfo.billing_state"
|
||||
placeholder="Type your billing state"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>State:</label>
|
||||
<div class="input-wrapper">
|
||||
<input @keyup="$updateText('/user/relationships/settings', 'billing_state', billingInfo.billing_state)"
|
||||
v-model="billingInfo.billing_state"
|
||||
placeholder="Type your billing state"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>City:</label>
|
||||
<div class="input-wrapper">
|
||||
@@ -135,13 +134,6 @@
|
||||
ThemeLabel,
|
||||
required,
|
||||
},
|
||||
/* watch: {
|
||||
'user.name': debounce(function (val) {
|
||||
if (val === '') return
|
||||
|
||||
this.$store.commit('UPDATE_NAME', val)
|
||||
}, 300),
|
||||
},*/
|
||||
data() {
|
||||
return {
|
||||
userInfo: undefined,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<PageTab v-if="storage">
|
||||
<PageTabGroup>
|
||||
<b class="form-group-label">{{ $t('storage.sec_capacity') }}</b>
|
||||
<StorageItemDetail type="disk" :title="$t('storage.total_used', {used: storage.attributes.used})" :percentage="storage.attributes.percentage" :used="$t('storage.total_capacity', {capacity: storage.attributes.capacity})"/>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup>
|
||||
|
||||
58
resources/js/views/User/Subscription.vue
Normal file
58
resources/js/views/User/Subscription.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<PageTab>
|
||||
<PageTabGroup>
|
||||
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
|
||||
import PageTab from '@/components/Others/Layout/PageTab'
|
||||
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
|
||||
import {ExternalLinkIcon} from "vue-feather-icons";
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'UserSubscription',
|
||||
components: {
|
||||
PageTabGroup,
|
||||
PageTab,
|
||||
DatatableWrapper,
|
||||
ExternalLinkIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
invoices: undefined,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
/* axios.get('/api/user/subscription')
|
||||
.then(response => {
|
||||
this.invoices = response.data.data
|
||||
this.isLoading = false
|
||||
})*/
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.block-form {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
26
resources/sass/app.scss
vendored
26
resources/sass/app.scss
vendored
@@ -28,18 +28,36 @@
|
||||
|
||||
#page-content {
|
||||
margin: 0 auto;
|
||||
padding-bottom: 50px;
|
||||
|
||||
&.full-width {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
&.medium-width {
|
||||
max-width: 1024px;
|
||||
max-width: 920px;
|
||||
}
|
||||
|
||||
&.large-width {
|
||||
max-width: 1190px;
|
||||
}
|
||||
|
||||
&.small-width {
|
||||
max-width: 690px;
|
||||
}
|
||||
|
||||
&.center-page {
|
||||
height: 100%;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 0;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
|
||||
.content-page {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +66,9 @@
|
||||
}
|
||||
|
||||
.form-group-label {
|
||||
@include font-size(17);
|
||||
font-weight: 500;
|
||||
@include font-size(18);
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.3px;
|
||||
margin-bottom: 25px;
|
||||
display: block;
|
||||
}
|
||||
@@ -249,6 +268,7 @@
|
||||
.cell-item {
|
||||
white-space: nowrap;
|
||||
color: $text;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
resources/sass/vue-file-manager/_forms.scss
vendored
27
resources/sass/vue-file-manager/_forms.scss
vendored
@@ -33,14 +33,14 @@
|
||||
}
|
||||
|
||||
.block-wrapper {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 15px;
|
||||
|
||||
label {
|
||||
@include font-size(14);
|
||||
color: $text-muted;
|
||||
color: rgba($text, 0.7);
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
@@ -57,6 +57,19 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.switch-label {
|
||||
.input-help {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
font-weight: 700;
|
||||
color: $text;
|
||||
@include font-size(16);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-help {
|
||||
@@ -85,16 +98,16 @@ input[type="password"],
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="email"] {
|
||||
border: 1px solid #ebebeb;
|
||||
border: 1px solid transparent;
|
||||
@include transition(150ms);
|
||||
@include font-size(14);
|
||||
@include font-size(16);
|
||||
border-radius: 8px;
|
||||
padding: 13px 20px;
|
||||
appearance: none;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
outline: 0;
|
||||
width: 100%;
|
||||
background: $light_mode_input_background;
|
||||
background: hsla(210, 10%, 98%, 1);
|
||||
|
||||
&.is-error {
|
||||
border-color: $danger;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Colors
|
||||
$text: #1c1d1f;
|
||||
$text: #1b2539;
|
||||
$text-muted: rgba($text, 0.7);
|
||||
|
||||
$theme: #00BC7E;
|
||||
@@ -13,11 +13,11 @@ $purple: #9D66FE;
|
||||
$light_mode_border: #F8F8F8;
|
||||
$danger: #fd397a;
|
||||
$light_text: #A4ADB6;
|
||||
$light_background: #f6f6f6;
|
||||
$light_background: #f4f5f6;
|
||||
$dark_background: #EBEBEB;
|
||||
$shadow: 0 7px 25px 1px rgba(0, 0, 0, 0.12);
|
||||
|
||||
$light_mode_input_background: hsl(0, 0%, 98%);
|
||||
$light_mode_input_background: #f4f5f6;
|
||||
$light_mode_popup_shadow: 0 15px 50px 10px rgba(26,38,74,0.12);
|
||||
$light_mode_vignette: rgba(9, 8, 12, 0.35);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user