You've already forked pages
forked from didirus/AstralRinth
fix: allow payouts that go over the tax limit by prefilling form (#4478)
* feat: start on fix * fix: withdraw btn * fix: lint issues * fix: use button rather than span * fix: lint issues --------- Co-authored-by: --global <--global>
This commit is contained in:
@@ -239,6 +239,7 @@ async function continueForm() {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error occurred while continuing tax form:', error)
|
||||
handleCancel()
|
||||
} finally {
|
||||
manualLoading.value = false
|
||||
}
|
||||
|
||||
@@ -68,25 +68,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mt-4">
|
||||
<span
|
||||
:class="{
|
||||
'disabled-cursor-wrapper': userBalance.available < minWithdraw || blockedByTax,
|
||||
}"
|
||||
>
|
||||
<ButtonStyled color="brand">
|
||||
<nuxt-link
|
||||
:aria-disabled="
|
||||
userBalance.available < minWithdraw || blockedByTax ? 'true' : 'false'
|
||||
"
|
||||
:class="{ 'disabled-link': userBalance.available < minWithdraw || blockedByTax }"
|
||||
:disabled="!!(userBalance.available < minWithdraw || blockedByTax) || null"
|
||||
:tabindex="userBalance.available < minWithdraw || blockedByTax ? -1 : undefined"
|
||||
to="/dashboard/revenue/withdraw"
|
||||
>
|
||||
<TransferIcon /> Withdraw
|
||||
</nuxt-link>
|
||||
</ButtonStyled>
|
||||
</span>
|
||||
<ButtonStyled color="brand">
|
||||
<nuxt-link
|
||||
v-if="!(userBalance.available < minWithdraw || blockedByTax)"
|
||||
to="/dashboard/revenue/withdraw"
|
||||
>
|
||||
<TransferIcon /> Withdraw
|
||||
</nuxt-link>
|
||||
<button v-else class="disabled"><TransferIcon /> Withdraw</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled>
|
||||
<NuxtLink to="/dashboard/revenue/transfers">
|
||||
<HistoryIcon />
|
||||
@@ -176,9 +166,19 @@ const { addNotification, handleError } = injectNotificationManager()
|
||||
const auth = await useAuth()
|
||||
const minWithdraw = ref(0.01)
|
||||
|
||||
const { data: userBalance } = await useAsyncData(`payout/balance`, () =>
|
||||
useBaseFetch(`payout/balance`, { apiVersion: 3 }),
|
||||
)
|
||||
const { data: userBalance } = await useAsyncData(`payout/balance`, async () => {
|
||||
const response = await useBaseFetch(`payout/balance`, { apiVersion: 3 })
|
||||
return {
|
||||
...response,
|
||||
available: parseFloat(response.available),
|
||||
withdrawn_lifetime: parseFloat(response.withdrawn_lifetime),
|
||||
withdrawn_ytd: parseFloat(response.withdrawn_ytd),
|
||||
pending: parseFloat(response.pending),
|
||||
dates: Object.fromEntries(
|
||||
Object.entries(response.dates).map(([date, value]) => [date, parseFloat(value)]),
|
||||
),
|
||||
}
|
||||
})
|
||||
|
||||
const blockedByTax = computed(() => {
|
||||
const status = userBalance.value?.form_completion_status ?? 'unknown'
|
||||
@@ -250,14 +250,6 @@ strong {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.disabled-cursor-wrapper {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.disabled-link {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.grid-display {
|
||||
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
<template>
|
||||
<CreatorTaxFormModal
|
||||
ref="taxFormModalRef"
|
||||
@success="onTaxFormSuccess"
|
||||
@cancelled="onTaxFormCancelled"
|
||||
/>
|
||||
<section class="universal-card">
|
||||
<Breadcrumbs
|
||||
current-title="Withdraw"
|
||||
@@ -135,6 +140,11 @@
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<p v-if="willTriggerTaxForm" class="font-bold text-orange">
|
||||
This withdrawal will exceed $600 for the year. You will be prompted to complete a tax form
|
||||
before proceeding.
|
||||
</p>
|
||||
|
||||
<p v-if="blockedByTax" class="font-bold text-orange">
|
||||
You have withdrawn over $600 this year. To continue withdrawing, you must complete a tax form.
|
||||
</p>
|
||||
@@ -207,6 +217,7 @@ import { all } from 'iso-3166-1'
|
||||
import { Multiselect } from 'vue-multiselect'
|
||||
|
||||
import VenmoIcon from '~/assets/images/external/venmo.svg?component'
|
||||
import CreatorTaxFormModal from '~/components/ui/dashboard/CreatorTaxFormModal.vue'
|
||||
|
||||
const { addNotification } = injectNotificationManager()
|
||||
const auth = await useAuth()
|
||||
@@ -227,7 +238,19 @@ const country = ref(
|
||||
|
||||
const [{ data: userBalance }, { data: payoutMethods, refresh: refreshPayoutMethods }] =
|
||||
await Promise.all([
|
||||
useAsyncData(`payout/balance`, () => useBaseFetch(`payout/balance`, { apiVersion: 3 })),
|
||||
useAsyncData(`payout/balance`, async () => {
|
||||
const response = await useBaseFetch(`payout/balance`, { apiVersion: 3 })
|
||||
return {
|
||||
...response,
|
||||
available: parseFloat(response.available),
|
||||
withdrawn_lifetime: parseFloat(response.withdrawn_lifetime),
|
||||
withdrawn_ytd: parseFloat(response.withdrawn_ytd),
|
||||
pending: parseFloat(response.pending),
|
||||
dates: Object.fromEntries(
|
||||
Object.entries(response.dates).map(([date, value]) => [date, parseFloat(value)]),
|
||||
),
|
||||
}
|
||||
}),
|
||||
useAsyncData(`payout/methods?country=${country.value.id}`, () =>
|
||||
useBaseFetch(`payout/methods?country=${country.value.id}`, { apiVersion: 3 }),
|
||||
),
|
||||
@@ -334,6 +357,13 @@ const blockedByTax = computed(() => {
|
||||
return thresholdMet && status !== 'complete'
|
||||
})
|
||||
|
||||
const willTriggerTaxForm = computed(() => {
|
||||
const status = userBalance.value?.form_completion_status ?? 'unknown'
|
||||
const currentWithdrawn = userBalance.value?.withdrawn_ytd ?? 0
|
||||
const wouldExceedThreshold = currentWithdrawn + parsedAmount.value >= 600
|
||||
return wouldExceedThreshold && status !== 'complete' && !blockedByTax.value
|
||||
})
|
||||
|
||||
watch(country, async () => {
|
||||
await refreshPayoutMethods()
|
||||
if (payoutMethods.value && payoutMethods.value[0]) {
|
||||
@@ -353,7 +383,18 @@ watch(selectedMethod, () => {
|
||||
agreedTerms.value = false
|
||||
})
|
||||
|
||||
const taxFormModalRef = ref(null)
|
||||
const taxFormCancelled = ref(false)
|
||||
|
||||
async function withdraw() {
|
||||
if (willTriggerTaxForm.value) {
|
||||
taxFormCancelled.value = false
|
||||
if (taxFormModalRef.value && taxFormModalRef.value.startTaxForm) {
|
||||
await taxFormModalRef.value.startTaxForm(new MouseEvent('click'))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
startLoading()
|
||||
try {
|
||||
const auth = await useAuth()
|
||||
@@ -386,6 +427,31 @@ async function withdraw() {
|
||||
}
|
||||
stopLoading()
|
||||
}
|
||||
|
||||
async function onTaxFormSuccess() {
|
||||
// Refresh user balance to get updated form completion status
|
||||
const updatedBalance = await useBaseFetch(`payout/balance`, { apiVersion: 3 })
|
||||
userBalance.value = updatedBalance
|
||||
|
||||
if (updatedBalance?.form_completion_status === 'complete') {
|
||||
await withdraw()
|
||||
} else {
|
||||
addNotification({
|
||||
title: 'Tax form incomplete',
|
||||
text: 'You must complete a tax form for this withdrawal.',
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function onTaxFormCancelled() {
|
||||
taxFormCancelled.value = true
|
||||
addNotification({
|
||||
title: 'Withdrawal canceled',
|
||||
text: 'You must complete a tax form for this withdrawal.',
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user