Files
cluedo-hp-webapp/frontend/src/styles/hooks/useHpGlobalStyles.js
T
nessi a532cae9bd Add user editing functionality to admin panel with improved UI and self-protection safeguards
Implemented comprehensive user editing in admin dashboard with PATCH endpoint for updating email, display name, role, password, and disabled status. Added validation to prevent admins from demoting or disabling themselves, and duplicate email detection. Refactored AdminPanel to modal-based editor with separate create/edit modes, form state management, and save/cancel actions. Enhanced UI with field labels, checkbox for account status, action
2026-08-02 10:11:38 +02:00

154 lines
9.5 KiB
JavaScript

import { useEffect } from "react";
import { stylesTokens } from "../theme";
import { applyTheme } from "../themes";
export function useHpGlobalStyles() {
// Google Fonts
useEffect(() => {
if (document.getElementById("hp-fonts")) return;
const pre1 = document.createElement("link");
pre1.id = "hp-fonts-pre1";
pre1.rel = "preconnect";
pre1.href = "https://fonts.googleapis.com";
const pre2 = document.createElement("link");
pre2.id = "hp-fonts-pre2";
pre2.rel = "preconnect";
pre2.href = "https://fonts.gstatic.com";
pre2.crossOrigin = "anonymous";
const link = document.createElement("link");
link.id = "hp-fonts";
link.rel = "stylesheet";
link.href =
"https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@700;900&family=IM+Fell+English:ital,wght@0,400;0,700;1,400&display=swap";
document.head.appendChild(pre1);
document.head.appendChild(pre2);
document.head.appendChild(link);
}, []);
// Keyframes
useEffect(() => {
if (document.getElementById("hp-anim-style")) return;
const style = document.createElement("style");
style.id = "hp-anim-style";
style.innerHTML = `
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes popIn { from { opacity: 0; transform: translateY(8px) scale(0.985); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes rowPulse { 0%{ transform: scale(1); } 50%{ transform: scale(1.01); } 100%{ transform: scale(1); } }
@keyframes candleGlow {
0% { opacity: .55; transform: translateY(0px) scale(1); filter: blur(16px); }
35% { opacity: .85; transform: translateY(-2px) scale(1.02); filter: blur(18px); }
70% { opacity: .62; transform: translateY(1px) scale(1.01); filter: blur(17px); }
100% { opacity: .55; transform: translateY(0px) scale(1); filter: blur(16px); }
}
`;
document.head.appendChild(style);
}, []);
// html/body reset
useEffect(() => {
document.documentElement.style.height = "100%";
document.body.style.height = "100%";
document.documentElement.style.margin = "0";
document.body.style.margin = "0";
document.documentElement.style.padding = "0";
document.body.style.padding = "0";
}, []);
// Global CSS
useEffect(() => {
if (document.getElementById("hp-global-style")) return;
const style = document.createElement("style");
style.id = "hp-global-style";
style.innerHTML = `
html, body {
overscroll-behavior-y: none;
-webkit-text-size-adjust: 100%;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background: ${stylesTokens.pageBg};
color: ${stylesTokens.textMain};
}
body {
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
#root { background: transparent; }
* { -webkit-tap-highlight-color: transparent; }
button, input, select { font-family: inherit; }
button { transition: transform 140ms ease, filter 140ms ease, border-color 140ms ease, background 140ms ease; }
button:not(:disabled):hover { filter: brightness(1.12); transform: translateY(-1px); }
button:not(:disabled):active { transform: translateY(0); filter: brightness(0.98); }
button:disabled { cursor: not-allowed; opacity: 0.55; }
input:focus, select:focus { border-color: var(--hp-textGold) !important; box-shadow: 0 0 0 3px color-mix(in srgb, var(--hp-textGold) 16%, transparent); }
.hp-row { transition: background 140ms ease, transform 140ms ease, box-shadow 140ms ease; }
.hp-row:hover { box-shadow: inset 0 0 0 1px rgba(233,216,166,0.12); }
.hp-start-overlay { position: fixed; inset: 0; z-index: 2147483646; display: grid; place-items: center; padding: 20px; background: radial-gradient(circle at center, rgba(233,216,166,0.12), rgba(4,4,7,0.88) 48%, rgba(0,0,0,0.96)); animation: hpStartFade 260ms ease-out; }
.hp-start-card { position: relative; width: min(420px, 100%); padding: 30px 22px 24px; border: 1px solid rgba(233,216,166,0.34); border-radius: 24px; text-align: center; background: linear-gradient(145deg, rgba(34,31,38,0.96), rgba(10,10,14,0.96)); box-shadow: 0 24px 90px rgba(0,0,0,0.72), 0 0 60px rgba(233,216,166,0.12); animation: hpStartCard 520ms cubic-bezier(.2,.8,.2,1); overflow: hidden; }
.hp-start-card::before, .hp-start-card::after { content: ""; position: absolute; left: 12%; right: 12%; height: 1px; background: linear-gradient(90deg, transparent, rgba(233,216,166,0.72), transparent); animation: hpStartLine 1.8s ease-in-out infinite; }
.hp-start-card::before { top: 12px; }
.hp-start-card::after { bottom: 12px; animation-delay: .45s; }
.hp-start-rune { color: var(--hp-textGold); font-size: 32px; line-height: 1; animation: hpStartRune 1.4s ease-in-out infinite; }
.hp-start-kicker { margin-top: 14px; color: var(--hp-textDim); font-size: 12px; letter-spacing: .16em; text-transform: uppercase; }
.hp-start-title { margin-top: 8px; color: var(--hp-textGold); font-family: "Cinzel Decorative", "IM Fell English", system-ui; font-size: 25px; font-weight: 900; }
.hp-start-subtitle { margin-top: 8px; color: var(--hp-textMain); font-size: 15px; }
.hp-start-card button { border: 1px solid rgba(233,216,166,0.26); border-radius: 12px; background: rgba(233,216,166,0.10); padding: 10px 16px; font-weight: 900; cursor: pointer; }
@keyframes hpStartFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes hpStartCard { from { opacity: 0; transform: translateY(18px) scale(.92) rotateX(8deg); } to { opacity: 1; transform: translateY(0) scale(1) rotateX(0); } }
@keyframes hpStartRune { 0%, 100% { transform: rotate(0) scale(1); opacity: .7; } 50% { transform: rotate(180deg) scale(1.22); opacity: 1; } }
@keyframes hpStartLine { 0%, 100% { opacity: .3; transform: scaleX(.7); } 50% { opacity: 1; transform: scaleX(1); } }
.hp-topbar-actions { margin-left: auto; }
.hp-user-menu-wrap { min-width: 0; }
.hp-admin-user-row { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.5fr) 70px 76px 150px; }
.hp-admin-action { min-width: 0; }
.hp-admin-actions { display: flex; align-items: center; justify-content: flex-end; gap: 6px; min-width: 0; }
.hp-admin-check { display: flex; align-items: center; gap: 8px; color: var(--hp-textDim); font-size: 13px; }
.hp-admin-check input { width: 18px; height: 18px; accent-color: var(--hp-textGold); }
.hp-admin-role { padding: 4px 8px; border-radius: 999px; background: rgba(233,216,166,0.10); border: 1px solid rgba(233,216,166,0.16); font-size: 12px; }
.hp-admin-status { color: #baf3c9 !important; font-size: 13px; }
.hp-admin-status--disabled { color: #ffb3b3 !important; }
@media (max-width: 600px) {
.hp-shell { padding: calc(12px + env(safe-area-inset-top)) 10px calc(28px + env(safe-area-inset-bottom)) !important; }
.hp-topbar { align-items: center !important; padding: 10px !important; gap: 6px !important; flex-wrap: nowrap !important; }
.hp-topbar > div:first-child { min-width: 0; flex: 1; }
.hp-topbar > div:first-child > div:last-child { max-width: 105px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px !important; }
.hp-topbar-actions { width: auto; flex: 0 0 auto; margin-left: 0; gap: 5px !important; }
.hp-user-menu-wrap { flex: 0 0 auto; min-width: 0; }
.hp-topbar-user, .hp-topbar-new { flex: 0 0 auto; min-height: 40px; width: auto; padding: 8px 9px !important; font-size: 13px; }
.hp-topbar-user { justify-content: center; }
.hp-user-dropdown { left: 50% !important; right: auto !important; transform: translateX(-50%); width: max-content; max-width: calc(100vw - 20px); min-width: min(220px, calc(100vw - 20px)) !important; }
.hp-user-dropdown > div:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hp-admin-user-row { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 10px; padding: 11px !important; border-radius: 15px !important; }
.hp-admin-name { grid-column: 1; grid-row: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 16px; }
.hp-admin-email { grid-column: 1; grid-row: 2; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px !important; }
.hp-admin-role { grid-column: 2; grid-row: 1; }
.hp-admin-status { grid-column: 2; grid-row: 2; }
.hp-admin-actions { grid-column: 1 / -1; grid-row: 3; width: 100%; justify-content: flex-end; }
.hp-admin-actions .hp-admin-action { width: auto; min-width: 0; min-height: 38px; padding: 7px 10px !important; }
.hp-row { grid-template-columns: minmax(0, 1fr) 42px 62px !important; gap: 7px !important; padding: 12px 11px !important; }
.hp-row button { min-height: 40px; }
button { min-height: 42px; }
input, select { min-height: 44px; box-sizing: border-box; }
.hp-topbar + * { margin-top: 12px !important; }
}
@media (max-width: 360px) {
.hp-row { grid-template-columns: minmax(0, 1fr) 38px 56px !important; font-size: 14px; }
.hp-topbar { gap: 5px !important; }
.hp-topbar-user, .hp-topbar-new { padding-left: 7px !important; padding-right: 7px !important; font-size: 12px; }
}
`;
document.head.appendChild(style);
}, []);
// Ensure a theme is applied once (fallback)
useEffect(() => {
applyTheme("default");
}, []);
}