-
Notifications
You must be signed in to change notification settings - Fork 386
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
web/satellite/vuetify-poc: add upgrade account dialog
This change adds the account upgrade dialog with the first information step. It allows a user to toggle on this dialog from the account dropdown or the dashboard. Issue: #6288 #6292 Change-Id: Ide87612994c999759150c8aa85ead3866e9df1f5
- Loading branch information
1 parent
c14e4b1
commit 1e3da9f
Showing
14 changed files
with
435 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
web/satellite/vuetify-poc/src/components/dialogs/upgradeAccountFlow/InfoBullet.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright (C) 2023 Storj Labs, Inc. | ||
// See LICENSE for copying information. | ||
|
||
<template> | ||
<v-row class="pa-0 flex-nowrap"> | ||
<v-col class="pa-2" cols="1"> | ||
<img v-if="!isPro" src="@/../static/images/modals/upgradeFlow/greyCheckmark.svg" alt="checkmark"> | ||
<img v-else src="@/../static/images/modals/upgradeFlow/greenCheckmark.svg" alt="checkmark"> | ||
</v-col> | ||
<v-col class="pa-2" cols="11"> | ||
<p class="font-weight-bold"> | ||
{{ title }} | ||
<v-tooltip v-if="$slots.moreInfo" max-width="200px" location="top" activator="parent"> | ||
<slot name="moreInfo" /> | ||
</v-tooltip> | ||
</p> | ||
<p>{{ info }}</p> | ||
</v-col> | ||
</v-row> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { VCol, VRow, VTooltip } from 'vuetify/components'; | ||
const props = withDefaults(defineProps<{ | ||
isPro?: boolean; | ||
title: string; | ||
info: string; | ||
}>(), { | ||
isPro: false, | ||
title: '', | ||
info: '', | ||
}); | ||
</script> |
181 changes: 181 additions & 0 deletions
181
web/satellite/vuetify-poc/src/components/dialogs/upgradeAccountFlow/UpgradeAccountDialog.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
// Copyright (C) 2023 Storj Labs, Inc. | ||
// See LICENSE for copying information. | ||
|
||
<template> | ||
<v-dialog | ||
v-model="model" | ||
width="auto" | ||
scrollable | ||
min-width="460px" | ||
:max-width="step === UpgradeAccountStep.Info || step === UpgradeAccountStep.PricingPlanSelection ? '700px' : '460px'" | ||
transition="fade-transition" | ||
:persistent="loading" | ||
> | ||
<v-card ref="content" rounded="xlg"> | ||
<v-card-item class="pl-7 py-4"> | ||
<template v-if="step === UpgradeAccountStep.Success" #prepend> | ||
<img class="d-block" src="@/../static/images/modals/upgradeFlow/success.svg" alt="success"> | ||
</template> | ||
<v-card-title class="font-weight-bold">{{ stepTitles[step] }}</v-card-title> | ||
<template #append> | ||
<v-btn | ||
icon="$close" | ||
variant="text" | ||
size="small" | ||
color="default" | ||
@click="model = false" | ||
/> | ||
</template> | ||
</v-card-item> | ||
|
||
<v-divider class="mx-8" /> | ||
|
||
<v-card-item class="px-8 py-4"> | ||
<v-window v-model="step"> | ||
<v-window-item :value="UpgradeAccountStep.Info"> | ||
<UpgradeInfoStep | ||
:loading="loading" | ||
@upgrade="setSecondStep" | ||
/> | ||
</v-window-item> | ||
</v-window> | ||
</v-card-item> | ||
</v-card> | ||
</v-dialog> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { computed, ref, watch } from 'vue'; | ||
import { VBtn, VCard, VCardItem, VCardTitle, VDialog, VDivider, VWindow, VWindowItem } from 'vuetify/components'; | ||
import { useConfigStore } from '@/store/modules/configStore'; | ||
import { useAppStore } from '@poc/store/appStore'; | ||
import { useUsersStore } from '@/store/modules/usersStore'; | ||
import { useBillingStore } from '@/store/modules/billingStore'; | ||
import { useNotify } from '@/utils/hooks'; | ||
import { PaymentsHttpApi } from '@/api/payments'; | ||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames'; | ||
import { User } from '@/types/users'; | ||
import { useAnalyticsStore } from '@/store/modules/analyticsStore'; | ||
import { PricingPlanInfo } from '@/types/common'; | ||
import UpgradeInfoStep from '@poc/components/dialogs/upgradeAccountFlow/UpgradeInfoStep.vue'; | ||
enum UpgradeAccountStep { | ||
Info = 'infoStep', | ||
Options = 'optionsStep', | ||
AddCC = 'addCCStep', | ||
AddTokens = 'addTokensStep', | ||
Success = 'successStep', | ||
PricingPlanSelection = 'pricingPlanSelectionStep', | ||
PricingPlan = 'pricingPlanStep', | ||
} | ||
const analyticsStore = useAnalyticsStore(); | ||
const configStore = useConfigStore(); | ||
const appStore = useAppStore(); | ||
const usersStore = useUsersStore(); | ||
const billingStore = useBillingStore(); | ||
const notify = useNotify(); | ||
const payments: PaymentsHttpApi = new PaymentsHttpApi(); | ||
const step = ref<UpgradeAccountStep>(UpgradeAccountStep.Info); | ||
const loading = ref<boolean>(false); | ||
const plan = ref<PricingPlanInfo | null>(null); | ||
const content = ref<HTMLElement | null>(null); | ||
const model = computed<boolean>({ | ||
get: () => appStore.state.isUpgradeFlowDialogShown, | ||
set: value => appStore.toggleUpgradeFlow(value), | ||
}); | ||
const stepTitles = computed(() => { | ||
return { | ||
[UpgradeAccountStep.Info]: 'Your account', | ||
[UpgradeAccountStep.Options]: 'Upgrade to Pro', | ||
[UpgradeAccountStep.AddCC]: 'Add Credit Card', | ||
[UpgradeAccountStep.AddTokens]: 'Add tokens', | ||
[UpgradeAccountStep.Success]: 'Success', | ||
[UpgradeAccountStep.PricingPlanSelection]: 'Upgrade', | ||
[UpgradeAccountStep.PricingPlan]: plan.value?.title || '', | ||
}; | ||
}); | ||
/** | ||
* Claims wallet and sets add token step. | ||
*/ | ||
async function onAddTokens(): Promise<void> { | ||
if (loading.value) return; | ||
loading.value = true; | ||
try { | ||
await billingStore.claimWallet(); | ||
analyticsStore.eventTriggered(AnalyticsEvent.ADD_FUNDS_CLICKED); | ||
setStep(UpgradeAccountStep.AddTokens); | ||
} catch (error) { | ||
notify.notifyError(error, AnalyticsErrorEventSource.UPGRADE_ACCOUNT_MODAL); | ||
} | ||
loading.value = false; | ||
} | ||
/** | ||
* Sets specific flow step. | ||
*/ | ||
function setStep(s: UpgradeAccountStep) { | ||
step.value = s; | ||
} | ||
function onSelectPricingPlan(p: PricingPlanInfo) { | ||
plan.value = p; | ||
setStep(UpgradeAccountStep.PricingPlan); | ||
} | ||
/** | ||
* Sets second step in the flow (after user clicks to upgrade). | ||
* Most users will go to the Options step, but if a user is eligible for a | ||
* pricing plan (and pricing plans are enabled), they will be sent to the PricingPlan step. | ||
*/ | ||
async function setSecondStep() { | ||
if (loading.value) return; | ||
loading.value = true; | ||
const user: User = usersStore.state.user; | ||
const pricingPkgsEnabled = configStore.state.config.pricingPackagesEnabled; | ||
if (!pricingPkgsEnabled || !user.partner) { | ||
setStep(UpgradeAccountStep.Options); | ||
loading.value = false; | ||
return; | ||
} | ||
let pkgAvailable = false; | ||
try { | ||
pkgAvailable = await payments.pricingPackageAvailable(); | ||
} catch (error) { | ||
notify.notifyError(error, null); | ||
setStep(UpgradeAccountStep.Options); | ||
loading.value = false; | ||
return; | ||
} | ||
if (!pkgAvailable) { | ||
setStep(UpgradeAccountStep.Options); | ||
loading.value = false; | ||
return; | ||
} | ||
setStep(UpgradeAccountStep.PricingPlanSelection); | ||
loading.value = false; | ||
} | ||
watch(content, (value) => { | ||
if (!value) { | ||
setStep(UpgradeAccountStep.Info); | ||
plan.value = null; | ||
} | ||
}); | ||
</script> |
139 changes: 139 additions & 0 deletions
139
web/satellite/vuetify-poc/src/components/dialogs/upgradeAccountFlow/UpgradeInfoStep.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Copyright (C) 2023 Storj Labs, Inc. | ||
// See LICENSE for copying information. | ||
|
||
<template> | ||
<v-row> | ||
<v-col v-if="!smAndDown" cols="6"> | ||
<h4 class="font-weight-bold mb-2">Free</h4> | ||
<v-btn | ||
block | ||
disabled | ||
color="grey" | ||
> | ||
Current | ||
</v-btn> | ||
<div class="border-sm rounded-lg pa-4 mt-3 mb-3"> | ||
<InfoBullet title="Projects" :info="freeProjects" /> | ||
<InfoBullet title="Storage" :info="`${freeUsageValue(user.projectStorageLimit)} limit`" /> | ||
<InfoBullet title="Egress" :info="`${freeUsageValue(user.projectBandwidthLimit)} limit`" /> | ||
<InfoBullet title="Segments" :info="`${user.projectSegmentLimit.toLocaleString()} segments limit`" /> | ||
<InfoBullet title="Link Sharing" info="Link sharing with Storj domain" /> | ||
</div> | ||
</v-col> | ||
<v-col :cols="smAndDown ? 12 : '6'"> | ||
<h4 class="font-weight-bold mb-2">Pro Account</h4> | ||
<v-btn | ||
class="mb-1" | ||
block | ||
color="success" | ||
:loading="loading" | ||
@click="emit('upgrade')" | ||
> | ||
Upgrade to Pro | ||
</v-btn> | ||
<div class="border-sm rounded-lg pa-4 mt-3 mb-3"> | ||
<InfoBullet is-pro title="Projects" :info="projectsInfo" /> | ||
<InfoBullet is-pro :title="storagePrice" :info="storagePriceInfo" /> | ||
<InfoBullet is-pro :title="downloadPrice" :info="downloadInfo"> | ||
<template v-if="downloadMoreInfo" #moreInfo> | ||
<p>{{ downloadMoreInfo }}</p> | ||
</template> | ||
</InfoBullet> | ||
<InfoBullet is-pro title="Segments" :info="segmentInfo"> | ||
<template #moreInfo> | ||
<a | ||
class="text-surface" | ||
href="https://docs.storj.io/dcs/billing-payment-and-accounts-1/pricing/billing-and-payment" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
Learn more about segments | ||
</a> | ||
</template> | ||
</InfoBullet> | ||
<InfoBullet is-pro title="Secure Custom Domains (HTTPS)" info="Link sharing with your domain" /> | ||
</div> | ||
</v-col> | ||
</v-row> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { computed, onBeforeMount, ref } from 'vue'; | ||
import { VBtn, VCol, VRow } from 'vuetify/components'; | ||
import { useDisplay } from 'vuetify'; | ||
import { useUsersStore } from '@/store/modules/usersStore'; | ||
import { useNotify } from '@/utils/hooks'; | ||
import { User } from '@/types/users'; | ||
import { Size } from '@/utils/bytesSize'; | ||
import InfoBullet from '@poc/components/dialogs/upgradeAccountFlow/InfoBullet.vue'; | ||
const usersStore = useUsersStore(); | ||
const notify = useNotify(); | ||
const { smAndDown } = useDisplay(); | ||
const props = defineProps<{ | ||
loading: boolean; | ||
}>(); | ||
const emit = defineEmits<{ | ||
upgrade: []; | ||
}>(); | ||
const storagePrice = ref<string>('Storage $0.004 GB / month'); | ||
const storagePriceInfo = ref<string>('25 GB free included'); | ||
const segmentInfo = ref<string>('$0.0000088 segment per month'); | ||
const projectsInfo = ref<string>('3 projects + more on request'); | ||
const downloadPrice = ref<string>('Egress $0.007 GB'); | ||
const downloadInfo = ref<string>('25 GB free every month'); | ||
const downloadMoreInfo = ref<string>(''); | ||
/** | ||
* Returns user entity from store. | ||
*/ | ||
const user = computed((): User => { | ||
return usersStore.state.user; | ||
}); | ||
/** | ||
* Returns formatted free projects count. | ||
*/ | ||
const freeProjects = computed((): string => { | ||
return `${user.value.projectLimit} project${user.value.projectLimit > 1 ? 's' : ''}`; | ||
}); | ||
/** | ||
* Returns formatted free usage value. | ||
*/ | ||
function freeUsageValue(value: number): string { | ||
const size = new Size(value); | ||
return `${size.formattedBytes} ${size.label}`; | ||
} | ||
/** | ||
* Lifecycle hook before initial render. | ||
* If applicable, loads additional clarifying text based on user partner. | ||
*/ | ||
onBeforeMount(async () => { | ||
try { | ||
const partner = usersStore.state.user.partner; | ||
const config = (await import('@poc/components/dialogs/upgradeAccountFlow/upgradeConfig.json')).default; | ||
if (partner && config[partner]) { | ||
if (config[partner].storagePrice) { | ||
storagePrice.value = config[partner].storagePrice; | ||
} | ||
if (config[partner].downloadInfo) { | ||
downloadInfo.value = config[partner].downloadInfo; | ||
} | ||
if (config[partner].downloadMoreInfo) { | ||
downloadMoreInfo.value = config[partner].downloadMoreInfo; | ||
} | ||
} | ||
} catch (e) { | ||
notify.error('No configuration file for page.', null); | ||
} | ||
}); | ||
</script> |
1 change: 1 addition & 0 deletions
1
web/satellite/vuetify-poc/src/components/dialogs/upgradeAccountFlow/upgradeConfig.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{} |
Oops, something went wrong.