mirror of
https://github.com/System-End/My-website.git
synced 2026-04-19 18:35:13 +00:00
fix: resolve eslint errors and remove dead code
This commit is contained in:
parent
1cbb7845bd
commit
bcaf48b1a0
5 changed files with 555 additions and 711 deletions
420
src/App.tsx
420
src/App.tsx
|
|
@ -4,12 +4,6 @@ import { AuthProvider, useAuth } from "@/context/AuthContext";
|
|||
import Navbar from "@/components/Navbar";
|
||||
import AboutPage from "@/pages/AboutPage";
|
||||
import ProjectsPage from "@/pages/ProjectsPage";
|
||||
// import APCSPPage from "@/pages/APCSPPage";
|
||||
// import LoginPage from "@/pages/LoginPage";
|
||||
// import SystemPage from "@/pages/SystemPage";
|
||||
// import SystemStatus from "@/components/SystemStatus";
|
||||
// import SwitchNotification from "@/components/SwitchNotification";
|
||||
// import ProtectedRoute from "@/components/ProtectedRoute";
|
||||
import FoxGame from "@/games/fox-adventure/components/FoxGame";
|
||||
import ThemeToggle from "@/components/ThemeToggle";
|
||||
import EndOSBootAnimation from "@/components/EndOSBootAnimation";
|
||||
|
|
@ -18,290 +12,190 @@ import "@/styles/protofox-theme.css";
|
|||
|
||||
// EndOS animation control
|
||||
const useEndOSAnimation = () => {
|
||||
const [bootComplete, setBootComplete] = useState(false);
|
||||
// Using underscore prefix to indicate intentionally unused variable
|
||||
const [skipBoot, _setSkipBoot] = useState(() => {
|
||||
// Check for URL parameter that allows skipping the boot animation
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const skipParam = urlParams.get("skipBoot");
|
||||
const [bootComplete, setBootComplete] = useState(false);
|
||||
const [skipBoot] = useState(() => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const skipParam = urlParams.get("skipBoot");
|
||||
const sessionSeen =
|
||||
sessionStorage.getItem("endos-boot-complete") === "true";
|
||||
|
||||
// Also check if user has already seen the animation in this session
|
||||
const sessionSeen =
|
||||
sessionStorage.getItem("endos-boot-complete") === "true";
|
||||
return skipParam === "true" || sessionSeen;
|
||||
});
|
||||
|
||||
return skipParam === "true" || sessionSeen;
|
||||
});
|
||||
const handleBootComplete = () => {
|
||||
setBootComplete(true);
|
||||
sessionStorage.setItem("endos-boot-complete", "true");
|
||||
};
|
||||
|
||||
// Handle boot animation completion
|
||||
const handleBootComplete = () => {
|
||||
setBootComplete(true);
|
||||
sessionStorage.setItem("endos-boot-complete", "true");
|
||||
};
|
||||
|
||||
return { bootComplete, skipBoot, handleBootComplete };
|
||||
return { bootComplete, skipBoot, handleBootComplete };
|
||||
};
|
||||
|
||||
// AuthChecker component to access auth context inside the router
|
||||
const AuthChecker = ({ children }: { children: React.ReactNode }) => {
|
||||
const auth = useAuth();
|
||||
const [isStatusVisible, setIsStatusVisible] = useState(false);
|
||||
// Using underscore prefix for all unused state variables
|
||||
const [_showNotification, setShowNotification] = useState(false);
|
||||
const [_notificationType, setNotificationType] = useState<
|
||||
"switch" | "warning" | "notice"
|
||||
>("switch");
|
||||
const [_notificationMessage, setNotificationMessage] = useState("");
|
||||
const [_selectedAlter, setSelectedAlter] = useState("");
|
||||
const auth = useAuth();
|
||||
const [isStatusVisible, setIsStatusVisible] = useState(false);
|
||||
|
||||
// Toggle system status floating panel
|
||||
const toggleStatus = () => {
|
||||
setIsStatusVisible((prev) => !prev);
|
||||
};
|
||||
const toggleStatus = () => {
|
||||
setIsStatusVisible((prev) => !prev);
|
||||
};
|
||||
|
||||
// Simulate random switches for demo purposes
|
||||
useEffect(() => {
|
||||
if (!auth.isAuthenticated) return;
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
|
||||
// Every 5-15 minutes, show a switch notification
|
||||
const randomInterval =
|
||||
Math.floor(Math.random() * (15 - 5 + 1) + 5) * 60 * 1000;
|
||||
const interval = setInterval(() => {
|
||||
// 70% chance of switch, 20% chance of notice, 10% chance of warning
|
||||
const rand = Math.random();
|
||||
|
||||
if (rand < 0.7) {
|
||||
setNotificationType("switch");
|
||||
setSelectedAlter(""); // Random alter will be selected
|
||||
} else if (rand < 0.9) {
|
||||
setNotificationType("notice");
|
||||
setNotificationMessage("System communication active");
|
||||
} else {
|
||||
setNotificationType("warning");
|
||||
setNotificationMessage("System experiencing stress");
|
||||
}
|
||||
|
||||
setShowNotification(true);
|
||||
}, randomInterval);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [auth.isAuthenticated]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
|
||||
{/* Floating System Status for authenticated users */}
|
||||
{auth.isAuthenticated && (
|
||||
<>
|
||||
<div
|
||||
className={`fixed bottom-4 right-4 z-40 transition-transform duration-300 ${
|
||||
isStatusVisible
|
||||
? "translate-y-0"
|
||||
: "translate-y-[calc(100%-40px)]"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className="p-2 bg-background-secondary rounded-t-lg cursor-pointer flex justify-center items-center"
|
||||
onClick={toggleStatus}
|
||||
>
|
||||
<span className="text-xs font-medium">
|
||||
{isStatusVisible
|
||||
? "Hide System Status"
|
||||
: "System Status"}
|
||||
</span>
|
||||
</div>
|
||||
{/* <SystemStatus
|
||||
minimal={true}
|
||||
className="shadow-lg rounded-t-none w-[300px] max-w-[calc(100vw-2rem)]"
|
||||
/> */}
|
||||
</div>
|
||||
|
||||
{/* System Notifications */}
|
||||
{/* <SwitchNotification
|
||||
show={showNotification}
|
||||
onClose={() => setShowNotification(false)}
|
||||
alterName={selectedAlter}
|
||||
type={notificationType}
|
||||
message={notificationMessage}
|
||||
autoClose
|
||||
autoCloseDelay={5000}
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
{auth.isAuthenticated && (
|
||||
<div
|
||||
className={`fixed bottom-4 right-4 z-40 transition-transform duration-300 ${
|
||||
isStatusVisible ? "translate-y-0" : "translate-y-[calc(100%-40px)]"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className="p-2 bg-background-secondary rounded-t-lg cursor-pointer flex justify-center items-center"
|
||||
onClick={toggleStatus}
|
||||
>
|
||||
<span className="text-xs font-medium">
|
||||
{isStatusVisible ? "Hide System Status" : "System Status"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const App = () => {
|
||||
const [isGameActive, setIsGameActive] = useState(false);
|
||||
const [_showInitialSwitchDemo, setShowInitialSwitchDemo] = useState(false);
|
||||
const { bootComplete, skipBoot, handleBootComplete } = useEndOSAnimation();
|
||||
const [isGameActive, setIsGameActive] = useState(false);
|
||||
const { bootComplete, skipBoot, handleBootComplete } = useEndOSAnimation();
|
||||
|
||||
// Demo the switch notification after a delay
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setShowInitialSwitchDemo(true);
|
||||
useEffect(() => {
|
||||
// Konami code sequence
|
||||
const konamiCode = [
|
||||
"ArrowUp",
|
||||
"ArrowUp",
|
||||
"ArrowDown",
|
||||
"ArrowDown",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"b",
|
||||
"a",
|
||||
];
|
||||
let index = 0;
|
||||
|
||||
// Hide after 5 seconds
|
||||
setTimeout(() => {
|
||||
setShowInitialSwitchDemo(false);
|
||||
}, 5000);
|
||||
}, 10000);
|
||||
const handleKeydown = (event: KeyboardEvent) => {
|
||||
if (event.key === konamiCode[index]) {
|
||||
index++;
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
if (index === konamiCode.length) {
|
||||
setIsGameActive(true);
|
||||
console.log("Konami code activated!");
|
||||
}
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Konami code sequence
|
||||
const konamiCode = [
|
||||
"ArrowUp",
|
||||
"ArrowUp",
|
||||
"ArrowDown",
|
||||
"ArrowDown",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"b",
|
||||
"a",
|
||||
];
|
||||
let index = 0;
|
||||
window.addEventListener("keydown", handleKeydown);
|
||||
|
||||
const handleKeydown = (event: KeyboardEvent) => {
|
||||
// Check if the pressed key matches the next key in the sequence
|
||||
if (event.key === konamiCode[index]) {
|
||||
index++;
|
||||
return () => window.removeEventListener("keydown", handleKeydown);
|
||||
}, []);
|
||||
|
||||
// If the entire sequence is completed
|
||||
if (index === konamiCode.length) {
|
||||
setIsGameActive(true);
|
||||
// Optional: Play a sound or show a notification
|
||||
console.log("Konami code activated!");
|
||||
}
|
||||
} else {
|
||||
// Reset if a wrong key is pressed
|
||||
index = 0;
|
||||
}
|
||||
};
|
||||
return (
|
||||
<AuthProvider>
|
||||
{/* EndOS Boot Animation */}
|
||||
{!skipBoot && !bootComplete && (
|
||||
<EndOSBootAnimation onComplete={handleBootComplete} />
|
||||
)}
|
||||
|
||||
window.addEventListener("keydown", handleKeydown);
|
||||
|
||||
// Clean up the event listener on component unmount
|
||||
return () => window.removeEventListener("keydown", handleKeydown);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AuthProvider>
|
||||
{/* EndOS Boot Animation */}
|
||||
{!skipBoot && !bootComplete && (
|
||||
<EndOSBootAnimation onComplete={handleBootComplete} />
|
||||
)}
|
||||
|
||||
{/* Main Application - Only visible after boot animation completes */}
|
||||
{/* Main Application - Only visible after boot animation completes */}
|
||||
<div
|
||||
style={{
|
||||
visibility: bootComplete || skipBoot ? "visible" : "hidden",
|
||||
opacity: bootComplete || skipBoot ? 1 : 0,
|
||||
transition: "opacity 0.5s ease-in-out",
|
||||
}}
|
||||
>
|
||||
<Router>
|
||||
<AuthChecker>
|
||||
<div
|
||||
style={{
|
||||
visibility: bootComplete || skipBoot ? "visible" : "hidden",
|
||||
opacity: bootComplete || skipBoot ? 1 : 0,
|
||||
transition: "opacity 0.5s ease-in-out",
|
||||
}}
|
||||
className={`min-h-screen bg-background-primary ${isGameActive ? "game-active" : ""}`}
|
||||
>
|
||||
<Router>
|
||||
<AuthChecker>
|
||||
<div
|
||||
className={`min-h-screen bg-background-primary ${isGameActive ? "game-active" : ""}`}
|
||||
>
|
||||
{/* Background Logo */}
|
||||
<div className="fixed inset-0 z-behind pointer-events-none">
|
||||
<div className="absolute inset-0">
|
||||
<img
|
||||
src="/logo.jpg"
|
||||
alt="Background Logo"
|
||||
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] opacity-[0.03] blur-[2px]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* Background Logo */}
|
||||
<div className="fixed inset-0 z-behind pointer-events-none">
|
||||
<div className="absolute inset-0">
|
||||
<img
|
||||
src="/logo.jpg"
|
||||
alt="Background Logo"
|
||||
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] opacity-[0.03] blur-[2px]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="relative">
|
||||
<Navbar />
|
||||
{/* Main Content */}
|
||||
<div className="relative">
|
||||
<Navbar />
|
||||
|
||||
{/* Theme Toggle */}
|
||||
<div className="fixed top-20 right-4 z-30">
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
{/* Theme Toggle */}
|
||||
<div className="fixed top-20 right-4 z-30">
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
|
||||
<main className="content-wrapper section-spacing pb-20 animate-fade-in">
|
||||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={<AboutPage />}
|
||||
/>
|
||||
<Route
|
||||
path="/projects"
|
||||
element={<ProjectsPage />}
|
||||
/>
|
||||
{/* <Route path="/apcsp" element={<APCSPPage />} /> */}
|
||||
{/* <Route path="/login" element={<LoginPage />} />
|
||||
<Route
|
||||
path="/system"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<SystemPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/> */}
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
<div className="flex flex-col items-center justify-center min-h-[60vh] space-y-4">
|
||||
<h1 className="text-4xl font-bold text-glow">
|
||||
404: Page Not Found
|
||||
</h1>
|
||||
<p className="text-xl text-text-primary/80">
|
||||
This fox couldn't find
|
||||
what you're looking for.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</main>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="py-6 border-t border-accent-primary/10 text-center text-sm text-text-primary/60">
|
||||
<p>
|
||||
© 2023 - {new Date().getFullYear()}{" "}
|
||||
EndofTimee. All rights reserved.
|
||||
</p>
|
||||
<div className="flex justify-center items-center gap-2 mt-2">
|
||||
<span className="text-xs">
|
||||
Try the Konami code: ↑↑↓↓←→←→BA
|
||||
</span>
|
||||
<div className="bg-background-secondary px-2 py-0.5 rounded-full text-[10px] text-accent-primary">
|
||||
v0.9.5
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{/* Fox Game Overlay - Activated by Konami Code */}
|
||||
{isGameActive && (
|
||||
<>
|
||||
<FoxGame />
|
||||
<button
|
||||
onClick={() => setIsGameActive(false)}
|
||||
className="fixed top-4 right-4 z-[999] bg-red-500/80 hover:bg-red-500 px-3 py-1.5 rounded-md text-white text-sm font-medium transition-colors"
|
||||
>
|
||||
Exit Game
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
<main className="content-wrapper section-spacing pb-20 animate-fade-in">
|
||||
<Routes>
|
||||
<Route path="/" element={<AboutPage />} />
|
||||
<Route path="/projects" element={<ProjectsPage />} />
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
<div className="flex flex-col items-center justify-center min-h-[60vh] space-y-4">
|
||||
<h1 className="text-4xl font-bold text-glow">
|
||||
404: Page Not Found
|
||||
</h1>
|
||||
<p className="text-xl text-text-primary/80">
|
||||
This fox couldn't find what you're looking for.
|
||||
</p>
|
||||
</div>
|
||||
</AuthChecker>
|
||||
</Router>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</main>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="py-6 border-t border-accent-primary/10 text-center text-sm text-text-primary/60">
|
||||
<p>
|
||||
© 2023 - {new Date().getFullYear()} EndofTimee. All rights
|
||||
reserved.
|
||||
</p>
|
||||
<div className="flex justify-center items-center gap-2 mt-2">
|
||||
<span className="text-xs">
|
||||
Try the Konami code: ↑↑↓↓←→←→BA
|
||||
</span>
|
||||
<div className="bg-background-secondary px-2 py-0.5 rounded-full text-[10px] text-accent-primary">
|
||||
v0.9.5
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{/* Fox Game Overlay - Activated by Konami Code */}
|
||||
{isGameActive && (
|
||||
<>
|
||||
<FoxGame />
|
||||
<button
|
||||
onClick={() => setIsGameActive(false)}
|
||||
className="fixed top-4 right-4 z-[999] bg-red-500/80 hover:bg-red-500 px-3 py-1.5 rounded-md text-white text-sm font-medium transition-colors"
|
||||
>
|
||||
Exit Game
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</AuthProvider>
|
||||
);
|
||||
</AuthChecker>
|
||||
</Router>
|
||||
</div>
|
||||
</AuthProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
|
|
|||
|
|
@ -1,269 +1,221 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import "@/styles/EndOSBootAnimation.css";
|
||||
|
||||
interface EndOSBootAnimationProps {
|
||||
// Using underscores to mark unused props to avoid TypeScript errors
|
||||
_customLogo?: string;
|
||||
_customColors?: {
|
||||
primary?: string;
|
||||
secondary?: string;
|
||||
fox?: string;
|
||||
};
|
||||
onComplete?: () => void;
|
||||
skipAnimation?: boolean;
|
||||
onComplete?: () => void;
|
||||
skipAnimation?: boolean;
|
||||
}
|
||||
|
||||
const EndOSBootAnimation: React.FC<EndOSBootAnimationProps> = ({
|
||||
onComplete,
|
||||
skipAnimation = false,
|
||||
// Rename with underscores to indicate variables are intentionally unused
|
||||
_customLogo,
|
||||
_customColors,
|
||||
onComplete,
|
||||
skipAnimation = false,
|
||||
}) => {
|
||||
const [active, setActive] = useState(true);
|
||||
const [bootStage, setBootStage] = useState(0);
|
||||
const [showLogo, setShowLogo] = useState(false);
|
||||
const [bootComplete, setBootComplete] = useState(false);
|
||||
const [active, setActive] = useState(true);
|
||||
const [bootStage, setBootStage] = useState(0);
|
||||
const [showLogo, setShowLogo] = useState(false);
|
||||
const [bootComplete, setBootComplete] = useState(false);
|
||||
|
||||
// Boot sequence timing
|
||||
useEffect(() => {
|
||||
if (skipAnimation) {
|
||||
handleAnimationComplete();
|
||||
return;
|
||||
}
|
||||
const handleAnimationComplete = useCallback(() => {
|
||||
setActive(false);
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
}, [onComplete]);
|
||||
|
||||
// Initialize boot sequence with proper timing to prevent overlap
|
||||
const bootSequence = [
|
||||
{ stage: 1, delay: 1500 }, // Initial screen flicker
|
||||
{ stage: 2, delay: 3000 }, // BIOS check (longer time to read)
|
||||
{ stage: 3, delay: 3500 }, // System scan (longer for progress bar)
|
||||
{ stage: 4, delay: 3500 }, // Loading modules (allow time for animation)
|
||||
{ stage: 5, delay: 3500 }, // Fox protocols (allow time to read traits)
|
||||
{ stage: 6, delay: 3000 }, // Show logo (allow time to appreciate)
|
||||
{ stage: 7, delay: 3000 }, // Final activation (longer read time)
|
||||
{ stage: 8, delay: 2000 }, // Fade out
|
||||
];
|
||||
// Boot sequence timing
|
||||
useEffect(() => {
|
||||
if (skipAnimation) {
|
||||
handleAnimationComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
let timeout: any; // Using any instead of NodeJS.Timeout
|
||||
let currentIndex = 0;
|
||||
// Initialize boot sequence with proper timing to prevent overlap
|
||||
const bootSequence = [
|
||||
{ stage: 1, delay: 1500 }, // Initial screen flicker
|
||||
{ stage: 2, delay: 3000 }, // BIOS check (longer time to read)
|
||||
{ stage: 3, delay: 3500 }, // System scan (longer for progress bar)
|
||||
{ stage: 4, delay: 3500 }, // Loading modules (allow time for animation)
|
||||
{ stage: 5, delay: 3500 }, // Fox protocols (allow time to read traits)
|
||||
{ stage: 6, delay: 3000 }, // Show logo (allow time to appreciate)
|
||||
{ stage: 7, delay: 3000 }, // Final activation (longer read time)
|
||||
{ stage: 8, delay: 2000 }, // Fade out
|
||||
];
|
||||
|
||||
const runNextStage = () => {
|
||||
if (currentIndex < bootSequence.length) {
|
||||
const { stage, delay } = bootSequence[currentIndex];
|
||||
let timeout: ReturnType<typeof setTimeout>;
|
||||
let currentIndex = 0;
|
||||
|
||||
// Clean transition - clear ALL previous stages to prevent any background visibility
|
||||
document.querySelectorAll(".boot-stage").forEach((el) => {
|
||||
el.classList.remove("active");
|
||||
});
|
||||
const runNextStage = () => {
|
||||
if (currentIndex < bootSequence.length) {
|
||||
const { stage, delay } = bootSequence[currentIndex];
|
||||
|
||||
// Reset content visibility
|
||||
document.querySelectorAll(".boot-content").forEach((el) => {
|
||||
el.classList.remove("active");
|
||||
});
|
||||
// Clean transition - clear ALL previous stages to prevent any background visibility
|
||||
document.querySelectorAll(".boot-stage").forEach((el) => {
|
||||
el.classList.remove("active");
|
||||
});
|
||||
|
||||
// Short delay to allow for transition
|
||||
setTimeout(() => {
|
||||
// First ensure boot content is visible
|
||||
document.querySelectorAll(".boot-content").forEach((el) => {
|
||||
el.classList.add("active");
|
||||
});
|
||||
// Reset content visibility
|
||||
document.querySelectorAll(".boot-content").forEach((el) => {
|
||||
el.classList.remove("active");
|
||||
});
|
||||
|
||||
// Then activate the correct stage
|
||||
setBootStage(stage);
|
||||
// Short delay to allow for transition
|
||||
setTimeout(() => {
|
||||
// First ensure boot content is visible
|
||||
document.querySelectorAll(".boot-content").forEach((el) => {
|
||||
el.classList.add("active");
|
||||
});
|
||||
|
||||
if (stage === 6) {
|
||||
setShowLogo(true);
|
||||
} else if (stage === 7) {
|
||||
setBootComplete(true);
|
||||
}
|
||||
}, 300);
|
||||
// Then activate the correct stage
|
||||
setBootStage(stage);
|
||||
|
||||
currentIndex++;
|
||||
timeout = setTimeout(runNextStage, delay);
|
||||
} else {
|
||||
handleAnimationComplete();
|
||||
}
|
||||
};
|
||||
if (stage === 6) {
|
||||
setShowLogo(true);
|
||||
} else if (stage === 7) {
|
||||
setBootComplete(true);
|
||||
}
|
||||
}, 300);
|
||||
|
||||
// Start the sequence
|
||||
timeout = setTimeout(runNextStage, 500);
|
||||
|
||||
return () => {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
};
|
||||
}, [skipAnimation]);
|
||||
|
||||
const handleAnimationComplete = () => {
|
||||
setActive(false);
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
};
|
||||
|
||||
// Skip button click handler
|
||||
const handleSkip = () => {
|
||||
currentIndex++;
|
||||
timeout = setTimeout(runNextStage, delay);
|
||||
} else {
|
||||
handleAnimationComplete();
|
||||
}
|
||||
};
|
||||
|
||||
if (!active) return null;
|
||||
// Start the sequence
|
||||
timeout = setTimeout(runNextStage, 500);
|
||||
|
||||
return (
|
||||
<div className="endos-boot-container">
|
||||
{/* Accessibility */}
|
||||
<div className="visually-hidden">
|
||||
Website loading. EndOS boot sequence in progress.
|
||||
</div>
|
||||
return () => {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
};
|
||||
}, [skipAnimation, handleAnimationComplete]);
|
||||
|
||||
<div className="boot-scan-line"></div>
|
||||
// Skip button click handler
|
||||
const handleSkip = () => {
|
||||
handleAnimationComplete();
|
||||
};
|
||||
|
||||
<div className="boot-visor-frame">
|
||||
<div className="visor-left-ear"></div>
|
||||
<div className="visor-right-ear"></div>
|
||||
if (!active) return null;
|
||||
|
||||
<div className="boot-visor">
|
||||
<div className="visor-line top"></div>
|
||||
<div className="visor-line bottom"></div>
|
||||
return (
|
||||
<div className="endos-boot-container">
|
||||
{/* Accessibility */}
|
||||
<div className="visually-hidden">
|
||||
Website loading. EndOS boot sequence in progress.
|
||||
</div>
|
||||
|
||||
{/* Boot Sequence Content */}
|
||||
<div className={`boot-content`}>
|
||||
{/* BIOS Check */}
|
||||
<div
|
||||
className={`boot-stage bios ${bootStage === 2 ? "active" : ""}`}
|
||||
>
|
||||
<div className="bios-header">END_OS BIOS v2.5</div>
|
||||
<div className="boot-text-line">
|
||||
Initializing hardware...
|
||||
</div>
|
||||
<div className="boot-text-line">
|
||||
CPU: ProtoCore i9 @ 4.7GHz
|
||||
</div>
|
||||
<div className="boot-text-line">
|
||||
Memory: 16GB NeuralRAM
|
||||
</div>
|
||||
<div className="boot-text-line">
|
||||
Checking system integrity... OK
|
||||
</div>
|
||||
<div className="boot-text-line">
|
||||
Starting boot sequence...
|
||||
</div>
|
||||
</div>
|
||||
<div className="boot-scan-line"></div>
|
||||
|
||||
{/* System Scan */}
|
||||
<div
|
||||
className={`boot-stage scan ${bootStage === 3 ? "active" : ""}`}
|
||||
>
|
||||
<div className="scan-header">SYSTEM SCAN</div>
|
||||
<div className="scan-progress-container">
|
||||
<div className="scan-progress-bar"></div>
|
||||
</div>
|
||||
<div className="scan-detail">
|
||||
Checking vital systems...
|
||||
</div>
|
||||
<div className="scan-detail">
|
||||
Initializing neural pathways...
|
||||
</div>
|
||||
<div className="scan-detail">
|
||||
Activating sensory modules...
|
||||
</div>
|
||||
<div className="scan-detail">
|
||||
All systems nominal
|
||||
</div>
|
||||
</div>
|
||||
<div className="boot-visor-frame">
|
||||
<div className="visor-left-ear"></div>
|
||||
<div className="visor-right-ear"></div>
|
||||
|
||||
{/* Module Loading */}
|
||||
<div
|
||||
className={`boot-stage modules ${bootStage === 4 ? "active" : ""}`}
|
||||
>
|
||||
<div className="module-header">
|
||||
LOADING CORE MODULES
|
||||
</div>
|
||||
<div className="modules-grid">
|
||||
<div className="module-item">
|
||||
<div className="module-icon"></div>
|
||||
<div className="module-name">
|
||||
ProtogenCore
|
||||
</div>
|
||||
</div>
|
||||
<div className="module-item">
|
||||
<div className="module-icon"></div>
|
||||
<div className="module-name">NeuralNet</div>
|
||||
</div>
|
||||
<div className="module-item">
|
||||
<div className="module-icon"></div>
|
||||
<div className="module-name">
|
||||
VisorDisplay
|
||||
</div>
|
||||
</div>
|
||||
<div className="module-item">
|
||||
<div className="module-icon"></div>
|
||||
<div className="module-name">FoxTraits</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="boot-visor">
|
||||
<div className="visor-line top"></div>
|
||||
<div className="visor-line bottom"></div>
|
||||
|
||||
{/* Fox Protocol */}
|
||||
<div
|
||||
className={`boot-stage fox-protocol ${bootStage === 5 ? "active" : ""}`}
|
||||
>
|
||||
<div className="fox-header">
|
||||
ACTIVATING FOX PROTOCOLS
|
||||
</div>
|
||||
<div className="fox-trait">
|
||||
Fluffy tail module: Online
|
||||
</div>
|
||||
<div className="fox-trait">
|
||||
Fox ears: Calibrated
|
||||
</div>
|
||||
<div className="fox-trait">
|
||||
Cuteness factor: Nonexistent
|
||||
</div>
|
||||
<div className="fox-trait">
|
||||
Mischief subroutines: Loaded
|
||||
</div>
|
||||
<div className="fox-trait">
|
||||
ProtoFox integration: Complete
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Logo Display */}
|
||||
<div
|
||||
className={`boot-stage logo-display ${bootStage === 6 && showLogo ? "active" : ""}`}
|
||||
>
|
||||
<div className="endos-logo">
|
||||
<span className="logo-end">End</span>
|
||||
<span className="logo-os">OS</span>
|
||||
</div>
|
||||
<div className="logo-subtitle">
|
||||
ProtoFox Operating System
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* System Ready */}
|
||||
<div
|
||||
className={`boot-stage system-ready ${bootStage === 7 && bootComplete ? "active" : ""}`}
|
||||
>
|
||||
<div className="ready-status">SYSTEM ACTIVATED</div>
|
||||
<div className="welcome-message">
|
||||
Welcome back, ProtoFox
|
||||
</div>
|
||||
<div className="boot-complete-message">
|
||||
EndOS v1.0 is fully operational
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Skip button - More prominent and always visible */}
|
||||
<button
|
||||
className="skip-button"
|
||||
onClick={handleSkip}
|
||||
aria-label="Skip boot animation"
|
||||
{/* Boot Sequence Content */}
|
||||
<div className={`boot-content`}>
|
||||
{/* BIOS Check */}
|
||||
<div
|
||||
className={`boot-stage bios ${bootStage === 2 ? "active" : ""}`}
|
||||
>
|
||||
SKIP BOOT SEQUENCE
|
||||
</button>
|
||||
<div className="bios-header">END_OS BIOS v2.5</div>
|
||||
<div className="boot-text-line">Initializing hardware...</div>
|
||||
<div className="boot-text-line">CPU: ProtoCore i9 @ 4.7GHz</div>
|
||||
<div className="boot-text-line">Memory: 16GB NeuralRAM</div>
|
||||
<div className="boot-text-line">
|
||||
Checking system integrity... OK
|
||||
</div>
|
||||
<div className="boot-text-line">Starting boot sequence...</div>
|
||||
</div>
|
||||
|
||||
{/* System Scan */}
|
||||
<div
|
||||
className={`boot-stage scan ${bootStage === 3 ? "active" : ""}`}
|
||||
>
|
||||
<div className="scan-header">SYSTEM SCAN</div>
|
||||
<div className="scan-progress-container">
|
||||
<div className="scan-progress-bar"></div>
|
||||
</div>
|
||||
<div className="scan-detail">Checking vital systems...</div>
|
||||
<div className="scan-detail">Initializing neural pathways...</div>
|
||||
<div className="scan-detail">Activating sensory modules...</div>
|
||||
<div className="scan-detail">All systems nominal</div>
|
||||
</div>
|
||||
|
||||
{/* Module Loading */}
|
||||
<div
|
||||
className={`boot-stage modules ${bootStage === 4 ? "active" : ""}`}
|
||||
>
|
||||
<div className="module-header">LOADING CORE MODULES</div>
|
||||
<div className="modules-grid">
|
||||
<div className="module-item">
|
||||
<div className="module-icon"></div>
|
||||
<div className="module-name">ProtogenCore</div>
|
||||
</div>
|
||||
<div className="module-item">
|
||||
<div className="module-icon"></div>
|
||||
<div className="module-name">NeuralNet</div>
|
||||
</div>
|
||||
<div className="module-item">
|
||||
<div className="module-icon"></div>
|
||||
<div className="module-name">VisorDisplay</div>
|
||||
</div>
|
||||
<div className="module-item">
|
||||
<div className="module-icon"></div>
|
||||
<div className="module-name">FoxTraits</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Fox Protocol */}
|
||||
<div
|
||||
className={`boot-stage fox-protocol ${bootStage === 5 ? "active" : ""}`}
|
||||
>
|
||||
<div className="fox-header">ACTIVATING FOX PROTOCOLS</div>
|
||||
<div className="fox-trait">Fluffy tail module: Online</div>
|
||||
<div className="fox-trait">Fox ears: Calibrated</div>
|
||||
<div className="fox-trait">Cuteness factor: Nonexistent</div>
|
||||
<div className="fox-trait">Mischief subroutines: Loaded</div>
|
||||
<div className="fox-trait">ProtoFox integration: Complete</div>
|
||||
</div>
|
||||
|
||||
{/* Logo Display */}
|
||||
<div
|
||||
className={`boot-stage logo-display ${bootStage === 6 && showLogo ? "active" : ""}`}
|
||||
>
|
||||
<div className="endos-logo">
|
||||
<span className="logo-end">End</span>
|
||||
<span className="logo-os">OS</span>
|
||||
</div>
|
||||
<div className="logo-subtitle">ProtoFox Operating System</div>
|
||||
</div>
|
||||
|
||||
{/* System Ready */}
|
||||
<div
|
||||
className={`boot-stage system-ready ${bootStage === 7 && bootComplete ? "active" : ""}`}
|
||||
>
|
||||
<div className="ready-status">SYSTEM ACTIVATED</div>
|
||||
<div className="welcome-message">Welcome back, ProtoFox</div>
|
||||
<div className="boot-complete-message">
|
||||
EndOS v1.0 is fully operational
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
</div>
|
||||
|
||||
{/* Skip button - More prominent and always visible */}
|
||||
<button
|
||||
className="skip-button"
|
||||
onClick={handleSkip}
|
||||
aria-label="Skip boot animation"
|
||||
>
|
||||
SKIP BOOT SEQUENCE
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EndOSBootAnimation;
|
||||
|
|
|
|||
|
|
@ -1,177 +1,175 @@
|
|||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
} from "react";
|
||||
|
||||
interface SystemMember {
|
||||
id: string;
|
||||
name: string;
|
||||
role: string;
|
||||
color?: string;
|
||||
id: string;
|
||||
name: string;
|
||||
role: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
interface SystemState {
|
||||
safetyLevel: "safe" | "unsafe" | "sorta-safe" | "unknown";
|
||||
mentalState:
|
||||
| "ok"
|
||||
| "bad"
|
||||
| "very-bad"
|
||||
| "panic"
|
||||
| "spiraling"
|
||||
| "unstable"
|
||||
| "delusional";
|
||||
frontingStatus: "single" | "co-fronting" | "switching" | "unknown";
|
||||
currentFronters: SystemMember[];
|
||||
safetyLevel: "safe" | "unsafe" | "sorta-safe" | "unknown";
|
||||
mentalState:
|
||||
| "ok"
|
||||
| "bad"
|
||||
| "very-bad"
|
||||
| "panic"
|
||||
| "spiraling"
|
||||
| "unstable"
|
||||
| "delusional";
|
||||
frontingStatus: "single" | "co-fronting" | "switching" | "unknown";
|
||||
currentFronters: SystemMember[];
|
||||
}
|
||||
|
||||
interface AuthContextType {
|
||||
isAuthenticated: boolean;
|
||||
username: string | null;
|
||||
systemState: SystemState | null;
|
||||
login: (username: string, password: string) => Promise<boolean>;
|
||||
logout: () => void;
|
||||
updateSystemState: (newState: Partial<SystemState>) => void;
|
||||
isAuthenticated: boolean;
|
||||
username: string | null;
|
||||
systemState: SystemState | null;
|
||||
login: (username: string, password: string) => Promise<boolean>;
|
||||
logout: () => void;
|
||||
updateSystemState: (newState: Partial<SystemState>) => void;
|
||||
}
|
||||
|
||||
// System members data
|
||||
const systemMembers: SystemMember[] = [
|
||||
{ id: "1", name: "Aurora", role: "Host", color: "#9d4edd" },
|
||||
{ id: "2", name: "Alex", role: "Younger", color: "#4ea8de" },
|
||||
{ id: "3", name: "Psy", role: "Protector", color: "#5e548e" },
|
||||
{ id: "4", name: "Xander", role: "Caretaker", color: "#219ebc" },
|
||||
{ id: "5", name: "Unknown", role: "Fragment", color: "#6c757d" },
|
||||
{ id: "6", name: "The thing", role: "Persecutor", color: "#e63946" },
|
||||
{ id: "7", name: "Unknown 2", role: "Fragment", color: "#6c757d" },
|
||||
{ id: "1", name: "Aurora", role: "Host", color: "#9d4edd" },
|
||||
{ id: "2", name: "Alex", role: "Younger", color: "#4ea8de" },
|
||||
{ id: "3", name: "Psy", role: "Protector", color: "#5e548e" },
|
||||
{ id: "4", name: "Xander", role: "Caretaker", color: "#219ebc" },
|
||||
{ id: "5", name: "Unknown", role: "Fragment", color: "#6c757d" },
|
||||
{ id: "6", name: "The thing", role: "Persecutor", color: "#e63946" },
|
||||
{ id: "7", name: "Unknown 2", role: "Fragment", color: "#6c757d" },
|
||||
];
|
||||
|
||||
// Creating the context with a default value of null
|
||||
const AuthContext = createContext<AuthContextType | null>(null);
|
||||
|
||||
export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
// Initialize authentication state from localStorage if available
|
||||
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(() => {
|
||||
const stored = localStorage.getItem("isAuthenticated");
|
||||
return stored === "true";
|
||||
});
|
||||
// Initialize authentication state from localStorage if available
|
||||
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(() => {
|
||||
const stored = localStorage.getItem("isAuthenticated");
|
||||
return stored === "true";
|
||||
});
|
||||
|
||||
const [username, setUsername] = useState<string | null>(() => {
|
||||
return localStorage.getItem("username");
|
||||
});
|
||||
const [username, setUsername] = useState<string | null>(() => {
|
||||
return localStorage.getItem("username");
|
||||
});
|
||||
|
||||
// Initialize system state from localStorage or set defaults
|
||||
const [systemState, setSystemState] = useState<SystemState | null>(() => {
|
||||
const stored = localStorage.getItem("systemState");
|
||||
if (stored && isAuthenticated) {
|
||||
return JSON.parse(stored);
|
||||
// Initialize system state from localStorage or set defaults
|
||||
const [systemState, setSystemState] = useState<SystemState | null>(() => {
|
||||
const stored = localStorage.getItem("systemState");
|
||||
if (stored && isAuthenticated) {
|
||||
return JSON.parse(stored);
|
||||
}
|
||||
return isAuthenticated
|
||||
? {
|
||||
safetyLevel: "safe",
|
||||
mentalState: "ok",
|
||||
frontingStatus: "single",
|
||||
currentFronters: [systemMembers[0]], // Default to Aurora as fronter
|
||||
}
|
||||
return isAuthenticated
|
||||
? {
|
||||
safetyLevel: "safe",
|
||||
mentalState: "ok",
|
||||
frontingStatus: "single",
|
||||
currentFronters: [systemMembers[0]], // Default to Aurora as fronter
|
||||
}
|
||||
: null;
|
||||
});
|
||||
: null;
|
||||
});
|
||||
|
||||
// Update localStorage when auth state changes
|
||||
useEffect(() => {
|
||||
localStorage.setItem("isAuthenticated", isAuthenticated.toString());
|
||||
if (username) {
|
||||
localStorage.setItem("username", username);
|
||||
} else {
|
||||
localStorage.removeItem("username");
|
||||
}
|
||||
// Sync auth state to localStorage
|
||||
useEffect(() => {
|
||||
localStorage.setItem("isAuthenticated", isAuthenticated.toString());
|
||||
if (username) {
|
||||
localStorage.setItem("username", username);
|
||||
} else {
|
||||
localStorage.removeItem("username");
|
||||
}
|
||||
}, [isAuthenticated, username]);
|
||||
|
||||
// If logged out, clear system state
|
||||
if (!isAuthenticated) {
|
||||
localStorage.removeItem("systemState");
|
||||
setSystemState(null);
|
||||
} else if (systemState) {
|
||||
localStorage.setItem("systemState", JSON.stringify(systemState));
|
||||
}
|
||||
}, [isAuthenticated, username, systemState]);
|
||||
// Sync system state to localStorage
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) {
|
||||
localStorage.removeItem("systemState");
|
||||
} else if (systemState) {
|
||||
localStorage.setItem("systemState", JSON.stringify(systemState));
|
||||
}
|
||||
}, [isAuthenticated, systemState]);
|
||||
|
||||
const login = async (username: string, password: string) => {
|
||||
// For security, add a slight delay to prevent rapid brute force attempts
|
||||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||||
const login = async (username: string, password: string) => {
|
||||
// For security, add a slight delay to prevent rapid brute force attempts
|
||||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||||
|
||||
// We use credential verification with multiple allowed passwords for different contexts
|
||||
const validCredentials = [{ user: "system", pass: "." }];
|
||||
// We use credential verification with multiple allowed passwords for different contexts
|
||||
const validCredentials = [{ user: "system", pass: "." }];
|
||||
|
||||
const isValid = validCredentials.some(
|
||||
(cred) =>
|
||||
cred.user === username.toLowerCase() && cred.pass === password,
|
||||
);
|
||||
|
||||
if (isValid) {
|
||||
setIsAuthenticated(true);
|
||||
setUsername(username);
|
||||
|
||||
// Initialize system state on login
|
||||
const initialState: SystemState = {
|
||||
safetyLevel: "safe",
|
||||
mentalState: "ok",
|
||||
frontingStatus: "single",
|
||||
currentFronters: [systemMembers[0]],
|
||||
};
|
||||
|
||||
setSystemState(initialState);
|
||||
localStorage.setItem("systemState", JSON.stringify(initialState));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
// Add a short delay for better UX
|
||||
setTimeout(() => {
|
||||
setIsAuthenticated(false);
|
||||
setUsername(null);
|
||||
setSystemState(null);
|
||||
|
||||
// Clear sensitive data from localStorage
|
||||
localStorage.removeItem("systemState");
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const updateSystemState = (newState: Partial<SystemState>) => {
|
||||
if (!systemState) return;
|
||||
|
||||
const updatedState = { ...systemState, ...newState };
|
||||
setSystemState(updatedState);
|
||||
localStorage.setItem("systemState", JSON.stringify(updatedState));
|
||||
};
|
||||
|
||||
// Construct the context value
|
||||
const contextValue: AuthContextType = {
|
||||
isAuthenticated,
|
||||
username,
|
||||
systemState,
|
||||
login,
|
||||
logout,
|
||||
updateSystemState,
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
const isValid = validCredentials.some(
|
||||
(cred) => cred.user === username.toLowerCase() && cred.pass === password,
|
||||
);
|
||||
|
||||
if (isValid) {
|
||||
setIsAuthenticated(true);
|
||||
setUsername(username);
|
||||
|
||||
// Initialize system state on login
|
||||
const initialState: SystemState = {
|
||||
safetyLevel: "safe",
|
||||
mentalState: "ok",
|
||||
frontingStatus: "single",
|
||||
currentFronters: [systemMembers[0]],
|
||||
};
|
||||
|
||||
setSystemState(initialState);
|
||||
localStorage.setItem("systemState", JSON.stringify(initialState));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
// Add a short delay for better UX
|
||||
setTimeout(() => {
|
||||
setIsAuthenticated(false);
|
||||
setUsername(null);
|
||||
setSystemState(null);
|
||||
|
||||
// Clear sensitive data from localStorage
|
||||
localStorage.removeItem("systemState");
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const updateSystemState = (newState: Partial<SystemState>) => {
|
||||
if (!systemState) return;
|
||||
|
||||
const updatedState = { ...systemState, ...newState };
|
||||
setSystemState(updatedState);
|
||||
localStorage.setItem("systemState", JSON.stringify(updatedState));
|
||||
};
|
||||
|
||||
// Construct the context value
|
||||
const contextValue: AuthContextType = {
|
||||
isAuthenticated,
|
||||
username,
|
||||
systemState,
|
||||
login,
|
||||
logout,
|
||||
updateSystemState,
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
// Custom hook for easier context consumption
|
||||
export const useAuth = () => {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error("useAuth must be used within an AuthProvider");
|
||||
}
|
||||
return context;
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error("useAuth must be used within an AuthProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
// Export system members data for use in other components
|
||||
|
|
|
|||
|
|
@ -1,71 +1,69 @@
|
|||
import { Gamepad2, Code, Music } from "lucide-react";
|
||||
import { useState, useEffect } from "react";
|
||||
import FoxCard from "@/components/FoxCard";
|
||||
import MusicDisplay from "@/components/MusicDisplay";
|
||||
import { calculatePreciseAge } from "@/utils/dateUtils";
|
||||
|
||||
const AboutPage = () => {
|
||||
// const [age, setAge] = useState(calculatePreciseAge(new Date("date")));
|
||||
// const [age, setAge] = useState(calculatePreciseAge(new Date("date")));
|
||||
|
||||
// useEffect(() => {
|
||||
// const interval = setInterval(() => {
|
||||
// setAge(calculatePreciseAge(new Date("date")));
|
||||
// }, 50);
|
||||
// useEffect(() => {
|
||||
// const interval = setInterval(() => {
|
||||
// setAge(calculatePreciseAge(new Date("date")));
|
||||
// }, 50);
|
||||
|
||||
// return () => clearInterval(interval);
|
||||
// }, []);
|
||||
// return () => clearInterval(interval);
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<div className="page-container">
|
||||
<FoxCard className="header-card">
|
||||
<h1 className="text-glow">About Me</h1>
|
||||
<p className="text-gradient">
|
||||
End • They/It/She • Programmer & Streamer
|
||||
</p>
|
||||
</FoxCard>
|
||||
return (
|
||||
<div className="page-container">
|
||||
<FoxCard className="header-card">
|
||||
<h1 className="text-glow">About Me</h1>
|
||||
<p className="text-gradient">
|
||||
End • They/It/She • Programmer & Streamer
|
||||
</p>
|
||||
</FoxCard>
|
||||
|
||||
<div className="content-grid">
|
||||
<FoxCard>
|
||||
<div className="flex items-center gap-4">
|
||||
<Code size={24} className="text-accent-primary" />
|
||||
<h2>Tech Interests</h2>
|
||||
</div>
|
||||
<ul className="interest-list">
|
||||
<li>Programming & Development</li>
|
||||
<li>Robotics & Hardware</li>
|
||||
<li>Cybersecurity</li>
|
||||
</ul>
|
||||
</FoxCard>
|
||||
<div className="content-grid">
|
||||
<FoxCard>
|
||||
<div className="flex items-center gap-4">
|
||||
<Code size={24} className="text-accent-primary" />
|
||||
<h2>Tech Interests</h2>
|
||||
</div>
|
||||
<ul className="interest-list">
|
||||
<li>Programming & Development</li>
|
||||
<li>Robotics & Hardware</li>
|
||||
<li>Cybersecurity</li>
|
||||
</ul>
|
||||
</FoxCard>
|
||||
|
||||
<FoxCard>
|
||||
<div className="flex items-center gap-4">
|
||||
<Gamepad2 size={24} className="text-accent-primary" />
|
||||
<h2>Streaming</h2>
|
||||
</div>
|
||||
<p>
|
||||
Find me on{" "}
|
||||
<a
|
||||
href="https://twitch.tv/EndofTimee"
|
||||
className="text-accent-neon hover:text-glow"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Twitch
|
||||
</a>{" "}
|
||||
playing FiveM and other games!
|
||||
</p>
|
||||
</FoxCard>
|
||||
<FoxCard>
|
||||
<div className="flex items-center gap-4">
|
||||
<Gamepad2 size={24} className="text-accent-primary" />
|
||||
<h2>Streaming</h2>
|
||||
</div>
|
||||
<p>
|
||||
Find me on{" "}
|
||||
<a
|
||||
href="https://twitch.tv/EndofTimee"
|
||||
className="text-accent-neon hover:text-glow"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Twitch
|
||||
</a>{" "}
|
||||
playing FiveM and other games!
|
||||
</p>
|
||||
</FoxCard>
|
||||
|
||||
<FoxCard>
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<Music size={24} className="text-accent-primary" />
|
||||
<h2>Music</h2>
|
||||
</div>
|
||||
<MusicDisplay />
|
||||
</FoxCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
<FoxCard>
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<Music size={24} className="text-accent-primary" />
|
||||
<h2>Music</h2>
|
||||
</div>
|
||||
<MusicDisplay />
|
||||
</FoxCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutPage;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
const reportWebVitals = (onPerfEntry?: (metric: any) => void): void => {
|
||||
if (onPerfEntry && typeof onPerfEntry === "function") {
|
||||
import("web-vitals")
|
||||
.then((vitals) => {
|
||||
const { onCLS, onFID, onFCP, onLCP, onTTFB } = vitals;
|
||||
onCLS(onPerfEntry);
|
||||
onFID(onPerfEntry);
|
||||
onFCP(onPerfEntry);
|
||||
onLCP(onPerfEntry);
|
||||
onTTFB(onPerfEntry);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error loading web-vitals:", error);
|
||||
});
|
||||
}
|
||||
import type { Metric } from "web-vitals";
|
||||
|
||||
const reportWebVitals = (onPerfEntry?: (metric: Metric) => void): void => {
|
||||
if (onPerfEntry && typeof onPerfEntry === "function") {
|
||||
import("web-vitals")
|
||||
.then((vitals) => {
|
||||
const { onCLS, onFID, onFCP, onLCP, onTTFB } = vitals;
|
||||
onCLS(onPerfEntry);
|
||||
onFID(onPerfEntry);
|
||||
onFCP(onPerfEntry);
|
||||
onLCP(onPerfEntry);
|
||||
onTTFB(onPerfEntry);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error loading web-vitals:", error);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue