Files
oslstats/internal/view/component/popup/errorModal.templ

127 lines
3.9 KiB
Plaintext

package popup
// ErrorModal displays a full-screen modal for critical errors (500, 503)
templ ErrorModal() {
<div
x-show="errorModal.show"
x-cloak
class="fixed inset-0 z-50 flex items-center justify-center p-4"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
>
<!-- Backdrop (not clickable) -->
<div class="absolute inset-0 bg-crust/80"></div>
<!-- Modal Card -->
<div
class="relative bg-surface0 border-2 border-dark-red rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto"
x-transition:enter="transition ease-out duration-300 delay-100"
x-transition:enter-start="opacity-0 translate-y-4"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 translate-y-4"
role="dialog"
aria-modal="true"
aria-labelledby="error-modal-title"
>
<!-- Header -->
<div class="flex items-start justify-between p-6 border-b border-dark-red">
<div class="flex items-center gap-3">
<!-- Warning Icon -->
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-8 text-red flex-shrink-0"
>
<path
fill-rule="evenodd"
d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z"
clip-rule="evenodd"
></path>
</svg>
<!-- Title -->
<h2
id="error-modal-title"
class="text-2xl font-bold text-red"
x-text="`${errorModal.code} - ${errorModal.title}`"
></h2>
</div>
<!-- Close Button -->
<button
@click="closeErrorModal()"
class="text-subtext0 hover:text-text transition"
aria-label="Close modal"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-6"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6 18L18 6M6 6l12 12"
></path>
</svg>
</button>
</div>
<!-- Body -->
<div class="p-6">
<!-- User Message -->
<p class="text-lg text-subtext0" x-text="errorModal.message"></p>
<!-- Details Dropdown -->
<div class="mt-6">
<details class="bg-mantle rounded-lg p-4">
<summary class="cursor-pointer text-subtext1 font-semibold select-none hover:text-text transition">
Details
<span class="text-xs text-subtext0 ml-2">(click to expand)</span>
</summary>
<div class="mt-4 relative">
<pre
id="error-modal-details"
class="text-xs text-subtext0 font-mono whitespace-pre-wrap break-all bg-surface0 p-4 rounded overflow-x-auto max-h-96"
x-text="errorModal.details"
></pre>
</div>
<button
onclick="copyToClipboard('error-modal-details', this)"
class="mt-2 bg-mauve text-crust px-3 py-1 rounded text-xs hover:bg-mauve/75 transition"
title="Copy to clipboard"
>
Copy
</button>
</details>
</div>
</div>
</div>
</div>
<!-- Copy to Clipboard Script -->
<script>
function copyToClipboard(elementId, button) {
const element = document.getElementById(elementId);
const text = element.innerText;
navigator.clipboard.writeText(text)
.then(() => {
const originalText = button.innerText;
button.innerText = 'Copied!';
setTimeout(() => {
button.innerText = originalText;
}, 2000);
})
.catch(err => {
console.error('Failed to copy:', err);
button.innerText = 'Failed';
});
}
</script>
}