Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: stripe #2473

Merged
merged 9 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 74 additions & 14 deletions src/components/dao/settings-plans-billing.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
import { mapGetters } from 'vuex'
import gql from 'graphql-tag'
import { ORIGIN, PLAN_TYPE } from '~/const'
import { ORIGIN, PLAN_TYPE, PAYMENT_INTERVAL } from '~/const'

const STATES = Object.freeze({
WAITING: 'WAITING',
Expand Down Expand Up @@ -54,7 +54,8 @@ export default {
STATES,
state: STATES.WAITING,

paymentInterval: 'year',
PAYMENT_INTERVAL,
paymentInterval: PAYMENT_INTERVAL.YEAR,

PLAN_TYPE,
planType: PLAN_TYPE.SAAS
Expand All @@ -68,11 +69,19 @@ export default {
const res = await this.$apollo.mutate({
mutation: gql`
mutation createSession(
$daoId: String!
$daoName: String!
$daoType: String!
$daoUrl: String!
$priceId: String!
$redirectDomain: String!
$successUrl: String!
) {
createCheckoutSession(
daoId: $daoId
daoName: $daoName
daoType: $daoType
daoUrl: $daoUrl
priceId: $priceId
redirectDomain: $redirectDomain
successUrl: $successUrl
Expand All @@ -83,9 +92,12 @@ export default {
}
`,
variables: {
daoId: this.selectedDao.docId,
daoName: this.selectedDao.title,
daoType: this.planType,
daoUrl: this.daoSettings.url,
priceId: id,
redirectDomain: ORIGIN,

successUrl: `/${this.daoSettings.url}/configuration?tab=PLANS_AND_BILLING`
}
})
Expand All @@ -95,12 +107,60 @@ export default {
}
},

async upgrade (id) {
this.state = STATES.CREATING_SESSION

const res = await this.$apollo.mutate({
mutation: gql`
mutation updateSubscription(
$subscriptionId: String!
$subscriptionItemId: String!
$priceId: String!
) {
updateSubscription(
subscriptionId: $subscriptionId
subscriptionItemId: $subscriptionItemId
priceId: $priceId
) {
id: planId
}
}
`,
variables: {
subscriptionId: this.selectedDaoPlan.subscriptionId,
subscriptionItemId: this.selectedDaoPlan.subscriptionItemId,
priceId: id
}
})

if (res) {
this.state = STATES.WAITING
}
},

onPlanDialogClose () {
this.state = STATES.WAITING
this.planType = PLAN_TYPE.SAAS
this.paymentInterval = PAYMENT_INTERVAL.YEAR
},

switchPlanType () {
if (this.planType === PLAN_TYPE.SAAS) {
this.planType = PLAN_TYPE.EAAS
this.paymentInterval = null
} else {
this.planType = PLAN_TYPE.SAAS
this.paymentInterval = PAYMENT_INTERVAL.YEAR
}
},

formatMoney (amount) { return amount ? new Intl.NumberFormat().format(parseInt(amount), { style: 'currency' }) : 0 }
},

computed: {
...mapGetters('dao', ['daoSettings', 'selectedDaoPlan']),
...mapGetters('dao', ['daoSettings', 'selectedDao', 'selectedDaoPlan']),

isFreePlan () { return !this.selectedDaoPlan.id },
isPlanModalOpen () { return [STATES.UPDATING_PLAIN, STATES.CREATING_SESSION].includes(this.state) },

plans () {
Expand All @@ -109,7 +169,7 @@ export default {
..._,
id: _.id,
name: _.productName.toLowerCase(),
amountUSD: _.amount / 100 / (_.recurringInterval === 'year' ? 12 : 1),
amountUSD: _.amount / 100 / (_.recurringInterval === PAYMENT_INTERVAL.YEAR ? 12 : 1),
interval: _.recurringInterval
}))
.filter(_ => _.planType === this.planType)
Expand All @@ -124,7 +184,7 @@ export default {

<template lang="pug">
.tab
q-dialog(:value="isPlanModalOpen" @before-hide="state = STATES.WAITING" full-width="full-width")
q-dialog(:value="isPlanModalOpen" @before-hide="onPlanDialogClose" full-width="full-width")
widget.relative.wrapper(
v-if="state === STATES.UPDATING_PLAIN"
:title="$t('configuration.settings-plans-billing.plan.modal.title')"
Expand All @@ -135,7 +195,7 @@ export default {
q-btn.q-px-xl.rounded-border.text-bold(
:color="planType === PLAN_TYPE.EAAS ? 'primary' : 'secondary'"
:label="planType === PLAN_TYPE.EAAS ? 'Single' : 'Ecosystem'"
@click="planType = PLAN_TYPE.EAAS, paymentInterval = null"
@click="switchPlanType"
no-caps
rounded
unelevated
Expand All @@ -148,16 +208,16 @@ export default {
section
nav.full-width.row.justify-center.items-center(v-if="planType === PLAN_TYPE.SAAS")
q-btn.q-px-xl.rounded-border.text-bold(
@click="paymentInterval = 'month'"
:color="paymentInterval === 'month' ? 'primary' : 'secondary'"
@click="paymentInterval = PAYMENT_INTERVAL.MONTH"
:color="paymentInterval === PAYMENT_INTERVAL.MONTH ? 'primary' : 'secondary'"
no-caps
rounded
unelevated
label="Monthly"
)
q-btn.q-px-xl.rounded-border.text-bold(
@click="paymentInterval = 'year'"
:color="paymentInterval === 'year' ? 'primary' : 'secondary'"
@click="paymentInterval = PAYMENT_INTERVAL.YEAR"
:color="paymentInterval === PAYMENT_INTERVAL.YEAR ? 'primary' : 'secondary'"
no-caps
rounded
unelevated
Expand Down Expand Up @@ -192,7 +252,7 @@ export default {
q-btn.q-px-xl.rounded-border.text-bold.q-ml-xs(
:disable="selectedDaoPlan.id === plan.id"
:label="$t('configuration.settings-plans-billing.plan.modal.cta')"
@click="checkout(plan.id)"
@click="isFreePlan ? checkout(plan.id) : upgrade(plan.id)"
color="secondary"
no-caps
rounded
Expand All @@ -208,7 +268,7 @@ export default {
widget.q-mt-xl(bar shadow)
header.row.justify-between
div
.text-xl.text-weight-600.text-primary {{ $t(`plans.${selectedDaoPlan.id}`) }}
.text-xl.text-weight-600.text-primary {{ $t(`plans.${selectedDaoPlan.name}`) }}
p.q-pa-none.q-ma-none.text-3xl.text-primary.text-bold ${{ formatMoney(selectedDaoPlan.amountUSD) }}
//- TODO: Return after beta
//- span.q-ml-xxs.text-sm.text-weight-500 / {{ $('periods.month') }}
Expand All @@ -221,7 +281,7 @@ export default {
footer
div.row.justify-between
p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose Core Members
p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose {{ selectedDaoPlan.coreMembersCount }}
p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose {{ selectedDaoPlan.currentCoreMembersCount }} / {{ selectedDaoPlan.coreMembersCount }}
//- TODO: Return after beta
//- div.row.justify-between.q-mt-xs
//- p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose Community Members
Expand Down
15 changes: 15 additions & 0 deletions src/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,22 @@ export const ROUTE_NAMES = Object.freeze({

export const ORIGIN = window.location.origin

export const PLAN = Object.freeze({
FOUNDER: 'founder'

})

export const PLAN_TYPE = Object.freeze({
EAAS: 'EAAS',
SAAS: 'SAAS'
})

export const PAYMENT_INTERVAL = Object.freeze({
YEAR: 'year',
MONTH: 'month'
})

export const PLAN_STATUS = Object.freeze({
ACTIVE: 'active'

})
28 changes: 21 additions & 7 deletions src/layouts/DhoSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,20 @@ import gql from 'graphql-tag'
const MAX_NUM_OF_RETIRES = 10

const DAO_ACTIVE_QUERY = `

activePlan(daoUrl: $daoUrl) {
subscriptionId
subscriptionItemId
subscriptionStatus
currency
currentPeriodEnd
currentPeriodStart
coreMembersCount
communityMembersCount
price
id: planId
name: planName
}

queryDao @cascade(fields: ["settings"]) {
docId
details_daoName_n
Expand Down Expand Up @@ -166,7 +179,7 @@ const DAO_ACTIVE_QUERY = `
settings_documentationURL_s
}

settings(filter: { settings_daoUrl_s: { regexp: $regexp } }) {
settings(filter: { settings_daoUrl_s: { regexp: $regexp } }) {
ecosystem_name_s
ecosystem_logo_s
ecosystem_domain_s
Expand All @@ -180,7 +193,7 @@ const DAO_ACTIVE_QUERY = `
settings_daoTitle_s
settings_daoDescription_s
settings_governanceTokenContract_n

settings_pegTokenName_s
settings_pegToken_a
settings_pegTokenContract_n
Expand Down Expand Up @@ -293,21 +306,22 @@ export default {

apollo: {
dao: {
query: gql`query activeDao($regexp: String!) { ${DAO_ACTIVE_QUERY} }`,
query: gql`query activeDao($daoUrl: String!, $regexp: String!) { ${DAO_ACTIVE_QUERY} }`,
update: data => data.queryDao,
skip () { return !this.dhoname || !this.daoRegexp },
variables () { return { regexp: this.daoRegexp } },
variables () { return { regexp: this.daoRegexp, daoUrl: this.dhoname } },

result (res) {
const data = res.data?.queryDao
const data = res?.data

if (!(data?.length)) {
if (!data?.queryDao?.length) {
this.daoQueryNumberOfRetires++
if (this.daoQueryNumberOfRetires > MAX_NUM_OF_RETIRES) {
this.$router.push({ path: '/not-found' })
} else {
this.$apollo.queries.dao.refetch()
}
return
}

this.$store.commit('dao/switchDao', data)
Expand Down
51 changes: 26 additions & 25 deletions src/layouts/MultiDhoLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,16 @@ export default {
},

apollo: {
member: {
dhos: {
query: require('../query/profile/profile-dhos.gql'),
update: data => { return data.getMember },
update: data => data?.getMember?.memberof.map(dao => ({
name: dao.details_daoName_n,
title: dao.settings[0].settings_daoTitle_s,
icon: dao.settings[0].settings_logo_s,
logo: dao.settings[0].settings_logo_s,
isHypha: dao.settings[0].settings_isHypha_i,
url: dao.settings[0].settings_daoUrl_s
})),
skip () { return !this.account },
variables () { return { username: this.account } }
}
Expand Down Expand Up @@ -229,12 +236,8 @@ export default {
...mapGetters('search', ['search']),

breadcrumbs () { return this.$route.meta ? this.$route.meta.breadcrumbs : null },
dhos () {
const member = (this.$apolloData && this.$apolloData.member) ? this.$apolloData.member : this.member
return this.getDaos(member)
},

isLoading () { return this.$apollo.queries.member.loading },
isLoading () { return this.$apollo.queries.dhos.loading },
status () { return this.$route.meta ? this.$route.meta.status ?? 'red' : 'red' },

loadingAccount () { return localStorage?.getItem('autoLogin') && !this.account },
Expand Down Expand Up @@ -281,22 +284,7 @@ export default {
}
}
},
getDaos (member) {
const results = []
if (member) {
member.memberof?.forEach((dao) => {
results.push({
name: dao.details_daoName_n,
title: dao.settings[0].settings_daoTitle_s,
icon: dao.settings[0].settings_logo_s,
logo: dao.settings[0].settings_logo_s,
isHypha: dao.settings[0].settings_isHypha_i,
url: dao.settings[0].settings_daoUrl_s
})
})
}
return results
},

async getProfile () {
if (this.account) {
const profile = await this.getPublicProfile(this.account)
Expand Down Expand Up @@ -447,7 +435,20 @@ export default {
//- Because iOS z-index doesn`t work
router-view(v-if="$router.currentRoute.name === 'proposal-create' && $q.screen.lt.md")
q-header.bg-white(v-if="$q.screen.lt.lg && $route.name !== ROUTE_NAMES.PROPOSAL_DETAIL && $route.name !== ROUTE_NAMES.CREATE_YOUR_DAO")
top-navigation(:unreadNotifications="countObjectsWithKeyValue(notifications, 'read', false)" :notifications="notifications" @openNotifications="languageSettings = false, right = false, showNotificationsBar = true" @isActiveRoute="isActiveRoute" @showLangSettings="languageSettings = true, right = false" :showTopButtons="showTopBarItems" :profile="profile" @toggle-sidebar="!$q.screen.md ? right = true : showMinimizedMenu = true" @search="onSearch" :dho="dho" :dhos="getDaos($apolloData.data.member)" :selectedDaoPlan="selectedDaoPlan")
top-navigation(
:dho="dho"
:dhos="dhos"
:selectedDaoPlan="selectedDaoPlan"
@search="onSearch"
:notifications="notifications"
:profile="profile"
:showTopButtons="showTopBarItems"
:unreadNotifications="countObjectsWithKeyValue(notifications, 'read', false)"
@isActiveRoute="isActiveRoute"
@openNotifications="languageSettings = false, right = false, showNotificationsBar = true"
@showLangSettings="languageSettings = true, right = false"
@toggle-sidebar="!$q.screen.md ? right = true : showMinimizedMenu = true"
)
q-page-container.bg-white.window-height.q-py-sm(:class="{ 'q-pr-sm': $q.screen.gt.md, 'q-px-xs': !$q.screen.gt.md}")
.bg-internal-bg.content.full-height
q-resize-observer(@resize="onContainerResize")
Expand Down Expand Up @@ -557,7 +558,7 @@ export default {
q-footer.bg-white(v-if="$q.screen.lt.lg && $route.name !== ROUTE_NAMES.PROPOSAL_DETAIL && $route.name !== ROUTE_NAMES.CREATE_YOUR_DAO" :style="{ height: '74px' }")
bottom-navigation
q-drawer(v-else v-model="left" side="left" :width="80" persistent="persistent" :show-if-above="true")
left-navigation(:dho="dho" :dhos="getDaos($apolloData.data.member)")
left-navigation(:dho="dho" :dhos="dhos")
</template>
<style lang="stylus" scoped>
.rounded-border
Expand Down
Loading
Loading