- Flat fee implementation

- Fixed/Metered plan pages
This commit is contained in:
Čarodej
2021-12-21 17:28:17 +01:00
parent 60b34e53a3
commit 6bb7789232
19 changed files with 740 additions and 130 deletions

View File

@@ -210,6 +210,8 @@ return [
// v2
'bandwidth' => 'Bandwidth',
'storage' => 'Storage',
'flat-fee' => 'Flat Fee',
'feature_usage_desc_flat-fee' => 'Price for the service.',
'feature_usage_desc_bandwidth' => 'Data amount you transferred to/from your account.',
'feature_usage_desc_storage' => 'Total storage amount you are using.',
'feature_usage_desc_members' => 'Total members you invited to your team folders.',

View File

@@ -3,7 +3,7 @@
"/css/app.css": "/css/app.css",
"/css/tailwind.css": "/css/tailwind.css",
"/chunks/admin.js": "/chunks/admin.js?id=5014620eaa736d4d5cd7",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=759433a182f73618e9f4",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=46820dda03fee8dc7770",
"/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~c7a13fb0.js": "/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~c7a13fb0.js?id=b6966627bd253eda63ba",
"/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~3e4fdd8b.js": "/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~3e4fdd8b.js?id=d7a8e5b5b913858da427",
"/chunks/admin~chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/my-shared-item~9b68162c.js": "/chunks/admin~chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/my-shared-item~9b68162c.js?id=5841d65172536a8a9bdc",
@@ -12,11 +12,11 @@
"/chunks/admin~chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/settin~97130d1f.js": "/chunks/admin~chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/settin~97130d1f.js?id=e2d818009a4e2c1fffdf",
"/chunks/admin~chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/shared~1bec6fe4.js": "/chunks/admin~chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/shared~1bec6fe4.js?id=510e6c1b1017a73a40a6",
"/chunks/admin~chunks/platform.js": "/chunks/admin~chunks/platform.js?id=917aab9de16d3eb7039a",
"/chunks/admin~chunks/platform~chunks/settings.js": "/chunks/admin~chunks/platform~chunks/settings.js?id=fc826cd2543dfefc4bd3",
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.js?id=8e89d2271b17b2d78177",
"/chunks/admin~chunks/platform~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/shared.js?id=37121892ebaeb6d8986a",
"/chunks/admin~chunks/platform~chunks/settings.js": "/chunks/admin~chunks/platform~chunks/settings.js?id=4bde434e3ed10f3f29b2",
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.js?id=946723d9a3185230f2a6",
"/chunks/admin~chunks/platform~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/shared.js?id=afeba4ebd13af7e995be",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=6035ca411b2c4239d964",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~5acee76d.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~5acee76d.js?id=b72bbc2e750c80377527",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~5acee76d.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~5acee76d.js?id=6261a46f75a495a94fae",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~fa9d08c1.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~fa9d08c1.js?id=741acf06489eac45774e",
"/chunks/app-billings.js": "/chunks/app-billings.js?id=714f7a9f33e15fe89b4a",
"/chunks/app-email.js": "/chunks/app-email.js?id=324ae41d780105c9a9fb",
@@ -27,7 +27,7 @@
"/chunks/app-others.js": "/chunks/app-others.js?id=2789aac07c894eeb29ea",
"/chunks/app-payments.js": "/chunks/app-payments.js?id=df48b9f5634db900c0ef",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=2a96295eef59bd6c8921",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=65481d5c45313ace4844",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=c54b4cf708cc411c1967",
"/chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/database~chunks/email-veri~5d0bfc57.js": "/chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/database~chunks/email-veri~5d0bfc57.js?id=107a78323eef0c1d4c81",
"/chunks/billings-detail.js": "/chunks/billings-detail.js?id=5dbf157c75ae6fb9bda3",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=fda418b31ad6bb55b223",
@@ -54,12 +54,12 @@
"/chunks/not-found.js": "/chunks/not-found.js?id=034287ee0ecb036320d3",
"/chunks/page-edit.js": "/chunks/page-edit.js?id=c327905d0b6d997d402d",
"/chunks/pages.js": "/chunks/pages.js?id=7db66df0453135bf4e51",
"/chunks/plan.js": "/chunks/plan.js?id=4fa6f87c04a875875d36",
"/chunks/plan-create.js": "/chunks/plan-create.js?id=e027f178caef630a63db",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=adbb08867b0da7178881",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=414ba1f705f387f7aeb6",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=adbaf70d9060712110ab",
"/chunks/plans.js": "/chunks/plans.js?id=7f262c68655989372d3c",
"/chunks/plan.js": "/chunks/plan.js?id=f62a5bd64fb706b2f0e2",
"/chunks/plan-create.js": "/chunks/plan-create.js?id=995a9a5ae9cc43f35d2c",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=ce206dd1e8141bb53e79",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=58e36ccb0b00623ebe93",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=474c4dc2cebe47ffa506",
"/chunks/plans.js": "/chunks/plans.js?id=3c1f3d5a9cfe4dcf5237",
"/chunks/platform.js": "/chunks/platform.js?id=cb224c18bb25c409345a",
"/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=5734e9333fc67c706853",
"/chunks/platform~chunks/shared~chunks/shared-with-me~chunks/team-folders.js": "/chunks/platform~chunks/shared~chunks/shared-with-me~chunks/team-folders.js?id=7d983dfdc91de607d737",
@@ -71,9 +71,9 @@
"/chunks/settings-create-payment-methods.js": "/chunks/settings-create-payment-methods.js?id=d3443e79b667f5b4b1d2",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=049c3383e310392f966d",
"/chunks/settings-payment-methods.js": "/chunks/settings-payment-methods.js?id=093cc2fd918ee6a340d3",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=05450719ccf4a5bf4fa9",
"/chunks/settings-storage~chunks/settings-subscription~chunks/user-storage~chunks/user-subscription.js": "/chunks/settings-storage~chunks/settings-subscription~chunks/user-storage~chunks/user-subscription.js?id=147afaac8c8bacfe6433",
"/chunks/settings-subscription.js": "/chunks/settings-subscription.js?id=e2717eb836e334b41976",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=76b45c336e8e12b23e81",
"/chunks/settings-storage~chunks/settings-subscription~chunks/user-storage~chunks/user-subscription.js": "/chunks/settings-storage~chunks/settings-subscription~chunks/user-storage~chunks/user-subscription.js?id=cd797256cb819aac4d24",
"/chunks/settings-subscription.js": "/chunks/settings-subscription.js?id=4a7dff8eca5417e36c64",
"/chunks/settings~chunks/settings-password.js": "/chunks/settings~chunks/settings-password.js?id=c33cd2341b9b04a732e5",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=651d5accf401908724c5",
"/chunks/shared.js": "/chunks/shared.js?id=6230d050545cd1bd9b87",
@@ -95,12 +95,12 @@
"/chunks/upgrade-billing~chunks/upgrade-plan.js": "/chunks/upgrade-billing~chunks/upgrade-plan.js?id=8bd237c632018a537d76",
"/chunks/upgrade-plan.js": "/chunks/upgrade-plan.js?id=7ee9b84ffed9bf544997",
"/chunks/user.js": "/chunks/user.js?id=80d4433e6a0f1a2a940d",
"/chunks/user-create.js": "/chunks/user-create.js?id=6ec0f7a5f0166dbe52fd",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=97b9567df09384f7d303",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=51e4b17ff373d4e39a2c",
"/chunks/user-password.js": "/chunks/user-password.js?id=ce6c12a5b038f5481bd1",
"/chunks/user-create.js": "/chunks/user-create.js?id=ff84767e33cdf49fab55",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=d0d3419a35ca27c4226c",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=fab2eae409831e768b0d",
"/chunks/user-password.js": "/chunks/user-password.js?id=6aeb19839b38f287953d",
"/chunks/user-storage.js": "/chunks/user-storage.js?id=936f120357a4480e1bd5",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=15afb8585f5bd23d0f4b",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=87009bae0d5da0dacaeb",
"/chunks/users.js": "/chunks/users.js?id=ab7eeac6e8559dc1eb2b",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~35bc7519.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~35bc7519.js?id=ae06aafc3749254fe4aa",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~629342a0.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~629342a0.js?id=cdefaa7800d04dafb07b",
@@ -334,5 +334,105 @@
"/chunks/user-storage.f37703378d8d1e016193.hot-update.js": "/chunks/user-storage.f37703378d8d1e016193.hot-update.js",
"/chunks/user-storage.f21876fba8ece97bbccd.hot-update.js": "/chunks/user-storage.f21876fba8ece97bbccd.hot-update.js",
"/chunks/user-storage.cbdde32513dd1279ac78.hot-update.js": "/chunks/user-storage.cbdde32513dd1279ac78.hot-update.js",
"/chunks/user-storage.1dc4b69b30fef14a8ce2.hot-update.js": "/chunks/user-storage.1dc4b69b30fef14a8ce2.hot-update.js"
"/chunks/user-storage.1dc4b69b30fef14a8ce2.hot-update.js": "/chunks/user-storage.1dc4b69b30fef14a8ce2.hot-update.js",
"/js/main.2867645a41a4f4555a41.hot-update.js": "/js/main.2867645a41a4f4555a41.hot-update.js",
"/chunks/admin~chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/my-shared-item~b19230b7.js": "/chunks/admin~chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/my-shared-item~b19230b7.js?id=9673c4a3d57732114787",
"/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/my-shared-items~chunks/page~6462db45.js": "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/my-shared-items~chunks/page~6462db45.js?id=915a8962ef769b80b66c",
"/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plan-subscribers~chunks/settings-payment-method~1c033dac.js": "/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plan-subscribers~chunks/settings-payment-method~1c033dac.js?id=de6ec8185355af53fe90",
"/chunks/dashboard~chunks/invoices~chunks/pages~chunks/subscriptions.js": "/chunks/dashboard~chunks/invoices~chunks/pages~chunks/subscriptions.js?id=861c2a5aa2247dbf214e",
"/chunks/dashboard~chunks/invoices~chunks/plan-subscribers~chunks/users.2867645a41a4f4555a41.hot-update.js": "/chunks/dashboard~chunks/invoices~chunks/plan-subscribers~chunks/users.2867645a41a4f4555a41.hot-update.js",
"/chunks/pages.2867645a41a4f4555a41.hot-update.js": "/chunks/pages.2867645a41a4f4555a41.hot-update.js",
"/chunks/plans.2867645a41a4f4555a41.hot-update.js": "/chunks/plans.2867645a41a4f4555a41.hot-update.js",
"/chunks/settings-payment-methods.2867645a41a4f4555a41.hot-update.js": "/chunks/settings-payment-methods.2867645a41a4f4555a41.hot-update.js",
"/chunks/settings-subscription.2867645a41a4f4555a41.hot-update.js": "/chunks/settings-subscription.2867645a41a4f4555a41.hot-update.js",
"/chunks/subscriptions.2867645a41a4f4555a41.hot-update.js": "/chunks/subscriptions.2867645a41a4f4555a41.hot-update.js",
"/chunks/user-subscription.2867645a41a4f4555a41.hot-update.js": "/chunks/user-subscription.2867645a41a4f4555a41.hot-update.js",
"/js/main.d4e3f14063a25452777b.hot-update.js": "/js/main.d4e3f14063a25452777b.hot-update.js",
"/chunks/plans.d4e3f14063a25452777b.hot-update.js": "/chunks/plans.d4e3f14063a25452777b.hot-update.js",
"/chunks/plans.1d817db5f6d25c90269a.hot-update.js": "/chunks/plans.1d817db5f6d25c90269a.hot-update.js",
"/chunks/plans.9ca8c7ac8fd29c972d0e.hot-update.js": "/chunks/plans.9ca8c7ac8fd29c972d0e.hot-update.js",
"/chunks/plans.d24813b8129900f63c38.hot-update.js": "/chunks/plans.d24813b8129900f63c38.hot-update.js",
"/chunks/plans.b1bd667ce36b98eb0801.hot-update.js": "/chunks/plans.b1bd667ce36b98eb0801.hot-update.js",
"/chunks/plans.4f2b90d9f07d7f809a35.hot-update.js": "/chunks/plans.4f2b90d9f07d7f809a35.hot-update.js",
"/chunks/plans.a44dfbe7ebf10b6a6941.hot-update.js": "/chunks/plans.a44dfbe7ebf10b6a6941.hot-update.js",
"/chunks/plans.7a4e7a05194821644b99.hot-update.js": "/chunks/plans.7a4e7a05194821644b99.hot-update.js",
"/js/main.8e4692ca7cd2827dba9b.hot-update.js": "/js/main.8e4692ca7cd2827dba9b.hot-update.js",
"/chunks/plan.8e4692ca7cd2827dba9b.hot-update.js": "/chunks/plan.8e4692ca7cd2827dba9b.hot-update.js",
"/chunks/plan-create.8e4692ca7cd2827dba9b.hot-update.js": "/chunks/plan-create.8e4692ca7cd2827dba9b.hot-update.js",
"/chunks/plan-delete.8e4692ca7cd2827dba9b.hot-update.js": "/chunks/plan-delete.8e4692ca7cd2827dba9b.hot-update.js",
"/chunks/plan-settings.8e4692ca7cd2827dba9b.hot-update.js": "/chunks/plan-settings.8e4692ca7cd2827dba9b.hot-update.js",
"/chunks/plan-subscribers.8e4692ca7cd2827dba9b.hot-update.js": "/chunks/plan-subscribers.8e4692ca7cd2827dba9b.hot-update.js",
"/chunks/plan.5debc6a8ebd0b2178c54.hot-update.js": "/chunks/plan.5debc6a8ebd0b2178c54.hot-update.js",
"/js/main.be3d6fc4c2e25a5cf262.hot-update.js": "/js/main.be3d6fc4c2e25a5cf262.hot-update.js",
"/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~4c3f2f2b.js": "/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~4c3f2f2b.js?id=84a1a26a8a14786ab67f",
"/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~a395cb9f.js": "/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~a395cb9f.js?id=5dc14bf7fc6111e90237",
"/chunks/app-language~chunks/dashboard~chunks/invoices~chunks/page-edit~chunks/pages~chunks/profile~ch~c7815c9e.js": "/chunks/app-language~chunks/dashboard~chunks/invoices~chunks/page-edit~chunks/pages~chunks/profile~ch~c7815c9e.js?id=83a6435cf1c4d139a427",
"/chunks/plan-create.be3d6fc4c2e25a5cf262.hot-update.js": "/chunks/plan-create.be3d6fc4c2e25a5cf262.hot-update.js",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~22daf8e2.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~22daf8e2.js?id=ad6783cb84da5d75b32b",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~6ddb6fb8.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~6ddb6fb8.js?id=41cc28a666ef50c019b0",
"/js/main.7ce55e461dc3238dbf4f.hot-update.js": "/js/main.7ce55e461dc3238dbf4f.hot-update.js",
"/chunks/plan.7ce55e461dc3238dbf4f.hot-update.js": "/chunks/plan.7ce55e461dc3238dbf4f.hot-update.js",
"/chunks/plan-create.7ce55e461dc3238dbf4f.hot-update.js": "/chunks/plan-create.7ce55e461dc3238dbf4f.hot-update.js",
"/chunks/plan-delete.7ce55e461dc3238dbf4f.hot-update.js": "/chunks/plan-delete.7ce55e461dc3238dbf4f.hot-update.js",
"/chunks/plan-settings.7ce55e461dc3238dbf4f.hot-update.js": "/chunks/plan-settings.7ce55e461dc3238dbf4f.hot-update.js",
"/chunks/plan-subscribers.7ce55e461dc3238dbf4f.hot-update.js": "/chunks/plan-subscribers.7ce55e461dc3238dbf4f.hot-update.js",
"/js/main.89032fa47396a585f409.hot-update.js": "/js/main.89032fa47396a585f409.hot-update.js",
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.89032fa47396a585f409.hot-update.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.89032fa47396a585f409.hot-update.js",
"/chunks/plan-create.89032fa47396a585f409.hot-update.js": "/chunks/plan-create.89032fa47396a585f409.hot-update.js",
"/chunks/plans.89032fa47396a585f409.hot-update.js": "/chunks/plans.89032fa47396a585f409.hot-update.js",
"/js/main.36da7a1403b6adf811d4.hot-update.js": "/js/main.36da7a1403b6adf811d4.hot-update.js",
"/chunks/plan-create.36da7a1403b6adf811d4.hot-update.js": "/chunks/plan-create.36da7a1403b6adf811d4.hot-update.js",
"/js/main.bfb51d46fe9500c09f69.hot-update.js": "/js/main.bfb51d46fe9500c09f69.hot-update.js",
"/chunks/admin-account.bfb51d46fe9500c09f69.hot-update.js": "/chunks/admin-account.bfb51d46fe9500c09f69.hot-update.js",
"/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~640155e3.js": "/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~640155e3.js?id=5679c483e3e3caef4b9d",
"/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~e871233b.js": "/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~e871233b.js?id=7df5c5c997a6f638efdf",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~5acee76d.bfb51d46fe9500c09f69.hot-update.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~5acee76d.bfb51d46fe9500c09f69.hot-update.js",
"/chunks/app-language~chunks/dashboard~chunks/invoices~chunks/page-edit~chunks/pages~chunks/plan-creat~d6690165.js": "/chunks/app-language~chunks/dashboard~chunks/invoices~chunks/page-edit~chunks/pages~chunks/plan-creat~d6690165.js?id=2f03fbbe27b922063d16",
"/chunks/app-setup.bfb51d46fe9500c09f69.hot-update.js": "/chunks/app-setup.bfb51d46fe9500c09f69.hot-update.js",
"/chunks/plan.bfb51d46fe9500c09f69.hot-update.js": "/chunks/plan.bfb51d46fe9500c09f69.hot-update.js",
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=ceca8743be6878e4f970",
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=1b619d3ee1a3875819b1",
"/chunks/settings-storage.bfb51d46fe9500c09f69.hot-update.js": "/chunks/settings-storage.bfb51d46fe9500c09f69.hot-update.js",
"/chunks/settings-subscription.bfb51d46fe9500c09f69.hot-update.js": "/chunks/settings-subscription.bfb51d46fe9500c09f69.hot-update.js",
"/chunks/user-create.bfb51d46fe9500c09f69.hot-update.js": "/chunks/user-create.bfb51d46fe9500c09f69.hot-update.js",
"/chunks/user-subscription.bfb51d46fe9500c09f69.hot-update.js": "/chunks/user-subscription.bfb51d46fe9500c09f69.hot-update.js",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~27e0fa60.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~27e0fa60.js?id=348042c51ef86f65cf0c",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~5ef927fd.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~5ef927fd.js?id=0ccd084e22a0efcfb390",
"/chunks/plans.3ded7897a6ccf181fe14.hot-update.js": "/chunks/plans.3ded7897a6ccf181fe14.hot-update.js",
"/chunks/plan.f821f4b80f002c165c40.hot-update.js": "/chunks/plan.f821f4b80f002c165c40.hot-update.js",
"/js/main.f3da17af78955e87f3ef.hot-update.js": "/js/main.f3da17af78955e87f3ef.hot-update.js",
"/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~b500c454.js": "/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~b500c454.js?id=cfcc79bc14201b68bc2b",
"/chunks/plan-settings.f3da17af78955e87f3ef.hot-update.js": "/chunks/plan-settings.f3da17af78955e87f3ef.hot-update.js",
"/chunks/plans.8c634cb7f88ad052da05.hot-update.js": "/chunks/plans.8c634cb7f88ad052da05.hot-update.js",
"/chunks/plans.fad7367eb66153c118b5.hot-update.js": "/chunks/plans.fad7367eb66153c118b5.hot-update.js",
"/chunks/plans.d68e8dbd3e2dd93d8568.hot-update.js": "/chunks/plans.d68e8dbd3e2dd93d8568.hot-update.js",
"/js/main.52cb71b84fadfb3394ef.hot-update.js": "/js/main.52cb71b84fadfb3394ef.hot-update.js",
"/chunks/plan-settings.52cb71b84fadfb3394ef.hot-update.js": "/chunks/plan-settings.52cb71b84fadfb3394ef.hot-update.js",
"/js/main.5e08b126ee3a7ab92804.hot-update.js": "/js/main.5e08b126ee3a7ab92804.hot-update.js",
"/chunks/plan.5e08b126ee3a7ab92804.hot-update.js": "/chunks/plan.5e08b126ee3a7ab92804.hot-update.js",
"/js/main.e71af95153e59b7d538e.hot-update.js": "/js/main.e71af95153e59b7d538e.hot-update.js",
"/chunks/plan-settings.e71af95153e59b7d538e.hot-update.js": "/chunks/plan-settings.e71af95153e59b7d538e.hot-update.js",
"/chunks/plan.2160a2a030bc52ca107e.hot-update.js": "/chunks/plan.2160a2a030bc52ca107e.hot-update.js",
"/chunks/plan.9f1abdeba5472275b82f.hot-update.js": "/chunks/plan.9f1abdeba5472275b82f.hot-update.js",
"/js/main.890110343ff17af996c9.hot-update.js": "/js/main.890110343ff17af996c9.hot-update.js",
"/chunks/plan.6cf5f9404d8064af8374.hot-update.js": "/chunks/plan.6cf5f9404d8064af8374.hot-update.js",
"/js/main.133c8385a1b84953f28b.hot-update.js": "/js/main.133c8385a1b84953f28b.hot-update.js",
"/chunks/plan.133c8385a1b84953f28b.hot-update.js": "/chunks/plan.133c8385a1b84953f28b.hot-update.js",
"/chunks/plan-create/metered.f8cf822a78b31d6812cb.hot-update.js": "/chunks/plan-create/metered.f8cf822a78b31d6812cb.hot-update.js",
"/chunks/plan-create/metered.d9de626030a1ccda3090.hot-update.js": "/chunks/plan-create/metered.d9de626030a1ccda3090.hot-update.js",
"/chunks/plan-create/metered.771695882aeb4fb5274d.hot-update.js": "/chunks/plan-create/metered.771695882aeb4fb5274d.hot-update.js",
"/chunks/plan-create/metered.acf1020524130d795f51.hot-update.js": "/chunks/plan-create/metered.acf1020524130d795f51.hot-update.js",
"/chunks/plan.1b6c20862ae8c04d7b21.hot-update.js": "/chunks/plan.1b6c20862ae8c04d7b21.hot-update.js",
"/js/main.306fcd63154c66e2d5e7.hot-update.js": "/js/main.306fcd63154c66e2d5e7.hot-update.js",
"/chunks/plan-subscribers.f3e025c8acfbdee7f463.hot-update.js": "/chunks/plan-subscribers.f3e025c8acfbdee7f463.hot-update.js",
"/chunks/plan-subscribers.35df47c1685b1df609d9.hot-update.js": "/chunks/plan-subscribers.35df47c1685b1df609d9.hot-update.js",
"/chunks/plan-subscribers.32c336e950a2b97d983e.hot-update.js": "/chunks/plan-subscribers.32c336e950a2b97d983e.hot-update.js",
"/chunks/plan-subscribers.4ff6600d0dcc6da1314d.hot-update.js": "/chunks/plan-subscribers.4ff6600d0dcc6da1314d.hot-update.js",
"/chunks/plan-subscribers.4f26e43a9f97ef585fa9.hot-update.js": "/chunks/plan-subscribers.4f26e43a9f97ef585fa9.hot-update.js",
"/chunks/plan-subscribers.371873c41d6546326be7.hot-update.js": "/chunks/plan-subscribers.371873c41d6546326be7.hot-update.js",
"/chunks/plan-subscribers.cd080c080ddd458b2bb5.hot-update.js": "/chunks/plan-subscribers.cd080c080ddd458b2bb5.hot-update.js",
"/chunks/plan-subscribers.76b5389d993f15c82718.hot-update.js": "/chunks/plan-subscribers.76b5389d993f15c82718.hot-update.js",
"/chunks/admin~chunks/platform~chunks/shared.d81516b0d8910b295242.hot-update.js": "/chunks/admin~chunks/platform~chunks/shared.d81516b0d8910b295242.hot-update.js",
"/chunks/admin~chunks/platform~chunks/settings.c70f3d519363bc62f153.hot-update.js": "/chunks/admin~chunks/platform~chunks/settings.c70f3d519363bc62f153.hot-update.js",
"/chunks/admin~chunks/platform~chunks/shared.90afb72045718354d8a6.hot-update.js": "/chunks/admin~chunks/platform~chunks/shared.90afb72045718354d8a6.hot-update.js"
}

