Skip to content

Commit 61bf894

Browse files
committed
Fix image paths and router basename for GitHub Pages subdirectory - Fix missing ImageWithFallback import in Header - Fix all image paths to work with /xktrading base path - Add assets utility for base path handling - Fix jsx attribute warning in HowItWorks
1 parent 45bfe4b commit 61bf894

24 files changed

Lines changed: 206 additions & 125 deletions

src/components/Footer.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import { Link } from 'react-router-dom';
3+
import { getAssetPath } from '../utils/assets.js';
34

45
function Footer() {
56
return (
@@ -8,7 +9,7 @@ function Footer() {
89
<div>
910
<Link to="/" className="flex items-center gap-2 mb-4">
1011
<img
11-
src="/assets/logo.png"
12+
src={getAssetPath("/assets/logo.png")}
1213
alt="XK Trading Floor Logo"
1314
className="h-8 w-8 rounded object-cover"
1415
/>

src/components/Header.jsx

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { ChevronDown } from "lucide-react";
55
import { useDispatch, useSelector } from "react-redux";
66
import { logout, syncUserFromCookie } from "../redux/slices/authSlice.js";
77
import { getUserCookie } from "../utils/cookies.js";
8+
import { getAssetPath } from "../utils/assets.js";
9+
import ImageWithFallback from "./shared/ImageWithFallback.jsx";
810

911
const navItems = [
1012
{ to: "/", label: "Home" },
@@ -60,12 +62,13 @@ function Header() {
6062
const location = useLocation();
6163
const reduxUser = useSelector((state) => state.auth.user);
6264
// Fallback to cookie if Redux user is not available (for cross-tab sync)
63-
const user = reduxUser || (typeof window !== 'undefined' ? getUserCookie() : null);
65+
const user =
66+
reduxUser || (typeof window !== "undefined" ? getUserCookie() : null);
6467
const [menuOpen, setMenuOpen] = React.useState(false);
6568

6669
// Sync user from cookie on mount and when storage changes (cross-tab sync)
6770
const lastSyncedRef = React.useRef(null);
68-
71+
6972
React.useEffect(() => {
7073
// Only sync once on mount if needed - don't re-sync on every reduxUser change
7174
const cookieUser = getUserCookie();
@@ -77,7 +80,7 @@ function Header() {
7780
lastSyncedRef.current = cookieStr;
7881
}
7982
}
80-
83+
8184
const handleStorageChange = () => {
8285
// Storage events only fire from other tabs, so safe to sync
8386
dispatch(syncUserFromCookie());
@@ -86,10 +89,10 @@ function Header() {
8689
lastSyncedRef.current = JSON.stringify(updatedCookie);
8790
}
8891
};
89-
92+
9093
// Listen for storage events (cross-tab sync)
91-
window.addEventListener('storage', handleStorageChange);
92-
94+
window.addEventListener("storage", handleStorageChange);
95+
9396
// Also check periodically for cookie changes (since cookies don't trigger storage events)
9497
const interval = setInterval(() => {
9598
const currentCookieUser = getUserCookie();
@@ -106,9 +109,9 @@ function Header() {
106109
lastSyncedRef.current = null;
107110
}
108111
}, 3000); // Check every 3 seconds
109-
112+
110113
return () => {
111-
window.removeEventListener('storage', handleStorageChange);
114+
window.removeEventListener("storage", handleStorageChange);
112115
clearInterval(interval);
113116
};
114117
}, [dispatch]); // Only dispatch in dependencies - sync once on mount
@@ -138,7 +141,7 @@ function Header() {
138141
className="flex items-center gap-1.5 md:gap-2 transition-transform hover:scale-105 flex-shrink-0"
139142
>
140143
<img
141-
src="/assets/logo.png"
144+
src={getAssetPath("/assets/logo.png")}
142145
alt="XK Trading Floor Logo"
143146
className="h-10 w-8 md:h-14 md:w-10 rounded object-cover"
144147
/>
@@ -244,8 +247,9 @@ function Header() {
244247
aria-expanded={menuOpen}
245248
aria-label="User menu"
246249
>
247-
<img
250+
<ImageWithFallback
248251
src={user.avatar || "/assets/users/default-avatar.jpg"}
252+
fallback="/assets/users/default-avatar.jpg"
249253
alt="User avatar"
250254
className="h-7 w-7 lg:h-8 lg:w-8 rounded-full object-cover ring-2 ring-blue-500/20 flex-shrink-0"
251255
/>
@@ -268,13 +272,13 @@ function Header() {
268272
className="absolute right-0 top-12 w-48 border border-gray-800 bg-gray-900/95 backdrop-blur-xl rounded-lg shadow-2xl overflow-hidden"
269273
role="menu"
270274
>
271-
{(user?.role === 'admin' || user?.role === 'operator') && (
275+
{(user?.role === "admin" || user?.role === "operator") && (
272276
<button
273277
onClick={() => {
274278
setMenuOpen(false);
275279
// Use navigate with a small delay to ensure menu closes first
276280
setTimeout(() => {
277-
navigate('/dashboard');
281+
navigate("/dashboard");
278282
}, 100);
279283
}}
280284
className="block w-full text-left px-4 py-3 text-sm text-gray-200 hover:bg-gray-800/50 transition-colors border-b border-gray-800"
@@ -364,12 +368,12 @@ function Header() {
364368
<div className="pt-4 mt-2 border-t border-gray-800 flex flex-col gap-2">
365369
{user ? (
366370
<>
367-
{(user?.role === 'admin' || user?.role === 'operator') && (
371+
{(user?.role === "admin" || user?.role === "operator") && (
368372
<button
369373
onClick={() => {
370374
setOpen(false);
371375
setTimeout(() => {
372-
navigate('/dashboard');
376+
navigate("/dashboard");
373377
}, 100);
374378
}}
375379
className="w-full text-left px-4 py-3 text-sm text-gray-300 hover:text-white hover:bg-gray-800/50 rounded-lg transition-colors"

src/components/academy/EventsGrid.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import React from "react";
22
import { motion } from "framer-motion";
33
import { getAllEvents } from "../../controllers/eventsController.js";
44
import { Calendar, User } from "lucide-react";
5+
import ImageWithFallback from "../shared/ImageWithFallback.jsx";
56

67
function EventCard({ evt, onRegister }) {
78
return (
89
<motion.div whileHover={{ y: -4 }} className="card overflow-hidden">
910
<div className="h-40 w-full bg-muted">
10-
<img
11+
<ImageWithFallback
1112
src={evt.image}
13+
fallback="/assets/placeholder.jpg"
1214
alt={evt.title}
1315
className="h-full w-full object-cover"
1416
/>

src/components/academy/PodcastSection.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import React from 'react';
22
import { motion } from 'framer-motion';
33
import { getAllPodcasts } from '../../controllers/podcastsController.js';
4+
import ImageWithFallback from '../shared/ImageWithFallback.jsx';
45

56
function PodcastCard({ item }) {
67
const [playing, setPlaying] = React.useState(false);
78
return (
89
<motion.div whileHover={{ y: -4 }} className="min-w-[260px] card overflow-hidden">
910
<div className="h-36 w-full bg-muted">
10-
<img src={item.thumbnail} alt={item.title} className="h-full w-full object-cover" />
11+
<ImageWithFallback src={item.thumbnail} fallback="/assets/placeholder.jpg" alt={item.title} className="h-full w-full object-cover" />
1112
</div>
1213
<div className="card-body">
1314
<div className="text-xs text-gray-400">{item.duration}</div>

src/components/blog/BlogAuthorInfo.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import React from 'react';
22
import { Linkedin, Twitter } from 'lucide-react';
3+
import ImageWithFallback from '../shared/ImageWithFallback.jsx';
34

45
function BlogAuthorInfo({ author }) {
56
if (!author) return null;
67
return (
78
<div className="card mt-8">
89
<div className="card-body flex items-center gap-4">
910
<div className="h-14 w-14 rounded-full bg-muted overflow-hidden">
10-
{author.avatar && <img src={author.avatar} alt={author.name} className="h-full w-full object-cover" />}
11+
{author.avatar && <ImageWithFallback src={author.avatar} fallback="/assets/users/default-avatar.jpg" alt={author.name} className="h-full w-full object-cover" />}
1112
</div>
1213
<div className="flex-1">
1314
<div className="font-semibold">{author.name}</div>

src/components/blog/BlogCard.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import React from 'react';
22
import { motion } from 'framer-motion';
3+
import ImageWithFallback from '../shared/ImageWithFallback.jsx';
34

45
function BlogCard({ post, onClick }) {
56
return (
67
<motion.div whileHover={{ y: -4, scale: 1.01 }} className="card overflow-hidden cursor-pointer shadow-lg shadow-blue-500/10" onClick={onClick}>
78
<div className="h-40 w-full bg-muted">
8-
<img src={post.image} alt={post.title} className="h-full w-full object-cover" />
9+
<ImageWithFallback src={post.image} fallback="/assets/placeholder.jpg" alt={post.title} className="h-full w-full object-cover" />
910
</div>
1011
<div className="card-body">
1112
<div className="text-xs text-blue-300">{post.category}</div>

src/components/home/FeaturedEvents.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import { motion } from 'framer-motion';
33
import { getAllEvents } from '../../controllers/eventsController.js';
44
import { Link, useNavigate } from 'react-router-dom';
5+
import ImageWithFallback from '../shared/ImageWithFallback.jsx';
56

67
function EventCard({ evt, onClick }) {
78
const formatDate = (dateString) => {
@@ -17,7 +18,7 @@ function EventCard({ evt, onClick }) {
1718
return (
1819
<motion.div whileHover={{ y: -4 }} className="card overflow-hidden cursor-pointer" onClick={onClick}>
1920
<div className="h-40 w-full bg-muted">
20-
<img src={evt.image || '/assets/placeholder.jpg'} alt={evt.title} className="h-full w-full object-cover" />
21+
<ImageWithFallback src={evt.image || '/assets/placeholder.jpg'} fallback="/assets/placeholder.jpg" alt={evt.title} className="h-full w-full object-cover" />
2122
</div>
2223
<div className="card-body">
2324
<div className="text-xs text-gray-400">{formatDate(evt.dateTime || evt.date)}</div>

src/components/home/HeroSection.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import { motion } from 'framer-motion';
33
import { ArrowRight } from 'lucide-react';
44
import { Link } from 'react-router-dom';
5+
import { getAssetPath } from '../../utils/assets.js';
56

67
function HeroSection() {
78
return (
@@ -99,7 +100,7 @@ function HeroSection() {
99100
className="absolute z-30 flex items-center justify-center"
100101
>
101102
<motion.img
102-
src="/assets/logo.png"
103+
src={getAssetPath("/assets/logo.png")}
103104
alt="XK Trading Floor Logo"
104105
className="h-64 w-48 md:h-80 md:w-60 lg:h-96 lg:w-72 object-contain drop-shadow-2xl"
105106
animate={{

0 commit comments

Comments
 (0)