- Fixed Challenge Modal overlap issue by adjusting the main stacking context in App.tsx
- Implemented "click-outside-to-close" functionality for both the Challenge Modal and User Dropdown - Added protocol-specific action buttons for challenges: "Open in new tab" for HTTP and "Copy to clipboard" for NC - Enhanced Scoreboard rankings with significantly larger, consistent font sizes (text-2xl) for better readability - Rebranded "TEAM_IDENTIFIER" to "PLAYER" and "TOTAL_POINTS" to "POINTS" across the platform (Scoreboard, Matrix, User Menu) - Updated navigation: Renamed "SCOREBOARD" to "SCORES" in the nav bar and dynamic page titles - Modernized User Dropdown menu with a dedicated "PLAYER" header and "LOGOUT" action - Improved Score Matrix and Score Graph titles for consistency with the new "Player" terminology - Added CAPTCHA human verification (svg-captcha) to Login and Registration flows for enhanced security - Optimized frontend assets by migrating Tailwind and JetBrains Mono to local hosting - Refactored Admin panel: Renamed "Operators" to "Users" and improved layout alignment
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { X, CheckCircle2, Download, Globe, Sparkles, Heart, Clock, Bell } from 'lucide-react';
|
||||
import { X, CheckCircle2, Download, Globe, Sparkles, Heart, Clock, Bell, Copy, ExternalLink } from 'lucide-react';
|
||||
import { useCTF } from './CTFContext';
|
||||
import { Challenge, Difficulty } from './types';
|
||||
import { CATEGORIES } from './constants';
|
||||
@@ -43,8 +43,8 @@ const ChallengeModal: React.FC<{ challenge: Challenge; onClose: () => void; }> =
|
||||
const difficultyColor = challenge.difficulty === 'Low' ? 'text-[#00ff00]' : challenge.difficulty === 'Medium' ? 'text-[#ffaa00]' : 'text-[#ff0000]';
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black/95 z-[300] flex items-center justify-center p-4">
|
||||
<div className="hxp-border border-4 max-w-2xl w-full bg-black p-8 relative overflow-y-auto max-h-[90vh] custom-scrollbar">
|
||||
<div className="fixed inset-0 bg-black/95 z-[300] flex items-center justify-center p-4" onClick={onClose}>
|
||||
<div className="hxp-border border-4 max-w-2xl w-full bg-black p-8 relative overflow-y-auto max-h-[90vh] custom-scrollbar" onClick={(e) => e.stopPropagation()}>
|
||||
<button onClick={onClose} className="absolute top-4 right-4 bg-[#ff0000] text-black font-black p-2 hover:bg-white transition-colors"><X size={24} /></button>
|
||||
<div className="mb-8">
|
||||
<h3 className="text-4xl font-black italic tracking-tighter text-white mb-2">{challenge.title}</h3>
|
||||
@@ -57,7 +57,34 @@ const ChallengeModal: React.FC<{ challenge: Challenge; onClose: () => void; }> =
|
||||
{connectionDetails && (
|
||||
<div className="mb-8 p-4 hxp-border border-[#00ccff] bg-[#00ccff]/5">
|
||||
<h4 className="text-[10px] font-black text-[#00ccff] uppercase tracking-[0.2em] mb-2 flex items-center gap-2"><Globe size={12}/> Connect to:</h4>
|
||||
<code className="block bg-black p-3 text-[#00ccff] font-black text-sm border border-[#00ccff]/30 break-all select-all">{connectionDetails}</code>
|
||||
<div className="flex gap-2">
|
||||
<code className="flex-1 bg-black p-3 text-[#00ccff] font-black text-sm border border-[#00ccff]/30 break-all select-all">{connectionDetails}</code>
|
||||
{(challenge.connectionType || 'nc') === 'nc' ? (
|
||||
<button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(connectionDetails);
|
||||
const btn = document.activeElement as HTMLButtonElement;
|
||||
const originalContent = btn.innerHTML;
|
||||
btn.innerHTML = 'COPIED!';
|
||||
setTimeout(() => { btn.innerHTML = originalContent; }, 2000);
|
||||
}}
|
||||
className="bg-[#00ccff] text-black p-3 hover:bg-white transition-colors flex items-center justify-center min-w-[50px]"
|
||||
title="Copy to clipboard"
|
||||
>
|
||||
<Copy size={20} />
|
||||
</button>
|
||||
) : (
|
||||
<a
|
||||
href={connectionDetails}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="bg-[#00ccff] text-black p-3 hover:bg-white transition-colors flex items-center justify-center min-w-[50px]"
|
||||
title="Open in new tab"
|
||||
>
|
||||
<ExternalLink size={20} />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -87,7 +114,7 @@ const ChallengeModal: React.FC<{ challenge: Challenge; onClose: () => void; }> =
|
||||
) : <p className="text-center font-bold text-red-500 mb-10 uppercase tracking-widest">PLEASE_SIGN_IN_TO_SOLVE</p>}
|
||||
|
||||
<div className="border-t-4 border-[#333] pt-6">
|
||||
<h4 className="text-sm font-black text-white tracking-[0.2em] mb-4 flex items-center gap-2 uppercase"><Sparkles size={14} /> SOLVER_LOG</h4>
|
||||
<h4 className="text-sm font-black text-white tracking-[0.2em] mb-4 flex items-center gap-2 uppercase"><Sparkles size={14} /> SOLVES</h4>
|
||||
<div className="space-y-1">
|
||||
{(challenge.solves || []).length > 0 ? (
|
||||
state.solves.filter(s => s.challengeId === challenge.id).sort((a, b) => a.timestamp - b.timestamp).map((solve, idx) => {
|
||||
@@ -100,7 +127,7 @@ const ChallengeModal: React.FC<{ challenge: Challenge; onClose: () => void; }> =
|
||||
<div key={solve.teamId + idx} className="flex justify-between items-center p-3 bg-white/5 border border-white/10 text-[10px] font-bold">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className={`w-5 h-5 flex items-center justify-center font-black ${idx === 0 ? 'bg-[#ffaa00] text-black' : idx === 1 ? 'bg-slate-400 text-black' : idx === 2 ? 'bg-[#cd7f32] text-black' : 'bg-white/10 text-slate-500'}`}>{idx + 1}</span>
|
||||
<span className="text-white text-xs uppercase italic">{team?.name}</span>
|
||||
<span className="text-white text-xs font-black">{team?.name}</span>
|
||||
{bonus > 0 && <span className="text-[#00ff00] animate-pulse">+{bonus} BONUS</span>}
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
@@ -170,8 +197,8 @@ export const ChallengeList: React.FC = () => {
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto py-32 text-center hxp-border border-4 p-12">
|
||||
<Clock className="w-20 h-20 text-slate-500 mx-auto mb-6" />
|
||||
<h2 className="text-4xl font-black italic mb-4 uppercase">{now > endTime ? 'MISSION_COMPLETE' : 'BOARD_PAUSED'}</h2>
|
||||
<p className="text-slate-500 font-bold tracking-widest uppercase">{now > endTime ? 'The operation timeframe has concluded.' : 'Waiting for HQ clearance...'}</p>
|
||||
<h2 className="text-4xl font-black italic mb-4 uppercase">{now > endTime ? 'TIME IS UP' : 'BOARD_PAUSED'}</h2>
|
||||
<p className="text-slate-500 font-bold tracking-widest uppercase">{now > endTime ? 'THE EVENT HAS CONCLUDED' : 'Waiting for HQ clearance...'}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user