View File

@@ -1,5 +1,5 @@
<template>
<section class="content-sidebar flex-none xl:w-56 w-52 lg:block hidden overflow-y-auto pt-6 select-none dark:bg-dark-background" id="content-sidebar">
<section class="content-sidebar flex-none xl:w-56 w-52 lg:block hidden overflow-y-auto pt-6 select-none dark:bg-dark-background bg-light-background" id="content-sidebar">
<slot></slot>
</section>
</template>
@@ -12,6 +12,6 @@
<style scoped lang="scss">
.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%);
}
</style>

View File

@@ -148,7 +148,7 @@
@import '/resources/sass/vuefilemanager/_variables';
.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%);
}
.router-link-active {

View File

@@ -82,7 +82,7 @@
<settings-icon v-if="['AppOthers', 'Profile', 'Password'].includes(result.action.value)" size="18" class="vue-feather text-theme"/>
<home-icon v-if="result.action.value === 'Files'" size="18" class="vue-feather text-theme"/>
<trash2-icon v-if="result.action.value === 'Trash'" size="18" class="vue-feather text-theme"/>
<database-icon v-if="result.action.value === 'PlanCreate'" size="18" class="vue-feather text-theme"/>
<database-icon v-if="result.action.value === 'CreateFixedPlan'" size="18" class="vue-feather text-theme"/>
<user-plus-icon v-if="result.action.value === 'UserCreate'" size="18" class="vue-feather text-theme"/>
<users-icon v-if="['TeamFolders', 'Users'].includes(result.action.value)" size="18" class="vue-feather text-theme"/>
<user-check-icon v-if="result.action.value === 'SharedWithMe'" size="18" class="vue-feather text-theme"/>
@@ -270,7 +270,7 @@ export default {
title: this.$t('Create Plan'),
action: {
type: 'route',
value: 'PlanCreate',
value: 'CreateFixedPlan',
},
},
]

