Refine admin PWA layout and tamagui usage

This commit is contained in:
Codex Agent
2026-01-15 22:24:10 +01:00
parent 8941860140
commit c533d43c0f
37 changed files with 51503 additions and 21989 deletions

View File

@@ -1,59 +1,120 @@
import { useTheme } from '@tamagui/core';
export const ADMIN_COLORS = {
primary: '#FF5A5F',
primaryStrong: '#C2413B',
accent: '#FFF8F5',
accentSoft: '#FFF1EB',
accentWarm: '#FFE4DA',
warning: '#F5C542',
success: '#06D6A0',
danger: '#B91C1C',
text: '#1F2937',
textMuted: '#6B7280',
textSubtle: '#94A3B8',
border: '#F2E4DA',
primary: '#FF5C5C',
primaryStrong: '#E63B57',
accent: '#3D5AFE',
accentSoft: '#E8ECFF',
accentWarm: '#FFE3D6',
warning: '#FBBF24',
success: '#22C55E',
danger: '#EF4444',
text: '#0B132B',
textMuted: '#54606E',
textSubtle: '#8C99A8',
border: '#F3D6C9',
surface: '#FFFFFF',
surfaceMuted: '#FFFDFB',
backdrop: '#0F172A',
surfaceMuted: '#FFF6F0',
backdrop: '#0B132B',
};
export const ADMIN_ACTION_COLORS = {
settings: '#14B8A6',
tasks: '#F59E0B',
qr: '#3B82F6',
images: '#8B5CF6',
liveShow: '#EC4899',
liveShowSettings: '#0EA5E9',
guests: '#10B981',
guestMessages: '#F97316',
branding: '#6366F1',
photobooth: '#E11D48',
recap: '#64748B',
settings: '#00C2A8',
tasks: '#FFC857',
qr: '#3D5AFE',
images: '#FF7AB6',
liveShow: '#FF6D00',
liveShowSettings: '#00B0FF',
guests: '#22C55E',
guestMessages: '#FF8A00',
branding: '#00B4D8',
photobooth: '#FF3D71',
recap: '#94A3B8',
packages: ADMIN_COLORS.primary,
analytics: '#22C55E',
invites: ADMIN_COLORS.primaryStrong,
invites: '#3D5AFE',
};
export const ADMIN_GRADIENTS = {
primaryCta: `linear-gradient(135deg, ${ADMIN_COLORS.primary}, #FF8A8E, ${ADMIN_COLORS.accent})`,
softCard: `linear-gradient(135deg, ${ADMIN_COLORS.accentSoft}, ${ADMIN_COLORS.accentWarm})`,
loginBackground: 'linear-gradient(135deg, #0b1020, #0f172a, #0b1020)',
primaryCta: `linear-gradient(135deg, ${ADMIN_COLORS.primary}, #FF9A5C, ${ADMIN_COLORS.accent})`,
softCard: 'linear-gradient(145deg, rgba(255,255,255,0.98), rgba(255,245,238,0.92))',
loginBackground: 'linear-gradient(135deg, #0b132b, #162040, #0b132b)',
appBackground:
'radial-gradient(circle at 15% 0%, rgba(255, 92, 92, 0.22), transparent 50%), radial-gradient(circle at 85% 10%, rgba(61, 90, 254, 0.2), transparent 55%), linear-gradient(180deg, #fff4ee 0%, #ffefe4 100%)',
appBackgroundDark:
'radial-gradient(circle at 15% 0%, rgba(255, 92, 92, 0.18), transparent 55%), radial-gradient(circle at 85% 10%, rgba(61, 90, 254, 0.18), transparent 55%), linear-gradient(180deg, #0b132b 0%, #0e1a33 100%)',
};
export const ADMIN_MOTION = {
tileStaggerMs: 40,
};
type Rgb = { r: number; g: number; b: number };
function parseRgb(color: string): Rgb | null {
const trimmed = color.trim();
if (trimmed.startsWith('#')) {
const hex = trimmed.slice(1);
const normalized = hex.length === 3 ? hex.split('').map((ch) => ch + ch).join('') : hex;
if (normalized.length === 6) {
return {
r: Number.parseInt(normalized.slice(0, 2), 16),
g: Number.parseInt(normalized.slice(2, 4), 16),
b: Number.parseInt(normalized.slice(4, 6), 16),
};
}
}
const rgb = trimmed.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/i);
if (rgb) {
return { r: Number(rgb[1]), g: Number(rgb[2]), b: Number(rgb[3]) };
}
const rgba = trimmed.match(/^rgba\((\d+),\s*(\d+),\s*(\d+),\s*([0-9.]+)\)$/i);
if (rgba) {
return { r: Number(rgba[1]), g: Number(rgba[2]), b: Number(rgba[3]) };
}
return null;
}
function withAlpha(color: string, alpha: number): string {
const rgb = parseRgb(color);
if (! rgb) {
return color;
}
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
}
function isDarkColor(color: string): boolean {
const rgb = parseRgb(color);
if (! rgb) {
return false;
}
const luminance = (0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b) / 255;
return luminance < 0.5;
}
export function useAdminTheme() {
const theme = useTheme();
const background = String(theme.background?.val ?? '#FFF8F5');
const surface = String(theme.surface?.val ?? ADMIN_COLORS.surface);
const border = String(theme.borderColor?.val ?? ADMIN_COLORS.border);
const isDark = isDarkColor(background);
const glassSurface = withAlpha(surface, isDark ? 0.96 : 0.98);
const glassSurfaceStrong = withAlpha(surface, isDark ? 1 : 1);
const glassBorder = withAlpha(border, isDark ? 0.85 : 0.95);
const glassShadow = isDark ? 'rgba(0, 0, 0, 0.55)' : 'rgba(11, 19, 43, 0.18)';
const appBackground = isDark ? ADMIN_GRADIENTS.appBackgroundDark : ADMIN_GRADIENTS.appBackground;
return {
theme,
background: String(theme.background?.val ?? '#FFF8F5'),
surface: String(theme.surface?.val ?? ADMIN_COLORS.surface),
background,
surface,
surfaceMuted: String(theme.gray2?.val ?? ADMIN_COLORS.surfaceMuted),
border: String(theme.borderColor?.val ?? ADMIN_COLORS.border),
border,
text: String(theme.color?.val ?? ADMIN_COLORS.text),
textStrong: String(theme.color12?.val ?? theme.color?.val ?? ADMIN_COLORS.text),
muted: String(theme.gray?.val ?? ADMIN_COLORS.textMuted),
@@ -73,7 +134,12 @@ export function useAdminTheme() {
infoText: String(theme.blue10?.val ?? ADMIN_COLORS.primaryStrong),
danger: String(theme.red10?.val ?? ADMIN_COLORS.danger),
backdrop: String(theme.gray12?.val ?? ADMIN_COLORS.backdrop),
overlay: String(theme.gray12?.val ?? 'rgba(15, 23, 42, 0.6)'),
shadow: String(theme.shadowColor?.val ?? 'rgba(31, 41, 55, 0.12)'),
overlay: withAlpha(String(theme.gray12?.val ?? ADMIN_COLORS.backdrop), 0.6),
shadow: String(theme.shadowColor?.val ?? 'rgba(15, 23, 42, 0.12)'),
glassSurface,
glassSurfaceStrong,
glassBorder,
glassShadow,
appBackground,
};
}