Add TailwindCSS (#1252)

* Setup TailwindCSS

* Fully setup configuration

* Refactor some tailwind variables
This commit is contained in:
Evan Song
2024-07-06 20:57:32 -07:00
committed by GitHub
parent 0f2ddb452c
commit abec2e48d4
176 changed files with 7905 additions and 7433 deletions

View File

@@ -75,34 +75,34 @@
</div>
</template>
<script setup>
import { TransferIcon, HistoryIcon, PayPalIcon, SaveIcon, XIcon } from '@modrinth/assets'
import { TransferIcon, HistoryIcon, PayPalIcon, SaveIcon, XIcon } from "@modrinth/assets";
const auth = await useAuth()
const minWithdraw = ref(0.01)
const auth = await useAuth();
const minWithdraw = ref(0.01);
async function updateVenmo() {
startLoading()
startLoading();
try {
const data = {
venmo_handle: auth.value.user.payout_data.venmo_handle ?? null,
}
};
await useBaseFetch(`user/${auth.value.user.id}`, {
method: 'PATCH',
method: "PATCH",
body: data,
apiVersion: 3,
})
await useAuth(auth.value.token)
});
await useAuth(auth.value.token);
} catch (err) {
const data = useNuxtApp()
const data = useNuxtApp();
data.$notify({
group: 'main',
title: 'An error occurred',
group: "main",
title: "An error occurred",
text: err.data.description,
type: 'error',
})
type: "error",
});
}
stopLoading()
stopLoading();
}
</script>
<style lang="scss" scoped>

View File