View File

@@ -330,7 +330,7 @@ const FunctionHelpers = {
'paystack': store.getters.isDarkMode ? '/assets/payments/paystack-dark.svg' : '/assets/payments/paystack.svg',
'stripe': '/assets/payments/stripe.svg',
'system': this.$getImage(store.getters.config.app_logo_horizontal),
}[driver]
}[driver] || this.$getImage(store.getters.config.app_logo_horizontal)
}
Vue.prototype.$getSubscriptionStatusColor = function (status) {

View File

@@ -90,10 +90,20 @@ const routesAdmin = [
},
},
{
name: 'PlanCreate',
path: '/admin/plan/create',
name: 'CreateFixedPlan',
path: '/admin/plan/create/fixed',
component: () =>
import(/* webpackChunkName: "chunks/plan-create" */ '../views/Admin/Plans/PlanCreate'),
import(/* webpackChunkName: "chunks/plan-create/fixed" */ '../views/Admin/Plans/Create/CreateFixedPlan'),
meta: {
requiresAuth: true,
title: 'routes_title.plan_create'
},
},
{
name: 'CreateMeteredPlan',
path: '/admin/plan/create/metered',
component: () =>
import(/* webpackChunkName: "chunks/plan-create/metered" */ '../views/Admin/Plans/Create/CreateMeteredPlan'),
meta: {
requiresAuth: true,
title: 'routes_title.plan_create'
@@ -162,40 +172,82 @@ const routesAdmin = [
]
},
{
name: 'Plan',
name: 'PlanFixed',
path: '/admin/plan/:id',
component: () =>
import(/* webpackChunkName: "chunks/plan" */ '../views/Admin/Plans/Plan'),
import(/* webpackChunkName: "chunks/plan" */ '../views/Admin/Plans/FixedPlan'),
meta: {
requiresAuth: true,
title: 'routes_title.plan'
},
children: [
{
name: 'PlanSubscribers',
path: '/admin/plan/:id/subscribers',
name: 'PlanFixedSubscribers',
path: '/admin/plan/:id/fixed/subscribers',
component: () =>
import(/* webpackChunkName: "chunks/plan-subscribers" */ '../views/Admin/Plans/PlanTabs/PlanSubscribers'),
import(/* webpackChunkName: "chunks/plan-subscribers" */ '../views/Admin/Plans/Tabs/PlanSubscribers'),
meta: {
requiresAuth: true,
title: 'routes_title.subscribers'
},
},
{
name: 'PlanSettings',
path: '/admin/plan/:id/settings',
name: 'PlanFixedSettings',
path: '/admin/plan/:id/fixed/settings',
component: () =>
import(/* webpackChunkName: "chunks/plan-settings" */ '../views/Admin/Plans/PlanTabs/PlanSettings'),
import(/* webpackChunkName: "chunks/plan-settings" */ '../views/Admin/Plans/Tabs/PlanFixedSettings'),
meta: {
requiresAuth: true,
title: 'routes_title.plan_settings',
},
},
{
name: 'PlanDelete',
path: '/admin/plan/:id/delete',
name: 'PlanFixedDelete',
path: '/admin/plan/:id/fixed/delete',
component: () =>
import(/* webpackChunkName: "chunks/plan-delete" */ '../views/Admin/Plans/PlanTabs/PlanDelete'),
import(/* webpackChunkName: "chunks/plan-delete" */ '../views/Admin/Plans/Tabs/PlanDelete'),
meta: {
requiresAuth: true,
title: 'routes_title.plan_delete',
},
},
]
},
{
name: 'PlanMetered',
path: '/admin/plan/:id',
component: () =>
import(/* webpackChunkName: "chunks/plan" */ '../views/Admin/Plans/MeteredPlan'),
meta: {
requiresAuth: true,
title: 'routes_title.plan'
},
children: [
{
name: 'PlanMeteredSubscribers',
path: '/admin/plan/:id/metered/subscribers',
component: () =>
import(/* webpackChunkName: "chunks/plan-subscribers" */ '../views/Admin/Plans/Tabs/PlanSubscribers'),
meta: {
requiresAuth: true,
title: 'routes_title.subscribers'
},
},
{
name: 'PlanMeteredSettings',
path: '/admin/plan/:id/metered/settings',
component: () =>
import(/* webpackChunkName: "chunks/plan-settings" */ '../views/Admin/Plans/Tabs/PlanMeteredSettings'),
meta: {
requiresAuth: true,
title: 'routes_title.plan_settings',
},
},
{
name: 'PlanMeteredDelete',
path: '/admin/plan/:id/metered/delete',
component: () =>
import(/* webpackChunkName: "chunks/plan-delete" */ '../views/Admin/Plans/Tabs/PlanDelete'),
meta: {
requiresAuth: true,
title: 'routes_title.plan_delete',

View File

@@ -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() {

View File

@@ -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,

View File

@@ -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>

View File

@@ -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',
},
]
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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
},
],
}
},
}

