mirror of
https://github.com/PretendoNetwork/website.git
synced 2026-08-23 17:17:02 -05:00
feat: error pages
This commit is contained in:
@@ -155,7 +155,5 @@ idk jvs, seems to work on my machine... and yours too now???
|
||||
- [ ] forgot password shows success toast even w no captcha (doesn't actually submit)
|
||||
- [ ] signup birthdate editor
|
||||
|
||||
- [ ] need error page
|
||||
- [ ] need 404 page
|
||||
|
||||
|
||||
- [X] need error page
|
||||
- [X] need 404 page
|
||||
|
||||
BIN
src/assets/images/err_bandwidthlost.png
Normal file
BIN
src/assets/images/err_bandwidthlost.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
@@ -26,11 +26,17 @@ function scoreLocale(cObj: LocaleObject): number {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
const sortedLocales = locales.value.sort((a, b) => {
|
||||
const sA = scoreLocale(a);
|
||||
const sB = scoreLocale(b);
|
||||
|
||||
return sA - sB || (a?.name || '').localeCompare(b?.name || '', locale.value);
|
||||
const sortedLocales = computed(() => {
|
||||
const sorted = [...locales.value];
|
||||
sorted.sort((a, b) => {
|
||||
const sA = scoreLocale(a);
|
||||
const sB = scoreLocale(b);
|
||||
|
||||
return sA - sB || (a?.name || '').localeCompare(b?.name || '', locale.value);
|
||||
});
|
||||
|
||||
return sorted;
|
||||
});
|
||||
|
||||
const me = useMeStore();
|
||||
|
||||
79
src/error.vue
Normal file
79
src/error.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import DefaultLayout from './layouts/default.vue';
|
||||
const { error } = defineProps<{ error: any }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DefaultLayout>
|
||||
<div
|
||||
v-if="error?.statusCode === 404"
|
||||
class="wrapper"
|
||||
>
|
||||
<h1 class="status">
|
||||
{{ error?.statusCode }}
|
||||
</h1>
|
||||
<p class="description">
|
||||
{{ $t('notfound.description') }}
|
||||
</p>
|
||||
<img
|
||||
src="~/assets/images/err_bandwidthlost.png"
|
||||
class="bandwidth notfound"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="wrapper"
|
||||
>
|
||||
<h1 class="status">
|
||||
{{ error?.statusCode }}
|
||||
</h1>
|
||||
|
||||
<p class="description">
|
||||
{{ $t('errorPage.500.title') }} {{ $t('errorPage.500.description') }}
|
||||
</p>
|
||||
|
||||
<img
|
||||
src="/assets/images/shockedbandwidth.svg"
|
||||
class="bandwidth"
|
||||
>
|
||||
</div>
|
||||
</DefaultLayout>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.status {
|
||||
font-size: 8rem;
|
||||
text-align: center;
|
||||
margin: 6rem 0 0;
|
||||
color: var(--text-shade-3);
|
||||
}
|
||||
.description {
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
color: var(--text-shade-1);
|
||||
margin: 0;
|
||||
}
|
||||
.bandwidth {
|
||||
display: block;
|
||||
margin: 4rem auto -120px;
|
||||
|
||||
height: 24rem;
|
||||
}
|
||||
|
||||
.bandwidth.notfound {
|
||||
height: 32rem;
|
||||
margin-bottom: 4em;
|
||||
}
|
||||
|
||||
@media screen and (min-height: 1100px) {
|
||||
.status {
|
||||
margin-top: 16rem;
|
||||
}
|
||||
.bandwidth {
|
||||
margin: 16rem auto -120px;
|
||||
}
|
||||
.bandwidth.bandwidth.notfound {
|
||||
margin: 6rem auto 16rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -341,7 +341,13 @@
|
||||
"confirm": "Confirm",
|
||||
"close": "Close"
|
||||
},
|
||||
"errorPage": {
|
||||
"500": {
|
||||
"title": "Server error!",
|
||||
"description": "Please try again later."
|
||||
}
|
||||
},
|
||||
"notfound": {
|
||||
"description": "Oops! We could not find this page."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,15 +51,23 @@ watchImmediate(discordLinkQuery, (val) => {
|
||||
useRouter().replace({ query: {} });
|
||||
});
|
||||
|
||||
const { data: profile, refresh } = await useApiFetch('/api/auth/me');
|
||||
const { data: connections, refresh: refreshConnections } = await useApiFetch('/api/auth/me-connections');
|
||||
|
||||
const selectedServerEnv = ref(profile.value?.serverAccessLevel);
|
||||
const dialogContainer = ref(null);
|
||||
const deleteModalOpen = ref(false);
|
||||
const editModalOpen = ref(false);
|
||||
const selectedServerEnv = ref<string | undefined>('');
|
||||
const { data: profile, refresh } = await useApiFetch('/api/auth/me', {
|
||||
onResponse: (opt) => {
|
||||
selectedServerEnv.value = opt.response._data?.serverAccessLevel;
|
||||
}
|
||||
});
|
||||
const { data: connections, refresh: refreshConnections } = await useApiFetch(
|
||||
'/api/auth/me-connections'
|
||||
);
|
||||
|
||||
const { execute: executeUpdateServerEnvironment, isLoading: isLoadingUpdateServerEnv } = useAsync({
|
||||
const {
|
||||
execute: executeUpdateServerEnvironment,
|
||||
isLoading: isLoadingUpdateServerEnv
|
||||
} = useAsync({
|
||||
async handler(env: ApiAccountUpdateRequest['environment']) {
|
||||
await apiFetch('/api/account/update', {
|
||||
method: 'PATCH',
|
||||
@@ -131,7 +139,6 @@ const { execute: executeUnlinkDiscord, isLoading: isLoadingUnlink } = useAsync({
|
||||
useHead({
|
||||
title: `Account`
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -202,15 +209,17 @@ useHead({
|
||||
<AlertDialog.Portal :to="dialogContainer ?? undefined">
|
||||
<AlertDialog.Overlay />
|
||||
<AlertDialog.Content class="modal">
|
||||
<AlertDialog.Title>{{ $t("account.settings.delete.modalTitle") }}?</AlertDialog.Title>
|
||||
<AlertDialog.Title>
|
||||
{{
|
||||
$t("account.settings.delete.modalTitle")
|
||||
}}?
|
||||
</AlertDialog.Title>
|
||||
<AlertDialog.Description class="modal-caption">
|
||||
<p
|
||||
style="white-space: pre-line;"
|
||||
>
|
||||
{{ $t('account.settings.delete.modalDescription') }}
|
||||
<p style="white-space: pre-line">
|
||||
{{ $t("account.settings.delete.modalDescription") }}
|
||||
</p>
|
||||
<p class="noundo">
|
||||
{{ $t('account.settings.delete.modalCaution') }}
|
||||
{{ $t("account.settings.delete.modalCaution") }}
|
||||
</p>
|
||||
</AlertDialog.Description>
|
||||
<div class="modal-button-wrapper">
|
||||
@@ -225,7 +234,9 @@ useHead({
|
||||
@click="executeDeleteAccount"
|
||||
>
|
||||
<Loader v-if="isLoadingDelete" />
|
||||
<span v-else>{{ $t("account.settings.delete.modalConfirm") }}</span>
|
||||
<span v-else>{{
|
||||
$t("account.settings.delete.modalConfirm")
|
||||
}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</AlertDialog.Content>
|
||||
@@ -246,9 +257,7 @@ useHead({
|
||||
{{ $t("account.settings.settingCards.profile") }}
|
||||
</h2>
|
||||
|
||||
<AlertDialog.Trigger
|
||||
class="edit"
|
||||
>
|
||||
<AlertDialog.Trigger class="edit">
|
||||
<Icon
|
||||
name="ph:pencil"
|
||||
size="26"
|
||||
@@ -257,10 +266,14 @@ useHead({
|
||||
<AlertDialog.Portal :to="dialogContainer ?? undefined">
|
||||
<AlertDialog.Overlay />
|
||||
<AlertDialog.Content class="modal">
|
||||
<AlertDialog.Title>{{ $t("account.settings.unavailable") }}.</AlertDialog.Title>
|
||||
<AlertDialog.Title>
|
||||
{{ $t("account.settings.unavailable") }}.
|
||||
</AlertDialog.Title>
|
||||
<AlertDialog.Description class="modal-caption">
|
||||
<p>
|
||||
{{ $t('account.settings.settingCards.no_edit_from_dashboard') }}
|
||||
{{
|
||||
$t("account.settings.settingCards.no_edit_from_dashboard")
|
||||
}}
|
||||
</p>
|
||||
</AlertDialog.Description>
|
||||
<div class="modal-button-wrapper">
|
||||
@@ -318,7 +331,11 @@ useHead({
|
||||
<h2 class="header">
|
||||
{{ $t("account.settings.settingCards.serverEnv") }}
|
||||
</h2>
|
||||
<fieldset :disabled="profile.serverAccessLevel === 'prod' && profile.accessLevel < 1">
|
||||
<fieldset
|
||||
:disabled="
|
||||
profile.serverAccessLevel === 'prod' && profile.accessLevel < 1
|
||||
"
|
||||
>
|
||||
<form
|
||||
id="server"
|
||||
class="server-selection"
|
||||
@@ -337,7 +354,10 @@ useHead({
|
||||
<h2>{{ $t("account.settings.settingCards.production") }}</h2>
|
||||
</label>
|
||||
<input
|
||||
v-if="profile.serverAccessLevel !== 'prod' || profile.accessLevel > 0"
|
||||
v-if="
|
||||
profile.serverAccessLevel !== 'prod' ||
|
||||
profile.accessLevel > 0
|
||||
"
|
||||
id="test"
|
||||
v-model="selectedServerEnv"
|
||||
type="radio"
|
||||
@@ -345,7 +365,10 @@ useHead({
|
||||
>
|
||||
|
||||
<label
|
||||
v-if="profile.serverAccessLevel !== 'prod' || profile.accessLevel > 0"
|
||||
v-if="
|
||||
profile.serverAccessLevel !== 'prod' ||
|
||||
profile.accessLevel > 0
|
||||
"
|
||||
for="test"
|
||||
>
|
||||
<Icon
|
||||
@@ -382,7 +405,9 @@ useHead({
|
||||
"
|
||||
id="save-server-selection"
|
||||
class="button secondary"
|
||||
@click.prevent="() => executeUpdateServerEnvironment(selectedServerEnv)"
|
||||
@click.prevent="
|
||||
() => executeUpdateServerEnvironment(selectedServerEnv)
|
||||
"
|
||||
>
|
||||
<Loader v-if="isLoadingUpdateServerEnv" />
|
||||
<span v-else>Save</span>
|
||||
@@ -406,9 +431,7 @@ useHead({
|
||||
<h2 class="header">
|
||||
{{ $t("account.account") }}
|
||||
</h2>
|
||||
<AlertDialog.Trigger
|
||||
class="edit"
|
||||
>
|
||||
<AlertDialog.Trigger class="edit">
|
||||
<Icon
|
||||
name="ph:pencil"
|
||||
size="26"
|
||||
@@ -459,11 +482,9 @@ useHead({
|
||||
>
|
||||
{{ $t("account.settings.settingCards.connectedToDiscord") }}
|
||||
<img
|
||||
:style="{ height: '25px', width: '25px', borderRadius: '100px'}"
|
||||
:style="{ height: '25px', width: '25px', borderRadius: '100px' }"
|
||||
:src="connections?.discord?.avatarUrl ?? '#'"
|
||||
>@{{
|
||||
connections?.discord?.username
|
||||
}}.
|
||||
>@{{ connections?.discord?.username }}.
|
||||
</p>
|
||||
|
||||
<button
|
||||
@@ -473,16 +494,20 @@ useHead({
|
||||
@click="executeUnlinkDiscord"
|
||||
>
|
||||
<Loader v-if="isLoadingUnlink" />
|
||||
<span v-else>{{ $t("account.settings.settingCards.removeDiscord") }}</span>
|
||||
<span v-else>{{
|
||||
$t("account.settings.settingCards.removeDiscord")
|
||||
}}</span>
|
||||
</button>
|
||||
<p v-else>
|
||||
{{ $t("account.settings.settingCards.noDiscordLinked") }}
|
||||
<NuxtLink
|
||||
:style="{cursor: 'pointer'}"
|
||||
:style="{ cursor: 'pointer' }"
|
||||
@click="executeLinkDiscord"
|
||||
>
|
||||
<Loader v-if="isLoadingLink" />
|
||||
<span v-else>{{ $t("account.settings.settingCards.linkDiscord") }}</span>
|
||||
<span v-else>{{
|
||||
$t("account.settings.settingCards.linkDiscord")
|
||||
}}</span>
|
||||
</NuxtLink>
|
||||
</p>
|
||||
</div>
|
||||
@@ -492,7 +517,7 @@ useHead({
|
||||
{{ $t("account.settings.settingCards.newsletter") }}
|
||||
</h2>
|
||||
<p>{{ $t("account.settings.settingCards.no_newsletter_notice") }}</p>
|
||||
<!--
|
||||
<!--
|
||||
<form id="other">
|
||||
<input type="checkbox" id="marketing" name="marketing" {{#if account.flags.marketing}}checked{{/if}}>
|
||||
<label for="marketing">{{ locale.account.settings.settingCards.newsletterPrompt }}</label>
|
||||
@@ -503,7 +528,10 @@ useHead({
|
||||
</AlertDialog.Root>
|
||||
<div
|
||||
id="delete-account"
|
||||
:class="{ 'modal-wrapper': true, hidden: !(deleteModalOpen || editModalOpen) }"
|
||||
:class="{
|
||||
'modal-wrapper': true,
|
||||
hidden: !(deleteModalOpen || editModalOpen),
|
||||
}"
|
||||
>
|
||||
<div ref="dialogContainer" />
|
||||
</div>
|
||||
@@ -651,7 +679,7 @@ useHead({
|
||||
|
||||
.modal p.noundo {
|
||||
font-weight: bold;
|
||||
color: var(--text-shade-3)
|
||||
color: var(--text-shade-3);
|
||||
}
|
||||
|
||||
/* Settings */
|
||||
@@ -810,7 +838,7 @@ fieldset {
|
||||
width: 100vw;
|
||||
animation: banner-notice 5s;
|
||||
z-index: 100;
|
||||
color: var(--text-shade-3)
|
||||
color: var(--text-shade-3);
|
||||
}
|
||||
.banner-notice div {
|
||||
padding: 4px 36px;
|
||||
@@ -822,7 +850,6 @@ fieldset {
|
||||
}
|
||||
.banner-notice.error div {
|
||||
background: var(--red-shade-1);
|
||||
|
||||
}
|
||||
|
||||
footer {
|
||||
|
||||
Reference in New Issue
Block a user