Files
BetiX/resources/js/pages/Errors/Banned.vue
Dolo 0280278978
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
Initialer Laravel Commit für BetiX
2026-04-04 18:01:50 +02:00

177 lines
4.8 KiB
Vue

<script setup lang="ts">
import { Head } from '@inertiajs/vue3';
import { ref, computed, onMounted, onUnmounted } from 'vue';
const props = defineProps<{
reason?: string;
ends_at?: string | null;
}>();
const nowTs = ref<number>(Date.now());
let ticker: number | undefined;
onMounted(() => {
// Tick every second to update countdown
ticker = window.setInterval(() => { nowTs.value = Date.now(); }, 1000);
});
onUnmounted(() => {
if (ticker) window.clearInterval(ticker);
});
const endsAtDate = computed<Date | null>(() => {
if (!props.ends_at) return null;
const d = new Date(props.ends_at);
return isNaN(d.getTime()) ? null : d;
});
const remainingMs = computed<number>(() => {
if (!endsAtDate.value) return 0;
return Math.max(0, endsAtDate.value.getTime() - nowTs.value);
});
function formatCountdown(ms: number): string {
const totalSec = Math.floor(ms / 1000);
const days = Math.floor(totalSec / 86400);
const hours = Math.floor((totalSec % 86400) / 3600);
const minutes = Math.floor((totalSec % 3600) / 60);
const seconds = totalSec % 60;
const pad = (n: number) => n.toString().padStart(2, '0');
if (days > 0) return `${days}d ${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
}
const countdownText = computed<string | null>(() => {
if (!endsAtDate.value || remainingMs.value <= 0) return null;
return formatCountdown(remainingMs.value);
});
const exactEndText = computed<string | null>(() => {
if (!endsAtDate.value) return null;
try {
return endsAtDate.value.toLocaleString();
} catch {
return endsAtDate.value.toISOString();
}
});
</script>
<template>
<Head title="Account Suspended" />
<div class="banned-screen">
<div class="overlay"></div>
<div class="content">
<div class="stamp">BANNED</div>
<h1>Account Suspended</h1>
<p class="reason" v-if="reason">Reason: {{ reason }}</p>
<p v-if="countdownText && exactEndText" class="sub">Ends in <strong>{{ countdownText }}</strong> ({{ exactEndText }})</p>
<p v-else class="sub">Your account has been permanently suspended due to a violation of our Terms of Service.</p>
<div class="actions">
<a href="/logout" class="btn-logout" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">Sign Out</a>
<form id="logout-form" action="/logout" method="POST" style="display: none;">
<input type="hidden" name="_token" :value="$page.props.csrf_token">
</form>
</div>
</div>
</div>
</template>
<style scoped>
.banned-screen {
height: 100vh;
width: 100vw;
background-size: cover;
display: flex;
align-items: center;
justify-content: center;
position: relative;
font-family: 'Impact', sans-serif;
overflow: hidden;
}
.overlay {
position: absolute; inset: 0;
background: radial-gradient(circle, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.9) 100%);
backdrop-filter: blur(3px);
}
.content {
position: relative; z-index: 10;
text-align: center;
color: #fff;
animation: zoomIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.stamp {
font-size: 80px;
color: #ff3e3e;
border: 8px solid #ff3e3e;
display: inline-block;
padding: 10px 40px;
transform: rotate(-10deg);
margin-bottom: 30px;
text-transform: uppercase;
letter-spacing: 5px;
opacity: 0;
animation: stamp-fall 0.4s cubic-bezier(0.6, 0.04, 0.98, 0.335) 0.5s forwards;
mask-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/8399/grunge.png'); /* Grunge texture effect */
mask-size: 900px;
mix-blend-mode: multiply;
}
h1 {
font-family: 'Helvetica Neue', sans-serif;
font-size: 32px;
text-transform: uppercase;
letter-spacing: 2px;
margin-bottom: 10px;
text-shadow: 0 2px 10px rgba(0,0,0,0.8);
}
.reason {
font-size: 18px;
color: #ffaaaa;
background: rgba(255, 0, 0, 0.1);
padding: 10px 20px;
border-radius: 8px;
display: inline-block;
margin-bottom: 20px;
border: 1px solid rgba(255, 0, 0, 0.3);
}
.sub {
font-family: sans-serif;
font-size: 14px;
color: #ccc;
max-width: 400px;
margin: 0 auto 40px;
line-height: 1.5;
}
.btn-logout {
background: #fff;
color: #000;
padding: 12px 30px;
text-decoration: none;
font-weight: 900;
text-transform: uppercase;
border-radius: 4px;
transition: 0.2s;
}
.btn-logout:hover {
background: #ccc;
transform: scale(1.05);
}
@keyframes stamp-fall {
0% { opacity: 0; transform: rotate(-10deg) scale(3); }
100% { opacity: 1; transform: rotate(-10deg) scale(1); }
}
@keyframes zoomIn {
from { opacity: 0; transform: scale(0.8); }
to { opacity: 1; transform: scale(1); }
}
</style>