Skip to content

Commit a88de00

Browse files
Add files via upload
1 parent 78075e1 commit a88de00

40 files changed

+8596
-0
lines changed

src/App.css

Lines changed: 613 additions & 0 deletions
Large diffs are not rendered by default.

src/App.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import './App.css';
2+
import React, { useState } from 'react';
3+
import { BrowserRouter as Router, Routes, Route, Link, useLocation, useNavigate } from 'react-router-dom';
4+
import Home from './components/Home';
5+
import Services from './components/Services';
6+
import About from './components/About';
7+
import Contact from './components/Contact';
8+
import Blog from './components/Blog';
9+
import Auth from './components/Auth';
10+
import User from './components/User';
11+
import Admin from './components/Admin';
12+
import UserDropdown from './components/UserDropdown';
13+
import techbloggerLogo from '../src/techblogger.png';
14+
15+
// Logout component
16+
function Logout() {
17+
const navigate = useNavigate();
18+
19+
React.useEffect(() => {
20+
// Clear authentication data
21+
localStorage.removeItem('username');
22+
23+
// Redirect to home page
24+
navigate('/', { replace: true });
25+
}, [navigate]);
26+
27+
return (
28+
<div style={{
29+
display: 'flex',
30+
justifyContent: 'center',
31+
alignItems: 'center',
32+
height: '100vh',
33+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
34+
color: 'white'
35+
}}>
36+
<div style={{ textAlign: 'center' }}>
37+
<h2>Logging out...</h2>
38+
<p>You have been successfully logged out.</p>
39+
</div>
40+
</div>
41+
);
42+
}
43+
44+
function AnimatedMain() {
45+
const location = useLocation();
46+
const [animate, setAnimate] = useState(true);
47+
48+
React.useEffect(() => {
49+
setAnimate(false);
50+
const timeout = setTimeout(() => setAnimate(true), 10);
51+
return () => clearTimeout(timeout);
52+
}, [location.pathname]);
53+
54+
return (
55+
<main className={animate ? 'route-fade-in' : ''}>
56+
<header className="header-container">
57+
<div className="logo-container">
58+
<a href="/"><img src={techbloggerLogo} alt="Tech Blogger Logo" className="logo-img" /></a>
59+
</div>
60+
<nav className="navbar">
61+
<ul className="nav-menu">
62+
<li><Link to="/">Home</Link></li>
63+
<li><Link to="/services">Services</Link></li>
64+
<li><Link to="/about">About Us</Link></li>
65+
<li><Link to="/contact">Contact</Link></li>
66+
<li><Link to="/blog">Blog</Link></li>
67+
</ul>
68+
<UserDropdown />
69+
</nav>
70+
</header>
71+
<Routes>
72+
<Route path="/" element={<Home />} />
73+
<Route path="/services" element={<Services />} />
74+
<Route path="/about" element={<About />} />
75+
<Route path="/contact" element={<Contact />} />
76+
<Route path="/blog" element={<Blog />} />
77+
<Route path="/auth" element={<Auth />} />
78+
<Route path="/user" element={<User />} />
79+
<Route path="/admin" element={<Admin />} />
80+
<Route path="/logout" element={<Logout />} />
81+
</Routes>
82+
</main>
83+
);
84+
}
85+
86+
function ScrollToTop() {
87+
React.useEffect(() => {
88+
window.scrollTo({ top: 0, behavior: 'smooth' });
89+
}, []);
90+
return null;
91+
}
92+
function App() {
93+
const [showScrollBtn, setShowScrollBtn] = useState(false);
94+
const [scrollBtnVisible, setScrollBtnVisible] = useState(false);
95+
const fadeDuration = 400; // ms, must match CSS
96+
97+
React.useEffect(() => {
98+
let timeout;
99+
const handleScroll = () => {
100+
if (window.scrollY > 80) {
101+
setShowScrollBtn(true);
102+
setScrollBtnVisible(true);
103+
if (timeout) clearTimeout(timeout);
104+
} else {
105+
setShowScrollBtn(false);
106+
timeout = setTimeout(() => setScrollBtnVisible(false), fadeDuration);
107+
}
108+
};
109+
window.addEventListener('scroll', handleScroll, { passive: true });
110+
// Check on mount in case already scrolled
111+
handleScroll();
112+
return () => {
113+
window.removeEventListener('scroll', handleScroll);
114+
clearTimeout(timeout);
115+
};
116+
}, []);
117+
118+
return (
119+
<Router>
120+
<AnimatedMain />
121+
<ScrollToTop />
122+
{scrollBtnVisible && (
123+
<button
124+
className={`scroll-to-top-btn ${showScrollBtn ? 'fade-in' : 'fade-out'}`}
125+
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
126+
aria-label="Scroll to top"
127+
>
128+
&#8593;
129+
</button>
130+
)}
131+
<footer>
132+
<p>&copy; 2025 Tech Blogger</p>
133+
</footer>
134+
</Router>
135+
);
136+
}
137+
138+
export default App;

src/App.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { render, screen } from '@testing-library/react';
2+
import App from './App';
3+
4+
test('renders learn react link', () => {
5+
render(<App />);
6+
const linkElement = screen.getByText(/learn react/i);
7+
expect(linkElement).toBeInTheDocument();
8+
});

0 commit comments

Comments
 (0)