From 7b7eafc18891b057a27af75cec5c95a204acc6a9 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 13 Nov 2024 12:08:30 +0530 Subject: [PATCH] fix: implemented Billing, Plans, Invoices in sidebar - body layout --- billing/package.json | 5 +- billing/src/App.vue | 15 +- billing/src/components/AddCardModal.vue | 35 ++ .../src/components/AddPrepaidCreditsModal.vue | 32 ++ billing/src/components/AddressForm.vue | 246 ++++++++++++ billing/src/components/AppSidebar.vue | 97 +++++ billing/src/components/BillingDetails.vue | 72 ++++ .../src/components/BillingDetailsModal.vue | 37 ++ billing/src/components/BuyCreditsRazorpay.vue | 133 +++++++ billing/src/components/BuyCreditsStripe.vue | 172 +++++++++ billing/src/components/CardForm.vue | 362 ++++++++++++++++++ billing/src/components/ChangeCardModal.vue | 137 +++++++ billing/src/components/CurrentPlan.vue | 172 +++++++++ billing/src/components/DropdownItem.vue | 22 ++ billing/src/components/PaymentDetails.vue | 264 +++++++++++++ billing/src/components/PlanDetails.vue | 26 ++ billing/src/components/PrepaidCreditsForm.vue | 122 ++++++ billing/src/components/SidebarLink.vue | 87 +++++ billing/src/components/TrialBanner.vue | 58 +++ .../src/components/UpgradePlanStepsModal.vue | 126 ++++++ billing/src/dialogs.js | 43 +++ billing/src/icons/BillingIcon.vue | 16 + billing/src/icons/CardIcon.vue | 10 + billing/src/icons/CollapseSidebarIcon.vue | 17 + billing/src/icons/GreenCheckIcon.vue | 16 + billing/src/icons/InvoiceIcon.vue | 16 + billing/src/icons/LightningIcon.vue | 16 + billing/src/icons/PlansIcon.vue | 10 + billing/src/icons/UnPaidBillIcon.vue | 16 + billing/src/logo/Amex.vue | 70 ++++ billing/src/logo/Generic.vue | 24 ++ billing/src/logo/JCB.vue | 96 +++++ billing/src/logo/MasterCard.vue | 78 ++++ billing/src/logo/PoweredByStripeLogo.vue | 27 ++ billing/src/logo/RazorpayLogo.vue | 50 +++ billing/src/logo/StripeLogo.vue | 48 +++ billing/src/logo/UnionPay.vue | 31 ++ billing/src/logo/Visa.vue | 82 ++++ billing/src/main.js | 6 + billing/src/pages/Billing.vue | 46 +++ billing/src/pages/BillingHistory.vue | 208 ++++++++++ billing/src/pages/Cards.vue | 7 + billing/src/pages/Plans.vue | 225 +++++++++++ billing/src/router.js | 31 ++ billing/src/utils.js | 51 +++ billing/vite.config.js | 3 +- frappe/hooks.py | 1 + 47 files changed, 3459 insertions(+), 5 deletions(-) create mode 100644 billing/src/components/AddCardModal.vue create mode 100644 billing/src/components/AddPrepaidCreditsModal.vue create mode 100644 billing/src/components/AddressForm.vue create mode 100644 billing/src/components/AppSidebar.vue create mode 100644 billing/src/components/BillingDetails.vue create mode 100644 billing/src/components/BillingDetailsModal.vue create mode 100644 billing/src/components/BuyCreditsRazorpay.vue create mode 100644 billing/src/components/BuyCreditsStripe.vue create mode 100644 billing/src/components/CardForm.vue create mode 100644 billing/src/components/ChangeCardModal.vue create mode 100644 billing/src/components/CurrentPlan.vue create mode 100644 billing/src/components/DropdownItem.vue create mode 100644 billing/src/components/PaymentDetails.vue create mode 100644 billing/src/components/PlanDetails.vue create mode 100644 billing/src/components/PrepaidCreditsForm.vue create mode 100644 billing/src/components/SidebarLink.vue create mode 100644 billing/src/components/TrialBanner.vue create mode 100644 billing/src/components/UpgradePlanStepsModal.vue create mode 100644 billing/src/dialogs.js create mode 100644 billing/src/icons/BillingIcon.vue create mode 100644 billing/src/icons/CardIcon.vue create mode 100644 billing/src/icons/CollapseSidebarIcon.vue create mode 100644 billing/src/icons/GreenCheckIcon.vue create mode 100644 billing/src/icons/InvoiceIcon.vue create mode 100644 billing/src/icons/LightningIcon.vue create mode 100644 billing/src/icons/PlansIcon.vue create mode 100644 billing/src/icons/UnPaidBillIcon.vue create mode 100644 billing/src/logo/Amex.vue create mode 100644 billing/src/logo/Generic.vue create mode 100644 billing/src/logo/JCB.vue create mode 100644 billing/src/logo/MasterCard.vue create mode 100644 billing/src/logo/PoweredByStripeLogo.vue create mode 100644 billing/src/logo/RazorpayLogo.vue create mode 100644 billing/src/logo/StripeLogo.vue create mode 100644 billing/src/logo/UnionPay.vue create mode 100644 billing/src/logo/Visa.vue create mode 100644 billing/src/pages/Billing.vue create mode 100644 billing/src/pages/BillingHistory.vue create mode 100644 billing/src/pages/Cards.vue create mode 100644 billing/src/pages/Plans.vue create mode 100644 billing/src/router.js create mode 100644 billing/src/utils.js diff --git a/billing/package.json b/billing/package.json index 2456d67b73..e8f179224f 100644 --- a/billing/package.json +++ b/billing/package.json @@ -9,9 +9,12 @@ "serve": "vite preview" }, "dependencies": { + "@stripe/stripe-js": "^1.3.0", + "@vueuse/core": "^11.2.0", "frappe-ui": "^v0.1.72", "tailwindcss": "^3.3.3", - "vue": "^3.4.12" + "vue": "^3.4.12", + "vue-router": "^4.2.2" }, "devDependencies": { "@vitejs/plugin-vue": "^4.2.3", diff --git a/billing/src/App.vue b/billing/src/App.vue index 2d3067be64..58c3a56a61 100644 --- a/billing/src/App.vue +++ b/billing/src/App.vue @@ -1,7 +1,18 @@ diff --git a/billing/src/components/AddCardModal.vue b/billing/src/components/AddCardModal.vue new file mode 100644 index 0000000000..6eaa06005a --- /dev/null +++ b/billing/src/components/AddCardModal.vue @@ -0,0 +1,35 @@ + + diff --git a/billing/src/components/AddPrepaidCreditsModal.vue b/billing/src/components/AddPrepaidCreditsModal.vue new file mode 100644 index 0000000000..0c0417649f --- /dev/null +++ b/billing/src/components/AddPrepaidCreditsModal.vue @@ -0,0 +1,32 @@ + + diff --git a/billing/src/components/AddressForm.vue b/billing/src/components/AddressForm.vue new file mode 100644 index 0000000000..73e37ced7a --- /dev/null +++ b/billing/src/components/AddressForm.vue @@ -0,0 +1,246 @@ + + diff --git a/billing/src/components/AppSidebar.vue b/billing/src/components/AppSidebar.vue new file mode 100644 index 0000000000..7ddb9ea1db --- /dev/null +++ b/billing/src/components/AppSidebar.vue @@ -0,0 +1,97 @@ + + diff --git a/billing/src/components/BillingDetails.vue b/billing/src/components/BillingDetails.vue new file mode 100644 index 0000000000..9c4b5b40f6 --- /dev/null +++ b/billing/src/components/BillingDetails.vue @@ -0,0 +1,72 @@ + + diff --git a/billing/src/components/BillingDetailsModal.vue b/billing/src/components/BillingDetailsModal.vue new file mode 100644 index 0000000000..36b4d76a38 --- /dev/null +++ b/billing/src/components/BillingDetailsModal.vue @@ -0,0 +1,37 @@ + + diff --git a/billing/src/components/BuyCreditsRazorpay.vue b/billing/src/components/BuyCreditsRazorpay.vue new file mode 100644 index 0000000000..5d2f5c2e0d --- /dev/null +++ b/billing/src/components/BuyCreditsRazorpay.vue @@ -0,0 +1,133 @@ + + diff --git a/billing/src/components/BuyCreditsStripe.vue b/billing/src/components/BuyCreditsStripe.vue new file mode 100644 index 0000000000..f16d735abe --- /dev/null +++ b/billing/src/components/BuyCreditsStripe.vue @@ -0,0 +1,172 @@ + + diff --git a/billing/src/components/CardForm.vue b/billing/src/components/CardForm.vue new file mode 100644 index 0000000000..195f140c39 --- /dev/null +++ b/billing/src/components/CardForm.vue @@ -0,0 +1,362 @@ + + diff --git a/billing/src/components/ChangeCardModal.vue b/billing/src/components/ChangeCardModal.vue new file mode 100644 index 0000000000..c38225f689 --- /dev/null +++ b/billing/src/components/ChangeCardModal.vue @@ -0,0 +1,137 @@ + + diff --git a/billing/src/components/CurrentPlan.vue b/billing/src/components/CurrentPlan.vue new file mode 100644 index 0000000000..f9bc41e5f3 --- /dev/null +++ b/billing/src/components/CurrentPlan.vue @@ -0,0 +1,172 @@ + + diff --git a/billing/src/components/DropdownItem.vue b/billing/src/components/DropdownItem.vue new file mode 100644 index 0000000000..bcb59b79fe --- /dev/null +++ b/billing/src/components/DropdownItem.vue @@ -0,0 +1,22 @@ + + diff --git a/billing/src/components/PaymentDetails.vue b/billing/src/components/PaymentDetails.vue new file mode 100644 index 0000000000..876a2a66db --- /dev/null +++ b/billing/src/components/PaymentDetails.vue @@ -0,0 +1,264 @@ + + diff --git a/billing/src/components/PlanDetails.vue b/billing/src/components/PlanDetails.vue new file mode 100644 index 0000000000..2814d128bd --- /dev/null +++ b/billing/src/components/PlanDetails.vue @@ -0,0 +1,26 @@ + + + diff --git a/billing/src/components/PrepaidCreditsForm.vue b/billing/src/components/PrepaidCreditsForm.vue new file mode 100644 index 0000000000..71dbd56d20 --- /dev/null +++ b/billing/src/components/PrepaidCreditsForm.vue @@ -0,0 +1,122 @@ + + diff --git a/billing/src/components/SidebarLink.vue b/billing/src/components/SidebarLink.vue new file mode 100644 index 0000000000..550c27cac3 --- /dev/null +++ b/billing/src/components/SidebarLink.vue @@ -0,0 +1,87 @@ + + + diff --git a/billing/src/components/TrialBanner.vue b/billing/src/components/TrialBanner.vue new file mode 100644 index 0000000000..a274b267f7 --- /dev/null +++ b/billing/src/components/TrialBanner.vue @@ -0,0 +1,58 @@ + + diff --git a/billing/src/components/UpgradePlanStepsModal.vue b/billing/src/components/UpgradePlanStepsModal.vue new file mode 100644 index 0000000000..df0be0bb83 --- /dev/null +++ b/billing/src/components/UpgradePlanStepsModal.vue @@ -0,0 +1,126 @@ + + diff --git a/billing/src/dialogs.js b/billing/src/dialogs.js new file mode 100644 index 0000000000..344ba3b20e --- /dev/null +++ b/billing/src/dialogs.js @@ -0,0 +1,43 @@ +import { Dialog, ErrorMessage } from 'frappe-ui' +import { reactive, ref, h } from 'vue' + +let dialogs = ref([]) + +export let Dialogs = { + name: 'Dialogs', + render() { + return dialogs.value.map((dialog) => { + return h( + Dialog, + { + options: dialog, + modelValue: dialog.show, + 'onUpdate:modelValue': (val) => (dialog.show = val), + onClose: () => { + let index = dialogs.value.indexOf(dialog) + dialogs.value.splice(index, 1) + dialog.onClose && dialog.onClose() + }, + }, + { + 'body-content': () => { + return [ + dialog.message && + h('p', { class: 'text-p-base text-gray-700' }, dialog.message), + dialog.html && h('div', { innerHTML: dialog.html }), + h(ErrorMessage, { class: 'mt-2', message: dialog.error }), + ] + }, + }, + ) + }) + }, +} + +export function createDialog(dialogOptions) { + let dialog = reactive(dialogOptions) + dialog.key = 'dialog-' + dialogs.value.length + dialog.show = false + setTimeout(() => (dialog.show = true), 0) + dialogs.value.push(dialog) +} diff --git a/billing/src/icons/BillingIcon.vue b/billing/src/icons/BillingIcon.vue new file mode 100644 index 0000000000..82c74c7cc2 --- /dev/null +++ b/billing/src/icons/BillingIcon.vue @@ -0,0 +1,16 @@ + diff --git a/billing/src/icons/CardIcon.vue b/billing/src/icons/CardIcon.vue new file mode 100644 index 0000000000..dfad3126e9 --- /dev/null +++ b/billing/src/icons/CardIcon.vue @@ -0,0 +1,10 @@ + diff --git a/billing/src/icons/CollapseSidebarIcon.vue b/billing/src/icons/CollapseSidebarIcon.vue new file mode 100644 index 0000000000..1470703acc --- /dev/null +++ b/billing/src/icons/CollapseSidebarIcon.vue @@ -0,0 +1,17 @@ + diff --git a/billing/src/icons/GreenCheckIcon.vue b/billing/src/icons/GreenCheckIcon.vue new file mode 100644 index 0000000000..2496295a30 --- /dev/null +++ b/billing/src/icons/GreenCheckIcon.vue @@ -0,0 +1,16 @@ + diff --git a/billing/src/icons/InvoiceIcon.vue b/billing/src/icons/InvoiceIcon.vue new file mode 100644 index 0000000000..738e4e5948 --- /dev/null +++ b/billing/src/icons/InvoiceIcon.vue @@ -0,0 +1,16 @@ + diff --git a/billing/src/icons/LightningIcon.vue b/billing/src/icons/LightningIcon.vue new file mode 100644 index 0000000000..18c9e08d03 --- /dev/null +++ b/billing/src/icons/LightningIcon.vue @@ -0,0 +1,16 @@ + diff --git a/billing/src/icons/PlansIcon.vue b/billing/src/icons/PlansIcon.vue new file mode 100644 index 0000000000..8c3999d8de --- /dev/null +++ b/billing/src/icons/PlansIcon.vue @@ -0,0 +1,10 @@ + diff --git a/billing/src/icons/UnPaidBillIcon.vue b/billing/src/icons/UnPaidBillIcon.vue new file mode 100644 index 0000000000..a1a01ad2b5 --- /dev/null +++ b/billing/src/icons/UnPaidBillIcon.vue @@ -0,0 +1,16 @@ + diff --git a/billing/src/logo/Amex.vue b/billing/src/logo/Amex.vue new file mode 100644 index 0000000000..e7361565d6 --- /dev/null +++ b/billing/src/logo/Amex.vue @@ -0,0 +1,70 @@ + diff --git a/billing/src/logo/Generic.vue b/billing/src/logo/Generic.vue new file mode 100644 index 0000000000..d5cc1c5501 --- /dev/null +++ b/billing/src/logo/Generic.vue @@ -0,0 +1,24 @@ + diff --git a/billing/src/logo/JCB.vue b/billing/src/logo/JCB.vue new file mode 100644 index 0000000000..4f97fe4fa4 --- /dev/null +++ b/billing/src/logo/JCB.vue @@ -0,0 +1,96 @@ + diff --git a/billing/src/logo/MasterCard.vue b/billing/src/logo/MasterCard.vue new file mode 100644 index 0000000000..6f62a12350 --- /dev/null +++ b/billing/src/logo/MasterCard.vue @@ -0,0 +1,78 @@ + diff --git a/billing/src/logo/PoweredByStripeLogo.vue b/billing/src/logo/PoweredByStripeLogo.vue new file mode 100644 index 0000000000..ab1a074f4d --- /dev/null +++ b/billing/src/logo/PoweredByStripeLogo.vue @@ -0,0 +1,27 @@ + diff --git a/billing/src/logo/RazorpayLogo.vue b/billing/src/logo/RazorpayLogo.vue new file mode 100644 index 0000000000..0efa43e618 --- /dev/null +++ b/billing/src/logo/RazorpayLogo.vue @@ -0,0 +1,50 @@ + diff --git a/billing/src/logo/StripeLogo.vue b/billing/src/logo/StripeLogo.vue new file mode 100644 index 0000000000..558f66c49a --- /dev/null +++ b/billing/src/logo/StripeLogo.vue @@ -0,0 +1,48 @@ + diff --git a/billing/src/logo/UnionPay.vue b/billing/src/logo/UnionPay.vue new file mode 100644 index 0000000000..b726e600b1 --- /dev/null +++ b/billing/src/logo/UnionPay.vue @@ -0,0 +1,31 @@ + diff --git a/billing/src/logo/Visa.vue b/billing/src/logo/Visa.vue new file mode 100644 index 0000000000..6f3fa38f4e --- /dev/null +++ b/billing/src/logo/Visa.vue @@ -0,0 +1,82 @@ + diff --git a/billing/src/main.js b/billing/src/main.js index c323e0086c..a5d944a111 100644 --- a/billing/src/main.js +++ b/billing/src/main.js @@ -1,8 +1,14 @@ import './index.css' import { createApp } from 'vue' +import { FrappeUI, setConfig, frappeRequest } from 'frappe-ui' +import router from './router' import App from './App.vue' let app = createApp(App) +setConfig('resourceFetcher', frappeRequest) +app.use(FrappeUI) +app.use(router) + app.mount('#app') diff --git a/billing/src/pages/Billing.vue b/billing/src/pages/Billing.vue new file mode 100644 index 0000000000..ab5b41a2aa --- /dev/null +++ b/billing/src/pages/Billing.vue @@ -0,0 +1,46 @@ + + diff --git a/billing/src/pages/BillingHistory.vue b/billing/src/pages/BillingHistory.vue new file mode 100644 index 0000000000..6adfeee9e1 --- /dev/null +++ b/billing/src/pages/BillingHistory.vue @@ -0,0 +1,208 @@ + + diff --git a/billing/src/pages/Cards.vue b/billing/src/pages/Cards.vue new file mode 100644 index 0000000000..f2b0a01660 --- /dev/null +++ b/billing/src/pages/Cards.vue @@ -0,0 +1,7 @@ + diff --git a/billing/src/pages/Plans.vue b/billing/src/pages/Plans.vue new file mode 100644 index 0000000000..6798947321 --- /dev/null +++ b/billing/src/pages/Plans.vue @@ -0,0 +1,225 @@ + + diff --git a/billing/src/router.js b/billing/src/router.js new file mode 100644 index 0000000000..aa7f617c41 --- /dev/null +++ b/billing/src/router.js @@ -0,0 +1,31 @@ +import { createRouter, createWebHistory } from 'vue-router' + +const routes = [ + { + path: '/', + name: 'Billing', + component: () => import('./pages/Billing.vue'), + }, + { + path: '/plans', + name: 'Plans', + component: () => import('./pages/Plans.vue'), + }, + { + path: '/invoices', + name: 'Invoices', + component: () => import('./pages/BillingHistory.vue'), + }, + { + path: '/cards', + name: 'Cards', + component: () => import('./pages/Cards.vue'), + }, +] + +let router = createRouter({ + history: createWebHistory('/billing'), + routes, +}) + +export default router diff --git a/billing/src/utils.js b/billing/src/utils.js new file mode 100644 index 0000000000..af7e7a711b --- /dev/null +++ b/billing/src/utils.js @@ -0,0 +1,51 @@ +import Visa from './logo/Visa.vue' +import MasterCard from './logo/MasterCard.vue' +import Amex from './logo/Amex.vue' +import JCB from './logo/JCB.vue' +import UnionPay from './logo/UnionPay.vue' +import Generic from './logo/Generic.vue' +import { h } from 'vue' + +export function calculateTrialEndDays(trialEndDate) { + if (!trialEndDate) return 0 + + trialEndDate = new Date(trialEndDate) + const today = new Date() + const diffTime = trialEndDate - today + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + return diffDays +} + +export function currency(value, currency, fractions = 2) { + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency, + maximumFractionDigits: fractions, + }).format(value) +} + +export function cardBrandIcon(brand) { + let component = { + 'master-card': MasterCard, + mastercard: MasterCard, + visa: Visa, + amex: Amex, + jcb: JCB, + generic: Generic, + 'union-pay': UnionPay, + }[brand || 'generic'] + + if (!component) { + component = Generic + } + + return h(component, { class: 'size-6' }) +} + +export function parseSize(sizeInMB) { + if (sizeInMB < 1024) { + return `${sizeInMB} MB` + } else { + return `${(sizeInMB / 1024).toFixed(0)} GB` + } +} diff --git a/billing/vite.config.js b/billing/vite.config.js index 63133c6698..c25de4c1df 100644 --- a/billing/vite.config.js +++ b/billing/vite.config.js @@ -39,10 +39,9 @@ export default defineConfig({ commonjsOptions: { include: [/tailwind.config.js/, /node_modules/], }, - // minify: false, sourcemap: true, }, optimizeDeps: { - include: ['tailwind.config.js'], + include: ['feather-icons', 'showdown', 'tailwind.config.js'], }, }) diff --git a/frappe/hooks.py b/frappe/hooks.py index 8aa52ed6be..6e4423e663 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -58,6 +58,7 @@ website_route_rules = [ {"from_route": "/newsletters", "to_route": "Newsletter"}, {"from_route": "/profile", "to_route": "me"}, {"from_route": "/app/", "to_route": "app"}, + {"from_route": "/billing/", "to_route": "billing"}, ] website_redirects = [