ddns/templates/layout.templ

108 lines
2.9 KiB
Text

package templates
import "io"
import "context"
// Render renders a component to an io.Writer
func Render(w io.Writer, component templ.Component) error {
return component.Render(context.Background(), w)
}
// Layout is the base layout for all pages
templ Layout(title string) {
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>{ title }</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css"
/>
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
<style>
body {
padding-top: 20px;
background-color: #f8f9fa;
}
.card {
margin-bottom: 20px;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}
.config-warning {
margin-bottom: 20px;
}
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 1050;
}
.update-badge {
font-size: 0.8em;
margin-left: 10px;
}
.htmx-indicator {
opacity: 0;
transition: opacity 300ms ease-in;
}
.htmx-request .htmx-indicator {
opacity: 1;
}
.htmx-request.htmx-indicator {
opacity: 1;
}
</style>
</head>
<body>
{ children... }
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Simple toast function for HTMX responses
document.body.addEventListener('htmx:afterRequest', function(evt) {
const xhr = evt.detail.xhr;
if (xhr.status >= 200 && xhr.status < 300) {
const successMessage = xhr.getResponseHeader('HX-Success-Message');
if (successMessage) {
showToast(successMessage, 'success');
}
} else {
const errorMessage = xhr.getResponseHeader('HX-Error-Message') || 'An error occurred';
showToast(errorMessage, 'danger');
}
});
function showToast(message, type = "success") {
const toastContainer = document.querySelector(".toast-container");
const toast = document.createElement("div");
toast.className = `toast align-items-center text-white bg-${type}`;
toast.setAttribute("role", "alert");
toast.setAttribute("aria-live", "assertive");
toast.setAttribute("aria-atomic", "true");
toast.innerHTML = `
<div class="d-flex">
<div class="toast-body">${message}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
`;
toastContainer.appendChild(toast);
const bsToast = new bootstrap.Toast(toast);
bsToast.show();
toast.addEventListener("hidden.bs.toast", () => {
toast.remove();
});
}
</script>
</body>
</html>
}