Fixed colours
This commit is contained in:
@@ -24,7 +24,7 @@ export default function BracketView({ matches, onMatchClick }) {
|
||||
const ex = r2.left - container.left, ey = r2.top + r2.height / 2 - container.top;
|
||||
const c1 = sx + (ex - sx) / 2;
|
||||
newLines.push(
|
||||
<path key={`w-${m.id}`} d={`M ${sx} ${sy} C ${c1} ${sy}, ${c1} ${ey}, ${ex} ${ey}`} className="stroke-zinc-300 dark:stroke-zinc-700 print:!stroke-zinc-400 fill-none stroke-[1.5px]" />
|
||||
<path key={`w-${m.id}`} d={`M ${sx} ${sy} C ${c1} ${sy}, ${c1} ${ey}, ${ex} ${ey}`} className="stroke-zinc-400/70 dark:stroke-zinc-700/70 print:!stroke-zinc-400 fill-none stroke-[2px]" />
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ export default function BracketView({ matches, onMatchClick }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-full overflow-auto print:overflow-visible print:h-auto print:w-auto bg-[#f8f9fa] dark:bg-zinc-950 bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] dark:bg-[radial-gradient(#27272a_1px,transparent_1px)] [background-size:24px_24px] print:!bg-white print:!bg-none">
|
||||
<div className="w-full h-full overflow-auto print:overflow-visible print:h-auto print:w-auto bg-zinc-50 dark:bg-zinc-950 bg-[radial-gradient(theme(colors.zinc.300)_1px,transparent_1px)] dark:bg-[radial-gradient(theme(colors.zinc.800)_1px,transparent_1px)] [background-size:20px_20px] print:!bg-white print:!bg-none">
|
||||
<style>
|
||||
{`@media print {
|
||||
@page { size: landscape; margin: 0.5cm; }
|
||||
|
||||
@@ -19,9 +19,9 @@ export default function MatchCard({ match, onClick }) {
|
||||
<div
|
||||
id={`match-${match.id}`}
|
||||
onClick={() => canInteract && onClick(match)}
|
||||
className={`w-64 bg-white dark:bg-zinc-900 print:!bg-white rounded-lg border ${borderClass} print:!border-zinc-400 print:!shadow-none shadow-sm transition-all duration-200 print:transition-none relative z-10 flex flex-col ${cursorClass}`}
|
||||
className={`transition-colors w-64 bg-white dark:bg-zinc-900 print:!bg-white rounded-lg border ${borderClass} print:!border-zinc-400 print:!shadow-none shadow-sm transition-all duration-200 print:transition-none relative z-10 flex flex-col ${cursorClass}`}
|
||||
>
|
||||
<div className="bg-zinc-50 dark:bg-zinc-900/50 print:!bg-transparent px-3 py-1.5 flex justify-between items-center border-b border-zinc-200 dark:border-zinc-800 print:!border-zinc-400 rounded-t-lg">
|
||||
<div className="transition-colors bg-zinc-50 dark:bg-zinc-900/50 print:!bg-transparent px-3 py-1.5 flex justify-between items-center border-b border-zinc-200 dark:border-zinc-800 print:!border-zinc-400 rounded-t-lg">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono text-[10px] font-bold text-zinc-400 print:!text-zinc-600"># {match.number}</span>
|
||||
{match.time && (
|
||||
@@ -42,9 +42,9 @@ export default function MatchCard({ match, onClick }) {
|
||||
{ n: match.p1, s: match.p1_sets, win: match.winner_team_id !== null && match.winner_team_id === match.p1_team_id, real: match.p1_is_real },
|
||||
{ n: match.p2, s: match.p2_sets, win: match.winner_team_id !== null && match.winner_team_id === match.p2_team_id, real: match.p2_is_real }
|
||||
].map((p, i) => (
|
||||
<div key={i} className={`flex justify-between items-center ${p.win ? 'text-zinc-900 dark:text-white print:!text-black font-black' : p.real ? 'text-zinc-600 dark:text-zinc-300 print:!text-black' : 'text-zinc-400 print:!text-zinc-600 italic'}`}>
|
||||
<div key={i} className={`flex justify-between items-center ${p.win ? 'text-zinc-800 dark:text-zinc-50 print:!text-black font-black' : p.real ? 'text-zinc-500 dark:text-zinc-400 print:!text-black' : 'text-zinc-400 print:!text-zinc-600 italic'}`}>
|
||||
|
||||
<span className="truncate text-xs tracking-tight pr-2 print:hidden">{p.n}</span>
|
||||
<span className={`truncate text-xs tracking-tight pr-2 print:hidden ${p.win ? ' font-black text-orange-500' : 'font-bold'}`}>{p.n}</span>
|
||||
|
||||
<span className="hidden print:inline-block print:whitespace-normal print:overflow-visible text-xs tracking-tight pr-2">
|
||||
{printName(p.n)}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// frontend/src/components/Layout/Layout.jsx
|
||||
|
||||
import { Moon, Sun } from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { getToken } from '../../services/api';
|
||||
import ThemeButton from "../UI/ThemeButton";
|
||||
import Navbar from './Navbar';
|
||||
|
||||
export default function Layout({ darkMode, setDarkMode }) {
|
||||
@@ -40,15 +40,7 @@ export default function Layout({ darkMode, setDarkMode }) {
|
||||
<Outlet context={{ setNavTitle, setNavSubtitle, isAdmin, showSettings, setShowSettings }} />
|
||||
</main>
|
||||
|
||||
<div className="fixed bottom-6 sm:bottom-8 right-6 sm:right-8 z-40 print:hidden">
|
||||
<button
|
||||
onClick={() => setDarkMode(!darkMode)}
|
||||
title="Toggle Theme"
|
||||
className="p-4 sm:p-5 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-[1.5rem] sm:rounded-[2rem] shadow-2xl transition hover:scale-110 active:scale-95 border-2 border-zinc-700 dark:border-zinc-300 group"
|
||||
>
|
||||
{darkMode ? <Sun size={24} strokeWidth={2.5} className="sm:size-7" /> : <Moon size={24} strokeWidth={2.5} className="sm:size-7" />}
|
||||
</button>
|
||||
</div>
|
||||
<ThemeButton darkMode={darkMode} setDarkMode={setDarkMode} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
export default function Navbar({ title, subtitle, isAdmin, onLogout }) {
|
||||
return (
|
||||
<nav className="bg-white/95 dark:bg-zinc-900/95 backdrop-blur-lg border-b border-zinc-300 dark:border-zinc-800 sticky top-0 z-[100] px-3 sm:px-6 py-3 sm:py-4 flex justify-between items-center shadow-md shrink-0">
|
||||
<nav className="transition-colors bg-zinc-50 dark:bg-zinc-900 border-b border-zinc-300 dark:border-zinc-800 sticky top-0 z-[100] px-3 sm:px-6 py-3 sm:py-4 flex justify-between items-center shadow-md shrink-0">
|
||||
<Link to="/" className="flex items-center gap-2 sm:gap-4 cursor-pointer group select-none shrink-0">
|
||||
<div className="p-1.5 sm:p-2.5 bg-orange-600 rounded-xl group-hover:rotate-12 transition-transform shadow-lg shadow-orange-600/30 active:scale-90">
|
||||
<Volleyball className="text-white" size={20} />
|
||||
@@ -16,7 +16,7 @@ export default function Navbar({ title, subtitle, isAdmin, onLogout }) {
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<div className="absolute left-1/2 -translate-x-1/2 text-center pointer-events-none w-full max-w-[140px] xs:max-w-[180px] sm:max-w-[400px]">
|
||||
<div className="transition-colors absolute left-1/2 -translate-x-1/2 text-center pointer-events-none w-full max-w-[140px] xs:max-w-[180px] sm:max-w-[400px]">
|
||||
<div className="font-black uppercase text-[10px] sm:text-sm tracking-[0.1em] sm:tracking-[0.3em] text-zinc-900 dark:text-white truncate leading-none mb-1">
|
||||
{title || 'Dashboard'}
|
||||
</div>
|
||||
|
||||
@@ -9,14 +9,14 @@ export default function ScheduleRow({ match: m, onMatchClick, badgeWidth }) {
|
||||
const isFinished = m.isFinished;
|
||||
|
||||
return (
|
||||
<div className="bg-white dark:bg-zinc-900 print:!bg-white p-4 print:p-3 rounded-2xl print:rounded-none border border-zinc-300 dark:border-zinc-800 print:!border-b print:!border-x-0 print:!border-t-0 print:!border-zinc-300 shadow-sm print:!shadow-none flex items-center justify-between transition-all hover:border-orange-500/30">
|
||||
<div className="transition-colors bg-white dark:bg-zinc-900 print:!bg-white p-4 print:p-3 rounded-2xl print:rounded-none border border-zinc-300 dark:border-zinc-800 print:!border-b print:!border-x-0 print:!border-t-0 print:!border-zinc-300 shadow-sm print:!shadow-none flex items-center justify-between transition-all hover:border-orange-500/30">
|
||||
<div className="flex gap-4 md:gap-6 print:gap-6 flex-1 min-w-0">
|
||||
<div className="flex flex-col gap-1 items-center shrink-0" style={{ minWidth: badgeWidth }}>
|
||||
<div className="text-lg md:text-xl print:text-xl font-black font-mono text-zinc-900 dark:text-white print:!text-black">{m.time}</div>
|
||||
<div className="text-tiny font-black text-white print:!text-zinc-800 px-2 py-1 rounded uppercase w-full truncate text-center print:!border print:!border-zinc-400 print:!bg-transparent" style={{ background: courtColor }}>
|
||||
{m.court}
|
||||
</div>
|
||||
<div className="block md:hidden print:hidden text-tiny font-black bg-zinc-100 dark:bg-zinc-800 w-full truncate text-center print:!bg-transparent text-zinc-400 print:!text-zinc-500 px-2 py-1 rounded w-fit">Match #{m.number}</div>
|
||||
<div className="transition-colors block md:hidden print:hidden text-tiny font-black bg-zinc-100 dark:bg-zinc-800 w-full truncate text-center print:!bg-transparent text-zinc-400 print:!text-zinc-500 px-2 py-1 rounded w-fit">Match #{m.number}</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 flex flex-col gap-0.5 min-w-0 justify-center md:justify-between">
|
||||
@@ -35,7 +35,7 @@ export default function ScheduleRow({ match: m, onMatchClick, badgeWidth }) {
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
<div className="hidden md:block print:block text-tiny font-black bg-zinc-100 dark:bg-zinc-800 print:!bg-transparent text-zinc-400 print:!text-zinc-500 px-2 py-1 rounded w-fit">Match #{m.number}</div>
|
||||
<div className="transition-colors hidden md:block print:block text-tiny font-black bg-zinc-100 dark:bg-zinc-800 print:!bg-transparent text-zinc-400 print:!text-zinc-500 px-2 py-1 rounded w-fit">Match #{m.number}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -49,14 +49,14 @@ export default function ScheduleRow({ match: m, onMatchClick, badgeWidth }) {
|
||||
title="Edit Score"
|
||||
>
|
||||
{/* --- MOBILE VERTICAL STACK --- */}
|
||||
<div className="px-2 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-white text-[10px] font-black font-mono border border-zinc-200 dark:border-zinc-700 md:hidden">
|
||||
<div className={`${m.winnerName === m.p1 ? 'bg-orange-100 dark:bg-orange-900/30 text-orange-700' : 'bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-50'} px-2 py-0.5 rounded text-[10px] font-black font-mono border border-zinc-200 dark:border-zinc-700 md:hidden`}>
|
||||
{m.p1_sets}
|
||||
</div>
|
||||
|
||||
{/* Clean minimal vertical line for mobile */}
|
||||
<div className="w-[2px] h-3 bg-zinc-200 dark:bg-zinc-700 rounded-full md:hidden my-1" />
|
||||
|
||||
<div className="px-2 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-white text-[10px] font-black font-mono border border-zinc-200 dark:border-zinc-700 md:hidden">
|
||||
<div className={`${m.winnerName === m.p2 ? 'bg-orange-100 dark:bg-orange-900/30 text-orange-700' : 'bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-50'} px-2 py-0.5 rounded text-[10px] font-black font-mono border border-zinc-200 dark:border-zinc-700 md:hidden`}>
|
||||
{m.p2_sets}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function ScheduleView({ schedule, onMatchClick }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute top-0 left-0 right-3 h-32 bg-gradient-to-b from-zinc-50 via-zinc-50/95 to-transparent dark:from-zinc-950 dark:via-zinc-950/95 dark:to-transparent pointer-events-none z-20 print:hidden" />
|
||||
<div className="transition-colors absolute top-0 left-0 right-3 h-32 bg-gradient-to-b from-zinc-50 via-zinc-50/95 to-transparent dark:from-zinc-950 dark:via-zinc-950/95 dark:to-transparent pointer-events-none z-20 print:hidden" />
|
||||
|
||||
<div className="flex-1 overflow-y-auto print:overflow-visible p-6 pt-28 pb-32 print:p-0 print:pt-12 relative z-10">
|
||||
<div className="max-w-4xl mx-auto w-full space-y-3 print:space-y-0">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// frontend/src/components/Tournament/Podium.jsx
|
||||
|
||||
import { Trophy } from 'lucide-react';
|
||||
import { printName } from '../../utils/helpers';
|
||||
|
||||
export default function Podium({ matches }) {
|
||||
const isDoubleElim = matches.some(m => m.bracket === 'Loser');
|
||||
@@ -73,14 +74,6 @@ export default function Podium({ matches }) {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper for rendering print strings (Takes "Winner of #7" -> "W#7: _______")
|
||||
const printName = (name) => {
|
||||
if (!name) return '';
|
||||
if (name.startsWith('Winner of #')) return name.replace('Winner of #', 'W#') + ': _______';
|
||||
if (name.startsWith('Loser of #')) return name.replace('Loser of #', 'L#') + ': _______';
|
||||
return name;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white dark:bg-zinc-900 print:!bg-white border border-zinc-200 dark:border-zinc-800 print:!border-zinc-400 rounded-xl shadow-sm w-64 overflow-hidden z-10 print:!shadow-none">
|
||||
<div className="bg-zinc-50 dark:bg-zinc-900/50 print:!bg-transparent p-3 border-b border-zinc-200 dark:border-zinc-800 print:!border-zinc-400">
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// frontend/src/components/UI/ThemeButton.jsx
|
||||
|
||||
import { Moon, Sun } from 'lucide-react';
|
||||
|
||||
export default function ThemeButton({ darkMode, setDarkMode }) {
|
||||
return (
|
||||
<div className="fixed bottom-6 sm:bottom-8 right-6 sm:right-8 z-40 print:hidden">
|
||||
<button
|
||||
onClick={() => setDarkMode(!darkMode)}
|
||||
title="Toggle Theme"
|
||||
className="p-4 sm:p-5 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-[1.5rem] sm:rounded-[2rem] shadow-2xl transition hover:scale-110 active:scale-95 border-2 border-zinc-700 dark:border-zinc-300 group"
|
||||
>
|
||||
{darkMode ? <Sun size={24} strokeWidth={2.5} className="sm:size-7" /> : <Moon size={24} strokeWidth={2.5} className="sm:size-7" />}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -112,7 +112,7 @@ export default function Tournament() {
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col print:h-auto print:block">
|
||||
<div className="border-b border-zinc-200 dark:border-zinc-800 bg-white/50 dark:bg-zinc-900/50 backdrop-blur px-6 py-3 flex justify-between items-center shrink-0 z-20 print:hidden">
|
||||
<div className="border-b border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 px-6 py-3 flex justify-between items-center shrink-0 z-20 print:hidden">
|
||||
<div className="flex gap-2">
|
||||
<button onClick={() => handleViewChange('bracket')} className={`flex items-center gap-2 px-4 py-2 rounded-xl text-xs font-black uppercase tracking-wider transition ${view === 'bracket' ? 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400' : 'text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800'}`}>
|
||||
<Network size={16} /> Bracket
|
||||
|
||||
Reference in New Issue
Block a user