GuardRateLeaderboard / src /error.html
Anton Malykhin
feat: integrate bucket-backed leaderboard data
c6afb12
Raw
History Blame Contribute Delete
6.41 kB
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="light dark" />
<title>%sveltekit.error.message%</title>
<style>
:root {
color-scheme: light dark;
--bg: #ffffff;
--text: #09090b;
--muted: #71717a;
--surface: #f4f4f5;
--surface-border: #e4e4e7;
--button: #18181b;
--button-text: #fafafa;
--button-alt: transparent;
--button-alt-text: #18181b;
--button-alt-border: #d4d4d8;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #09090b;
--text: #fafafa;
--muted: #a1a1aa;
--surface: #18181b;
--surface-border: #27272a;
--button: #fafafa;
--button-text: #18181b;
--button-alt: transparent;
--button-alt-text: #fafafa;
--button-alt-border: #3f3f46;
}
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100svh;
display: grid;
place-items: center;
padding: 1.25rem;
background: var(--bg);
color: var(--text);
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Helvetica,
Arial,
sans-serif;
}
.error {
width: min(100%, 26rem);
text-align: center;
}
.icon {
width: 3rem;
height: 3rem;
margin: 0 auto 1rem;
border-radius: 0.9rem;
display: grid;
place-items: center;
background: var(--surface);
border: 1px solid var(--surface-border);
}
.icon svg {
width: 1.35rem;
height: 1.35rem;
stroke: var(--text);
}
h1 {
margin: 0;
font-size: 1.85rem;
line-height: 1.2;
font-weight: 600;
}
.text {
margin: 0.8rem 0 0;
color: var(--muted);
font-size: 1rem;
line-height: 1.55;
}
.meta {
margin: 1rem auto 0;
width: fit-content;
max-width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.45rem;
}
code {
font-family:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
font-size: 0.78rem;
padding: 0.3rem 0.5rem;
border-radius: 0.45rem;
background: var(--surface);
border: 1px solid var(--surface-border);
color: var(--muted);
word-break: break-word;
}
.actions {
margin-top: 1.35rem;
display: flex;
justify-content: center;
gap: 0.65rem;
}
.button {
appearance: none;
border-radius: 0.65rem;
border: 1px solid transparent;
padding: 0.62rem 1rem;
font: inherit;
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
}
.button:focus-visible {
outline: 2px solid color-mix(in srgb, var(--text) 28%, transparent);
outline-offset: 2px;
}
.button-primary {
background: var(--button);
color: var(--button-text);
}
.button-primary:hover {
opacity: 0.92;
}
.button-secondary {
background: var(--button-alt);
color: var(--button-alt-text);
border-color: var(--button-alt-border);
}
.button-secondary:hover {
background: var(--surface);
}
.link {
margin-top: 1rem;
display: inline-flex;
align-items: center;
gap: 0.4rem;
color: var(--muted);
font-size: 0.95rem;
text-decoration: none;
}
.link:hover {
color: var(--text);
}
@media (max-width: 520px) {
h1 {
font-size: 1.55rem;
}
.actions {
flex-direction: column;
align-items: stretch;
}
.button {
width: 100%;
}
}
</style>
</head>
<body>
<main class="error" role="main">
<div class="icon" aria-hidden="true">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-server-off-icon lucide-server-off"
>
<path d="M7 2h13a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-5" />
<path d="M10 10 2.5 2.5C2 2 2 2.5 2 5v3a2 2 0 0 0 2 2h6z" />
<path d="M22 17v-1a2 2 0 0 0-2-2h-1" />
<path d="M4 14a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16.5l1-.5.5.5-8-8H4z" />
<path d="M6 18h.01" />
<path d="m2 2 20 20" />
</svg>
</div>
<h1 data-i18n="heading">Произошла ошибка</h1>
<p class="text" data-i18n="description">
Не удалось открыть страницу. Попробуйте обновить её или вернуться на главную.
</p>
<div class="meta" aria-label="Error details">
<code><span data-i18n="status_label">Код</span>: %sveltekit.status%</code>
<code><span data-i18n="message_label">Сообщение</span>: %sveltekit.error.message%</code>
</div>
<div class="actions">
<button
class="button button-primary"
type="button"
onclick="window.location.reload()"
data-i18n="reload"
>
Обновить
</button>
<button
class="button button-secondary"
type="button"
onclick="window.location.href = '/'"
data-i18n="go_home"
>
На главную
</button>
</div>
</main>
<script>
(() => {
const translations = {
ru: {
heading: 'Произошла ошибка',
description:
'Не удалось открыть страницу. Попробуйте обновить её или вернуться на главную.',
status_label: 'Код',
message_label: 'Сообщение',
reload: 'Обновить',
go_home: 'На главную'
},
en: {
heading: 'Something went wrong',
description: 'Unable to open this page. Try reloading it or return to the home page.',
status_label: 'Status',
message_label: 'Message',
reload: 'Reload',
go_home: 'Home'
}
};
const browserLang =
(navigator.languages && navigator.languages[0]) || navigator.language || 'en';
const locale = browserLang.toLowerCase().startsWith('ru') ? 'ru' : 'en';
const dict = translations[locale];
document.documentElement.lang = locale;
document.querySelectorAll('[data-i18n]').forEach((node) => {
const key = node.dataset.i18n;
if (key && dict[key]) {
node.textContent = dict[key];
}
});
})();
</script>
</body>
</html>