@@ -25,8 +25,8 @@
</div>
<p>
{{
selectedYear !== 'all'
? selectedMethod !== 'all'
selectedYear !== "all"
? selectedMethod !== "all"
? formatMessage(messages.transfersTotalYearMethod, {
amount: $formatMoney(totalAmount),
year: selectedYear,
@@ -36,12 +36,12 @@
amount: $formatMoney(totalAmount),
year: selectedYear,
})
: selectedMethod !== 'all'
? formatMessage(messages.transfersTotalMethod, {
amount: $formatMoney(totalAmount),
method: selectedMethod,
})
: formatMessage(messages.transfersTotal, { amount: $formatMoney(totalAmount) })
: selectedMethod !== "all"
? formatMessage(messages.transfersTotalMethod, {
amount: $formatMoney(totalAmount),
method: selectedMethod,
})
: formatMessage(messages.transfersTotal, { amount: $formatMoney(totalAmount) })
}}
</p>
<div
@@ -58,7 +58,7 @@
<div class="payout-info">
<div>
<strong>
{{ $dayjs(payout.created).format('MMMM D, YYYY [at] h:mm A') }}
{{ $dayjs(payout.created).format("MMMM D, YYYY [at] h:mm A") }}
</strong>
</div>
<div>
@@ -94,96 +94,96 @@
</div>
</template>
<script setup>
import { DropdownSelect } from '@modrinth/ui'
import { XIcon, PayPalIcon, UnknownIcon } from '@modrinth/assets'
import { capitalizeString } from '@modrinth/utils'
import { Badge, Breadcrumbs } from '@modrinth/ui'
import dayjs from 'dayjs'
import TremendousIcon from '~/assets/images/external/tremendous.svg?component'
import VenmoIcon from '~/assets/images/external/venmo-small.svg?component'
import { DropdownSelect } from "@modrinth/ui";
import { XIcon, PayPalIcon, UnknownIcon } from "@modrinth/assets";
import { capitalizeString } from "@modrinth/utils";
import { Badge, Breadcrumbs } from "@modrinth/ui";
import dayjs from "dayjs";
import TremendousIcon from "~/assets/images/external/tremendous.svg?component";
import VenmoIcon from "~/assets/images/external/venmo-small.svg?component";
const vintl = useVIntl()
const { formatMessage } = vintl
const vintl = useVIntl();
const { formatMessage } = vintl;
useHead({
title: 'Transfer history - Modrinth',
})
title: "Transfer history - Modrinth",
});
const data = await useNuxtApp()
const auth = await useAuth()
const data = await useNuxtApp();
const auth = await useAuth();
const { data: payouts, refresh } = await useAsyncData(`payout`, () =>
useBaseFetch(`payout`, {
apiVersion: 3,
})
)
}),
);
const sortedPayouts = computed(() =>
payouts.value.sort((a, b) => dayjs(b.created) - dayjs(a.created))
)
payouts.value.sort((a, b) => dayjs(b.created) - dayjs(a.created)),
);
const years = computed(() => {
const values = sortedPayouts.value.map((x) => dayjs(x.created).year())
return ['all', ...new Set(values)]
})
const values = sortedPayouts.value.map((x) => dayjs(x.created).year());
return ["all", ...new Set(values)];
});
const selectedYear = ref('all')
const selectedYear = ref("all");
const methods = computed(() => {
const values = sortedPayouts.value.filter((x) => x.method).map((x) => x.method)
return ['all', ...new Set(values)]
})
const values = sortedPayouts.value.filter((x) => x.method).map((x) => x.method);
return ["all", ...new Set(values)];
});
const selectedMethod = ref('all')
const selectedMethod = ref("all");
const filteredPayouts = computed(() =>
sortedPayouts.value
.filter((x) => selectedYear.value === 'all' || dayjs(x.created).year() === selectedYear.value)
.filter((x) => selectedMethod.value === 'all' || x.method === selectedMethod.value)
)
.filter((x) => selectedYear.value === "all" || dayjs(x.created).year() === selectedYear.value)
.filter((x) => selectedMethod.value === "all" || x.method === selectedMethod.value),
);
const totalAmount = computed(() =>
filteredPayouts.value.reduce((sum, payout) => sum + payout.amount, 0)
)
filteredPayouts.value.reduce((sum, payout) => sum + payout.amount, 0),
);
async function cancelPayout(id) {
startLoading()
startLoading();
try {
await useBaseFetch(`payout/${id}`, {
method: 'DELETE',
method: "DELETE",
apiVersion: 3,
})
await refresh()
await useAuth(auth.value.token)
});
await refresh();
await useAuth(auth.value.token);
} catch (err) {
data.$notify({
group: 'main',
title: 'An error occurred',
group: "main",
title: "An error occurred",
text: err.data.description,
type: 'error',
})
type: "error",
});
}
stopLoading()
stopLoading();
}
const messages = defineMessages({
transfersTotal: {
id: 'revenue.transfers.total',
defaultMessage: 'You have withdrawn {amount} in total.',
id: "revenue.transfers.total",
defaultMessage: "You have withdrawn {amount} in total.",
},
transfersTotalYear: {
id: 'revenue.transfers.total.year',
defaultMessage: 'You have withdrawn {amount} in {year}.',
id: "revenue.transfers.total.year",
defaultMessage: "You have withdrawn {amount} in {year}.",
},
transfersTotalMethod: {
id: 'revenue.transfers.total.method',
defaultMessage: 'You have withdrawn {amount} through {method}.',
id: "revenue.transfers.total.method",
defaultMessage: "You have withdrawn {amount} through {method}.",
},
transfersTotalYearMethod: {
id: 'revenue.transfers.total.year_method',
defaultMessage: 'You have withdrawn {amount} in {year} through {method}.',
id: "revenue.transfers.total.year_method",
defaultMessage: "You have withdrawn {amount} in {year} through {method}.",
},
})
});
</script>
<style lang="scss" scoped>
.payout {

View File

@@ -39,7 +39,7 @@
<div class="withdraw-options">
<button
v-for="method in payoutMethods.filter((x) =>
x.name.toLowerCase().includes(search.toLowerCase())
x.name.toLowerCase().includes(search.toLowerCase()),
)"
:key="method.id"
class="withdraw-option button-base"
@@ -53,8 +53,8 @@
{{
getRangeOfMethod(method)
.map($formatMoney)
.map((i) => i.replace('.00', ''))
.join('')
.map((i) => i.replace(".00", ""))
.join("")
}}
</span>
</div>
@@ -183,7 +183,7 @@
</template>
<script setup>
import { Multiselect } from 'vue-multiselect'
import { Multiselect } from "vue-multiselect";
import {
PayPalIcon,
SearchIcon,
@@ -191,182 +191,182 @@ import {
RadioButtonChecked,
XIcon,
TransferIcon,
} from '@modrinth/assets'
import { Chips, Checkbox, Breadcrumbs } from '@modrinth/ui'
import { all } from 'iso-3166-1'
import VenmoIcon from '~/assets/images/external/venmo.svg?component'
} from "@modrinth/assets";
import { Chips, Checkbox, Breadcrumbs } from "@modrinth/ui";
import { all } from "iso-3166-1";
import VenmoIcon from "~/assets/images/external/venmo.svg?component";
const auth = await useAuth()
const data = useNuxtApp()
const auth = await useAuth();
const data = useNuxtApp();
const countries = computed(() =>
all().map((x) => ({
id: x.alpha2,
name: x.alpha2 === 'TW' ? 'Taiwan' : x.country,
}))
)
const search = ref('')
name: x.alpha2 === "TW" ? "Taiwan" : x.country,
})),
);
const search = ref("");
const amount = ref('')
const amount = ref("");
const country = ref(
countries.value.find((x) => x.id === (auth.value.user.payout_data.paypal_region ?? 'US'))
)
countries.value.find((x) => x.id === (auth.value.user.payout_data.paypal_region ?? "US")),
);
const { data: payoutMethods, refresh: refreshPayoutMethods } = await useAsyncData(
`payout/methods?country=${country.value.id}`,
() => useBaseFetch(`payout/methods?country=${country.value.id}`, { apiVersion: 3 })
)
() => useBaseFetch(`payout/methods?country=${country.value.id}`, { apiVersion: 3 }),
);
const selectedMethodId = ref(payoutMethods.value[0].id)
const selectedMethodId = ref(payoutMethods.value[0].id);
const selectedMethod = computed(() =>
payoutMethods.value.find((x) => x.id === selectedMethodId.value)
)
payoutMethods.value.find((x) => x.id === selectedMethodId.value),
);
const parsedAmount = computed(() => {
const regex = /^\$?(\d*(\.\d{2})?)$/gm
const matches = regex.exec(amount.value)
return matches && matches[1] ? parseFloat(matches[1]) : 0.0
})
const regex = /^\$?(\d*(\.\d{2})?)$/gm;
const matches = regex.exec(amount.value);
return matches && matches[1] ? parseFloat(matches[1]) : 0.0;
});
const fees = computed(() => {
return Math.min(
Math.max(
selectedMethod.value.fee.min,
selectedMethod.value.fee.percentage * parsedAmount.value
selectedMethod.value.fee.percentage * parsedAmount.value,
),
selectedMethod.value.fee.max ?? Number.MAX_VALUE
)
})
selectedMethod.value.fee.max ?? Number.MAX_VALUE,
);
});
const getIntervalRange = (intervalType) => {
if (!intervalType) {
return []
return [];
}
const { min, max, values } = intervalType
const { min, max, values } = intervalType;
if (values) {
const first = values[0]
const last = values.slice(-1)[0]
return first === last ? [first] : [first, last]
const first = values[0];
const last = values.slice(-1)[0];
return first === last ? [first] : [first, last];
}
return min === max ? [min] : [min, max]
}
return min === max ? [min] : [min, max];
};
const getRangeOfMethod = (method) => {
return getIntervalRange(method.interval?.fixed || method.interval?.standard)
}
return getIntervalRange(method.interval?.fixed || method.interval?.standard);
};
const maxWithdrawAmount = computed(() => {
const interval = selectedMethod.value.interval
return interval?.standard ? interval.standard.max : interval?.fixed?.values.slice(-1)[0] ?? 0
})
const interval = selectedMethod.value.interval;
return interval?.standard ? interval.standard.max : interval?.fixed?.values.slice(-1)[0] ?? 0;
});
const minWithdrawAmount = computed(() => {
const interval = selectedMethod.value.interval
return interval?.standard ? interval.standard.min : interval?.fixed?.values?.[0] ?? fees.value
})
const interval = selectedMethod.value.interval;
return interval?.standard ? interval.standard.min : interval?.fixed?.values?.[0] ?? fees.value;
});
const withdrawAccount = computed(() => {
if (selectedMethod.value.type === 'paypal') {
return auth.value.user.payout_data.paypal_address
} else if (selectedMethod.value.type === 'venmo') {
return auth.value.user.payout_data.venmo_handle
if (selectedMethod.value.type === "paypal") {
return auth.value.user.payout_data.paypal_address;
} else if (selectedMethod.value.type === "venmo") {
return auth.value.user.payout_data.venmo_handle;
} else {
return auth.value.user.email
return auth.value.user.email;
}
})
});
const knownErrors = computed(() => {
const errors = []
if (selectedMethod.value.type === 'paypal' && !auth.value.user.payout_data.paypal_address) {
errors.push('Please link your PayPal account in the dashboard to proceed.')
const errors = [];
if (selectedMethod.value.type === "paypal" && !auth.value.user.payout_data.paypal_address) {
errors.push("Please link your PayPal account in the dashboard to proceed.");
}
if (selectedMethod.value.type === 'venmo' && !auth.value.user.payout_data.venmo_handle) {
errors.push('Please set your Venmo handle in the dashboard to proceed.')
if (selectedMethod.value.type === "venmo" && !auth.value.user.payout_data.venmo_handle) {
errors.push("Please set your Venmo handle in the dashboard to proceed.");
}
if (selectedMethod.value.type === 'tremendous') {
if (selectedMethod.value.type === "tremendous") {
if (!auth.value.user.email) {
errors.push('Please set your email address in your account settings to proceed.')
errors.push("Please set your email address in your account settings to proceed.");
}
if (!auth.value.user.email_verified) {
errors.push('Please verify your email address to proceed.')
errors.push("Please verify your email address to proceed.");
}
}
if (!parsedAmount.value && amount.value.length > 0) {
errors.push(`${amount.value} is not a valid amount`)
errors.push(`${amount.value} is not a valid amount`);
} else if (
parsedAmount.value > auth.value.user.payout_data.balance ||
parsedAmount.value > maxWithdrawAmount.value
) {
const maxAmount = Math.min(auth.value.user.payout_data.balance, maxWithdrawAmount.value)
errors.push(`The amount must be no more than ${data.$formatMoney(maxAmount)}`)
const maxAmount = Math.min(auth.value.user.payout_data.balance, maxWithdrawAmount.value);
errors.push(`The amount must be no more than ${data.$formatMoney(maxAmount)}`);
} else if (parsedAmount.value <= fees.value || parsedAmount.value < minWithdrawAmount.value) {
const minAmount = Math.max(fees.value + 0.01, minWithdrawAmount.value)
errors.push(`The amount must be at least ${data.$formatMoney(minAmount)}`)
const minAmount = Math.max(fees.value + 0.01, minWithdrawAmount.value);
errors.push(`The amount must be at least ${data.$formatMoney(minAmount)}`);
}
return errors
})
return errors;
});
const agreedTransfer = ref(false)
const agreedFees = ref(false)
const agreedTerms = ref(false)
const agreedTransfer = ref(false);
const agreedFees = ref(false);
const agreedTerms = ref(false);
watch(country, async () => {
await refreshPayoutMethods()
await refreshPayoutMethods();
if (payoutMethods.value && payoutMethods.value[0]) {
selectedMethodId.value = payoutMethods.value[0].id
selectedMethodId.value = payoutMethods.value[0].id;
}
})
});
watch(selectedMethod, () => {
if (selectedMethod.value.interval?.fixed) {
amount.value = selectedMethod.value.interval.fixed.values[0]
amount.value = selectedMethod.value.interval.fixed.values[0];
}
if (maxWithdrawAmount.value === minWithdrawAmount.value) {
amount.value = maxWithdrawAmount.value
amount.value = maxWithdrawAmount.value;
}
agreedTransfer.value = false
agreedFees.value = false
agreedTerms.value = false
})
agreedTransfer.value = false;
agreedFees.value = false;
agreedTerms.value = false;
});
async function withdraw() {
startLoading()
startLoading();
try {
const auth = await useAuth()
const auth = await useAuth();
await useBaseFetch(`payout`, {
method: 'POST',
method: "POST",
body: {
amount: parsedAmount.value,
method: selectedMethod.value.type,
method_id: selectedMethod.value.id,
},
apiVersion: 3,
})
await useAuth(auth.value.token)
await navigateTo('/dashboard/revenue')
});
await useAuth(auth.value.token);
await navigateTo("/dashboard/revenue");
data.$notify({
group: 'main',
title: 'Withdrawal complete',
group: "main",
title: "Withdrawal complete",
text:
selectedMethod.value.type === 'tremendous'
? 'An email has been sent to your account with further instructions on how to redeem your payout!'
selectedMethod.value.type === "tremendous"
? "An email has been sent to your account with further instructions on how to redeem your payout!"
: `Payment has been sent to your ${data.$formatWallet(
selectedMethod.value.type
selectedMethod.value.type,
)} account!`,
type: 'success',
})
type: "success",
});
} catch (err) {
data.$notify({
group: 'main',
title: 'An error occurred',
group: "main",
title: "An error occurred",
text: err.data.description,
type: 'error',
})
type: "error",
});
}
stopLoading()
stopLoading();
}
</script>