mirror of
https://github.com/JorySeverijnse/ui-fixer-supreme.git
synced 2026-01-29 23:38:36 +00:00
149 lines
6.0 KiB
TypeScript
149 lines
6.0 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import GlitchText from './GlitchText';
|
|
|
|
// Hacker-themed questions that any human would know
|
|
const QUESTIONS = [
|
|
{ q: "What key do you press to open a terminal? (Hint: between D and G)", answers: ["f", "f key"] },
|
|
{ q: "Complete: The Matrix has you, ___", answers: ["neo"] },
|
|
{ q: "What does 'www' stand for in a URL?", answers: ["world wide web", "worldwideweb"] },
|
|
{ q: "What color is the Matrix rain?", answers: ["green"] },
|
|
{ q: "What does 'ctrl+c' do?", answers: ["copy", "cancel", "stop", "interrupt"] },
|
|
{ q: "What number comes after 0 in binary?", answers: ["1", "one"] },
|
|
{ q: "What does 'IP' stand for in networking?", answers: ["internet protocol"] },
|
|
{ q: "What key exits most programs? (3 letters)", answers: ["esc", "escape"] },
|
|
{ q: "Red pill or blue pill - which reveals the truth?", answers: ["red", "red pill"] },
|
|
{ q: "What symbol starts most terminal commands?", answers: ["$", "/", ">", "dollar", "slash"] },
|
|
{ q: "What does 'USB' stand for?", answers: ["universal serial bus"] },
|
|
{ q: "What is localhost's IP address?", answers: ["127.0.0.1", "localhost"] },
|
|
{ q: "Complete: Hello, _____ (classic first program output)", answers: ["world"] },
|
|
{ q: "What animal is Linux's mascot?", answers: ["penguin", "tux"] },
|
|
{ q: "What does 'CPU' stand for?", answers: ["central processing unit"] },
|
|
];
|
|
|
|
const BYPASS_KEY = 'bypass-human-check';
|
|
const VERIFIED_KEY = 'human-verified';
|
|
|
|
interface HumanVerificationProps {
|
|
onVerified: () => void;
|
|
}
|
|
|
|
const HumanVerification = ({ onVerified }: HumanVerificationProps) => {
|
|
const [question] = useState(() => QUESTIONS[Math.floor(Math.random() * QUESTIONS.length)]);
|
|
const [answer, setAnswer] = useState('');
|
|
const [error, setError] = useState(false);
|
|
const [showHint, setShowHint] = useState(false);
|
|
|
|
// Check for bypass in URL
|
|
useEffect(() => {
|
|
const params = new URLSearchParams(window.location.search);
|
|
if (params.has(BYPASS_KEY) || window.location.pathname.includes(BYPASS_KEY)) {
|
|
localStorage.setItem(VERIFIED_KEY, 'true');
|
|
onVerified();
|
|
}
|
|
}, [onVerified]);
|
|
|
|
const handleSubmit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
const normalizedAnswer = answer.toLowerCase().trim();
|
|
|
|
if (question.answers.some(a => normalizedAnswer === a.toLowerCase())) {
|
|
localStorage.setItem(VERIFIED_KEY, 'true');
|
|
onVerified();
|
|
} else {
|
|
setError(true);
|
|
setShowHint(true);
|
|
setTimeout(() => setError(false), 500);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
className="fixed inset-0 z-[100] bg-background flex items-center justify-center p-4"
|
|
>
|
|
<div className="max-w-md w-full">
|
|
<motion.div
|
|
initial={{ scale: 0.9, opacity: 0 }}
|
|
animate={{ scale: 1, opacity: 1 }}
|
|
transition={{ delay: 0.2 }}
|
|
className="border-2 border-primary box-glow p-6 bg-background"
|
|
>
|
|
{/* ASCII Art Header */}
|
|
<pre className="font-mono text-[8px] sm:text-[10px] text-primary text-center mb-4 leading-tight">
|
|
{`╔═══════════════════════════════════════╗
|
|
║ HUMAN VERIFICATION REQUIRED ║
|
|
╚═══════════════════════════════════════╝`}
|
|
</pre>
|
|
|
|
<div className="text-center mb-6">
|
|
<GlitchText
|
|
text="ACCESS CONTROL"
|
|
className="font-minecraft text-xl text-primary text-glow-strong"
|
|
/>
|
|
<p className="font-pixel text-xs text-foreground/60 mt-2">
|
|
Prove you are human to continue
|
|
</p>
|
|
</div>
|
|
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
<div className="border border-primary/30 p-4 bg-background/50">
|
|
<p className="font-pixel text-[10px] text-foreground/60 mb-2">> QUERY:</p>
|
|
<p className="font-minecraft text-sm text-primary">{question.q}</p>
|
|
</div>
|
|
|
|
<div>
|
|
<input
|
|
type="text"
|
|
value={answer}
|
|
onChange={(e) => setAnswer(e.target.value)}
|
|
placeholder="> Enter response..."
|
|
autoFocus
|
|
className={`w-full bg-background border-2 ${
|
|
error ? 'border-destructive animate-pulse' : 'border-primary/50'
|
|
} p-3 font-pixel text-sm text-foreground placeholder:text-foreground/30 focus:outline-none focus:border-primary transition-colors`}
|
|
/>
|
|
</div>
|
|
|
|
<AnimatePresence>
|
|
{showHint && (
|
|
<motion.p
|
|
initial={{ opacity: 0, y: -10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0 }}
|
|
className="font-pixel text-[10px] text-destructive"
|
|
>
|
|
ERROR: Invalid response. Retry required.
|
|
</motion.p>
|
|
)}
|
|
</AnimatePresence>
|
|
|
|
<button
|
|
type="submit"
|
|
className="w-full font-minecraft text-sm py-3 border-2 border-primary bg-primary/20 text-primary hover:bg-primary/40 transition-all duration-300 box-glow"
|
|
>
|
|
EXECUTE
|
|
</button>
|
|
</form>
|
|
|
|
<div className="mt-6 pt-4 border-t border-primary/20">
|
|
<p className="font-pixel text-[8px] text-foreground/30 text-center">
|
|
// Anti-bot verification protocol v1.0
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Decorative terminal lines */}
|
|
<div className="mt-4 font-mono text-[10px] text-primary/50">
|
|
<p>> Awaiting human verification...</p>
|
|
<p className="animate-pulse">> _</p>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
export default HumanVerification;
|
|
export { VERIFIED_KEY, BYPASS_KEY };
|