View File

@@ -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>-->

View File

@@ -1,4 +1,5 @@
<?php
namespace App\Users\Actions;
use ByteUnits\Metric;
@@ -12,11 +13,15 @@ class FormatUsageEstimatesAction
// Format usage
$usage = match ($estimate['feature']) {
'bandwidth' => Metric::megabytes($estimate['usage'])->format(),
'storage' => Metric::megabytes($estimate['usage'])->format(),
'storage' => Metric::megabytes($estimate['usage'])->format(),
'flat-fee' => intval($estimate['usage']) . ' ' . __('Pcs.'),
};
// Normalize units
$amount = $estimate['amount'] / 1000;
$amount = match ($estimate['feature']) {
'bandwidth', 'storage' => $estimate['amount'] / 1000,
'flat-fee' => $estimate['amount'],
};
return [
$estimate['feature'] => [

View File

@@ -116,6 +116,10 @@ class UserSubscriptionTest extends TestCase
'feature' => 'storage',
'amount' => 476.28,
'usage' => 3969,
], [
'feature' => 'flat-fee',
'amount' => 2.49,
'usage' => 1,
],
]);
@@ -124,17 +128,24 @@ class UserSubscriptionTest extends TestCase
->toArray();
$expected = [
[
'bandwidth' => [
'feature' => 'bandwidth',
'amount' => 7.54696,
'cost' => '$7.55',
'usage' => '26.02GB',
], [
],
'storage' => [
'feature' => 'storage',
'amount' => 0.47628,
'cost' => '$0.48',
'usage' => '3.97GB',
],
'flat-fee' => [
'feature' => 'flat-fee',
'amount' => 2.49,
'cost' => '$2.49',
'usage' => '1 Pcs.',
],
];
$this->assertEquals($expected, $estimates);