mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-06 08:28:20 +01:00
feat: ✨ Add error page when an account is not found
This commit is contained in:
parent
46193938fe
commit
3db36ae618
65
components/errors/ErrorBoundary.vue
Normal file
65
components/errors/ErrorBoundary.vue
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
<template>
|
||||||
|
<slot name="error" v-if="error" v-bind="{ error }">
|
||||||
|
<div id="error" class="grid min-h-screen place-items-center px-6 py-24 sm:py-32 lg:px-8">
|
||||||
|
<div class="text-center prose prose-invert">
|
||||||
|
<p class="text-base font-semibold text-pink-400">404</p>
|
||||||
|
<h1 class="mt-4 text-3xl font-bold tracking-tight text-gray-100 sm:text-5xl">{{ error.title }}
|
||||||
|
</h1>
|
||||||
|
<p class="mt-6 text-base leading-7 text-gray-400" v-html="error.message"></p>
|
||||||
|
<div class="mt-10 grid grid-cols-2 gap-x-6 mx-auto max-w-md">
|
||||||
|
<ButtonsPrimary class="w-full" @click="back">Go back</ButtonsPrimary>
|
||||||
|
<a href="https://github.com/lysand-org/lysand-fe/issues" target="_blank">
|
||||||
|
<ButtonsSecondary class="w-full">Report an issue</ButtonsSecondary>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
<slot v-else />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const error = ref<{
|
||||||
|
title: string;
|
||||||
|
message: string;
|
||||||
|
code: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
useListen("error", (err) => {
|
||||||
|
error.value = err;
|
||||||
|
});
|
||||||
|
|
||||||
|
const back = () => {
|
||||||
|
useRouter().back();
|
||||||
|
};
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: computed(() => error.value?.title || "Error"),
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#error code:not(pre code)::after,
|
||||||
|
#error code:not(pre code)::before {
|
||||||
|
content: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
#error code:not(pre code) {
|
||||||
|
border-radius: .25rem;
|
||||||
|
padding: .25rem .5rem;
|
||||||
|
word-wrap: break-word;
|
||||||
|
background: transparent;
|
||||||
|
background-color: #ffffff0d;
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
margin-top: 1rem;
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), 0 0 #0000;
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||||
|
--tw-ring-color: hsla(0, 0%, 100%, .1)
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -31,6 +31,11 @@ type ApplicationEvents = {
|
||||||
"notification:new": NotificationEvent;
|
"notification:new": NotificationEvent;
|
||||||
"attachment:view": Attachment;
|
"attachment:view": Attachment;
|
||||||
"identity:change": Identity;
|
"identity:change": Identity;
|
||||||
|
error: {
|
||||||
|
code: string;
|
||||||
|
title: string;
|
||||||
|
message: string;
|
||||||
|
} | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const emitter = mitt<ApplicationEvents>();
|
const emitter = mitt<ApplicationEvents>();
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
<rect width="100%" height="100%" stroke-width="0" fill="url(#983e3e4c-de6d-4c3f-8d64-b9761d1534cc)"></rect>
|
<rect width="100%" height="100%" stroke-width="0" fill="url(#983e3e4c-de6d-4c3f-8d64-b9761d1534cc)"></rect>
|
||||||
</svg>
|
</svg>
|
||||||
<LazySidebarsNavigation />
|
<LazySidebarsNavigation />
|
||||||
|
|
||||||
<div class="relative md:pl-20 min-h-dvh flex flex-row overflow-hidden justify-center xl:justify-between">
|
<div class="relative md:pl-20 min-h-dvh flex flex-row overflow-hidden justify-center xl:justify-between">
|
||||||
<OverlayScrollbarsComponent :defer="true" class="w-full max-h-dvh overflow-y-auto" :element="'main'">
|
<OverlayScrollbarsComponent :defer="true" class="w-full max-h-dvh overflow-y-auto" :element="'main'">
|
||||||
<slot />
|
<slot />
|
||||||
|
|
@ -64,12 +65,12 @@ const client = useClient();
|
||||||
const providers = useSSOConfig();
|
const providers = useSSOConfig();
|
||||||
|
|
||||||
watchEffect(async () => {
|
watchEffect(async () => {
|
||||||
if (n.value) {
|
if (n?.value) {
|
||||||
// Wait 50ms
|
// Wait 50ms
|
||||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||||
useEvent("composer:open");
|
useEvent("composer:open");
|
||||||
}
|
}
|
||||||
if (o_i_d_c.value) {
|
if (o_i_d_c?.value) {
|
||||||
useEvent("notification:new", {
|
useEvent("notification:new", {
|
||||||
type: "progress",
|
type: "progress",
|
||||||
title: "Linking your account",
|
title: "Linking your account",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mx-auto max-w-2xl w-full">
|
<ErrorsErrorBoundary>
|
||||||
<LazyTimelinesTimelineScroller>
|
<div class="mx-auto max-w-2xl w-full">
|
||||||
<LazySocialElementsUsersAccount :account="account ?? undefined" />
|
<LazyTimelinesTimelineScroller>
|
||||||
<LazyTimelinesAccount :id="accountId" :key="accountId" />
|
<LazySocialElementsUsersAccount :account="account ?? undefined" />
|
||||||
</LazyTimelinesTimelineScroller>
|
<LazyTimelinesAccount :id="accountId" :key="accountId" />
|
||||||
</div>
|
</LazyTimelinesTimelineScroller>
|
||||||
|
</div>
|
||||||
|
</ErrorsErrorBoundary>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
@ -19,6 +21,17 @@ const client = useClient();
|
||||||
const username = (route.params.username as string).replace("@", "");
|
const username = (route.params.username as string).replace("@", "");
|
||||||
|
|
||||||
const accounts = useAccountSearch(client, username);
|
const accounts = useAccountSearch(client, username);
|
||||||
|
watch(accounts, (newValue) => {
|
||||||
|
if (Array.isArray(newValue)) {
|
||||||
|
if (!newValue.find((account) => account.acct === username)) {
|
||||||
|
useEvent("error", {
|
||||||
|
title: "Account not found",
|
||||||
|
message: `The account <code>@${username}</code> does not exist.`,
|
||||||
|
code: "ERR_ACCOUNT_NOT_FOUND",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
const account = computed<Account | null>(
|
const account = computed<Account | null>(
|
||||||
() => accounts.value?.find((account) => account.acct === username) ?? null,
|
() => accounts.value?.find((account) => account.acct === username) ?? null,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue