|
1 | 1 | <template> |
2 | 2 | <div class="flex flex-row gap-2 md:gap-3"> |
3 | 3 | <div |
4 | | - class="flex h-10 min-h-10 w-10 min-w-10 justify-center rounded-full border-[1px] border-solid border-button-bg bg-bg-raised !p-0 shadow-md md:h-12 md:min-h-12 md:w-12 md:min-w-12" |
| 4 | + class="flex h-10 min-h-10 w-10 min-w-10 items-center justify-center rounded-full border-[1px] border-solid border-button-bg bg-bg-raised !p-0 shadow-md md:h-12 md:min-h-12 md:w-12 md:min-w-12" |
5 | 5 | > |
6 | | - <ArrowDownIcon v-if="isIncome" class="my-auto size-6 text-secondary md:size-8" /> |
7 | | - <ArrowUpIcon v-else class="my-auto size-6 text-secondary md:size-8" /> |
| 6 | + <img |
| 7 | + v-if="methodIconUrl" |
| 8 | + :src="methodIconUrl" |
| 9 | + alt="" |
| 10 | + class="size-6 rounded-full object-cover md:size-8" |
| 11 | + /> |
| 12 | + <component |
| 13 | + :is="methodIconComponent" |
| 14 | + v-else-if="methodIconComponent" |
| 15 | + class="size-6 md:size-8" |
| 16 | + /> |
| 17 | + <ArrowDownIcon v-else-if="isIncome" class="size-6 text-secondary md:size-8" /> |
| 18 | + <ArrowUpIcon v-else class="size-6 text-secondary md:size-8" /> |
8 | 19 | </div> |
9 | 20 | <div class="flex w-full flex-row justify-between"> |
10 | 21 | <div class="flex flex-col"> |
11 | 22 | <span class="text-base font-semibold text-contrast md:text-lg">{{ |
12 | 23 | transaction.type === 'payout_available' |
13 | 24 | ? formatPayoutSource(transaction.payout_source) |
14 | | - : formatMethodName(transaction.method_type || transaction.method) |
| 25 | + : formatMethodName(transaction.method_type || transaction.method, transaction.method_id) |
15 | 26 | }}</span> |
16 | 27 | <span class="text-xs text-secondary md:text-sm"> |
17 | 28 | <template v-if="transaction.type === 'withdrawal'"> |
|
33 | 44 | <div class="my-auto flex flex-row items-center gap-2"> |
34 | 45 | <span |
35 | 46 | class="text-base font-semibold md:text-lg" |
36 | | - :class="transaction.type === 'payout_available' ? 'text-green' : 'text-contrast'" |
37 | | - >{{ formatMoney(transaction.amount) }}</span |
| 47 | + :class="isIncome ? 'text-green' : 'text-contrast'" |
| 48 | + >{{ isIncome ? '' : '-' }}{{ formatMoney(transaction.amount) }}</span |
38 | 49 | > |
39 | 50 | <template v-if="transaction.type === 'withdrawal' && transaction.status === 'in-transit'"> |
40 | 51 | <Tooltip theme="dismissable-prompt" :triggers="['hover', 'focus']" no-auto-focus> |
|
55 | 66 | </template> |
56 | 67 |
|
57 | 68 | <script setup lang="ts"> |
58 | | -import { ArrowDownIcon, ArrowUpIcon, XIcon } from '@modrinth/assets' |
59 | | -import { BulletDivider, ButtonStyled, injectNotificationManager } from '@modrinth/ui' |
| 69 | +import { |
| 70 | + ArrowDownIcon, |
| 71 | + ArrowUpIcon, |
| 72 | + LandmarkIcon, |
| 73 | + PayPalColorIcon, |
| 74 | + VenmoColorIcon, |
| 75 | + XIcon, |
| 76 | +} from '@modrinth/assets' |
| 77 | +import { |
| 78 | + BulletDivider, |
| 79 | + ButtonStyled, |
| 80 | + getCurrencyIcon, |
| 81 | + injectNotificationManager, |
| 82 | +} from '@modrinth/ui' |
60 | 83 | import { capitalizeString, formatMoney } from '@modrinth/utils' |
61 | 84 | import dayjs from 'dayjs' |
62 | 85 | import { Tooltip } from 'floating-vue' |
63 | 86 |
|
| 87 | +import { useGeneratedState } from '~/composables/generated' |
| 88 | +import { findRail } from '~/utils/muralpay-rails' |
| 89 | +
|
64 | 90 | type PayoutStatus = 'in-transit' | 'cancelling' | 'cancelled' | 'success' | 'failed' |
65 | 91 | type PayoutMethodType = 'paypal' | 'venmo' | 'tremendous' | 'muralpay' |
66 | 92 | type PayoutSource = 'creator_rewards' | 'affilites' |
@@ -96,25 +122,93 @@ const emit = defineEmits<{ |
96 | 122 | }>() |
97 | 123 |
|
98 | 124 | const { addNotification } = injectNotificationManager() |
| 125 | +const generatedState = useGeneratedState() |
99 | 126 |
|
100 | 127 | const isIncome = computed(() => props.transaction.type === 'payout_available') |
101 | 128 |
|
| 129 | +const methodIconUrl = computed(() => { |
| 130 | + if (props.transaction.type !== 'withdrawal') return null |
| 131 | + const method = props.transaction.method_type || props.transaction.method |
| 132 | + const methodId = props.transaction.method_id |
| 133 | +
|
| 134 | + if (method === 'tremendous' && methodId) { |
| 135 | + const methodInfo = generatedState.value.tremendousIdMap?.[methodId] |
| 136 | + if (methodInfo?.name?.toLowerCase()?.includes('paypal')) return null |
| 137 | + return methodInfo?.image_url ?? null |
| 138 | + } |
| 139 | +
|
| 140 | + return null |
| 141 | +}) |
| 142 | +
|
| 143 | +const methodIconComponent = computed(() => { |
| 144 | + if (props.transaction.type !== 'withdrawal') return null |
| 145 | + const method = props.transaction.method_type || props.transaction.method |
| 146 | + switch (method) { |
| 147 | + case 'paypal': |
| 148 | + return PayPalColorIcon |
| 149 | + case 'tremendous': { |
| 150 | + const methodId = props.transaction.method_id |
| 151 | + if (methodId) { |
| 152 | + const info = generatedState.value.tremendousIdMap?.[methodId] |
| 153 | + if (info?.name?.toLowerCase()?.includes('paypal')) { |
| 154 | + return PayPalColorIcon |
| 155 | + } |
| 156 | + } |
| 157 | + return null |
| 158 | + } |
| 159 | + case 'venmo': |
| 160 | + return VenmoColorIcon |
| 161 | + case 'muralpay': { |
| 162 | + const methodId = props.transaction.method_id |
| 163 | + if (methodId) { |
| 164 | + const rail = findRail(methodId) |
| 165 | + if (rail) { |
| 166 | + if (rail.type === 'crypto') { |
| 167 | + const currencyIcon = getCurrencyIcon(rail.currency) |
| 168 | + if (currencyIcon) return currencyIcon |
| 169 | + } |
| 170 | + if (rail.type === 'fiat') { |
| 171 | + const currencyIcon = getCurrencyIcon(rail.currency) |
| 172 | + if (currencyIcon) return currencyIcon |
| 173 | + return LandmarkIcon |
| 174 | + } |
| 175 | + } |
| 176 | + } |
| 177 | + return null |
| 178 | + } |
| 179 | + default: |
| 180 | + return null |
| 181 | + } |
| 182 | +}) |
| 183 | +
|
102 | 184 | function formatTransactionStatus(status: string): string { |
103 | 185 | if (status === 'in-transit') return 'In Transit' |
104 | 186 | return capitalizeString(status) |
105 | 187 | } |
106 | 188 |
|
107 | | -function formatMethodName(method: string | undefined): string { |
| 189 | +const { formatMessage } = useVIntl() |
| 190 | +
|
| 191 | +function formatMethodName(method: string | undefined, method_id: string | undefined): string { |
108 | 192 | if (!method) return 'Unknown' |
109 | 193 | switch (method) { |
110 | 194 | case 'paypal': |
111 | 195 | return 'PayPal' |
112 | 196 | case 'venmo': |
113 | 197 | return 'Venmo' |
114 | 198 | case 'tremendous': |
| 199 | + if (method_id) { |
| 200 | + const info = generatedState.value.tremendousIdMap?.[method_id] |
| 201 | + if (info) return `${info.name}` |
| 202 | + } |
115 | 203 | return 'Tremendous' |
116 | 204 | case 'muralpay': |
117 | | - return 'Muralpay' |
| 205 | + if (method_id) { |
| 206 | + const rail = findRail(method_id) |
| 207 | + if (rail) { |
| 208 | + return formatMessage(rail.name) |
| 209 | + } |
| 210 | + } |
| 211 | + return 'Mural Pay (Unknown)' |
118 | 212 | default: |
119 | 213 | return capitalizeString(method) |
120 | 214 | } |
|
0 commit comments