Files
sapiens-web3/client/src/pages/Home.tsx
kimjaehyeon0101 06e79e1e25 Update logo source to fix display issues across the platform
Corrected image source path for the SAPIENS logo in multiple components (Footer, Header, LoginModal, AdminDashboard, Article, AuctionGuide, Auctions, Community, Home, Landing, MediaOutlet, Report) from `/attached_assets/검은색 로고_1760521542271.png` to `/attached_assets/sapiens_black_logo.png` to resolve display errors.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9a264234-c5d7-4dcc-adf3-a954b149b30d
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/9a264234-c5d7-4dcc-adf3-a954b149b30d/uLfJUnK
2025-10-15 09:52:56 +00:00

311 lines
12 KiB
TypeScript

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { useAuth } from "@/hooks/useAuth";
import { Search, Settings, User, LogOut, Sun, Moon, Monitor, Globe } from "lucide-react";
import { useState, useEffect } from "react";
import MainContent from "@/components/MainContent";
import LoginModal from "@/components/LoginModal";
import SearchModal from "@/components/SearchModal";
import { useToast } from "@/hooks/use-toast";
import { queryClient } from "@/lib/queryClient";
import { useLocation } from "wouter";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export default function Home() {
const { user, isAuthenticated } = useAuth();
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false);
const { toast } = useToast();
const [, setLocation] = useLocation();
const [theme, setTheme] = useState(() => localStorage.getItem('theme') || 'light');
const [language, setLanguage] = useState(() => localStorage.getItem('language') || 'en');
useEffect(() => {
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
localStorage.setItem('theme', theme);
}, [theme]);
useEffect(() => {
localStorage.setItem('language', language);
}, [language]);
const handleThemeChange = (newTheme: string) => {
setTheme(newTheme);
};
const handleLanguageChange = (newLanguage: string) => {
setLanguage(newLanguage);
};
const languages = [
{ code: 'en', name: 'English' },
{ code: 'fr', name: 'Français' },
{ code: 'de', name: 'Deutsch' },
{ code: 'it', name: 'Italiano' },
{ code: 'hi', name: 'हिन्दी' },
{ code: 'ar', name: 'العربية' },
{ code: 'ja', name: '日本語' },
{ code: 'ko', name: '한국어' },
{ code: 'zh-TW', name: '繁體中文' },
{ code: 'zh-CN', name: '简体中文' },
];
const handleLogout = async () => {
try {
const response = await fetch("/api/logout", {
method: "POST",
credentials: "include",
});
if (response.ok) {
toast({
title: "Logged Out",
description: "You have been successfully logged out.",
});
// Invalidate auth queries to refresh user state
queryClient.invalidateQueries({ queryKey: ["/api/auth/user"] });
}
} catch (error) {
toast({
title: "Logout Error",
description: "An error occurred while logging out.",
variant: "destructive",
});
}
};
const handleAdminPage = () => {
setLocation("/admin");
};
return (
<div className="min-h-screen bg-gray-50">
{/* Header */}
<header className="bg-white border-b border-gray-200 sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-6 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center">
<img
src="/attached_assets/sapiens_black_logo.png"
alt="SAPIENS"
className="h-8 w-auto cursor-pointer"
data-testid="logo-sapiens"
onClick={() => setLocation("/")}
/>
</div>
<div className="flex items-center space-x-4">
<div
className="relative cursor-pointer flex items-center"
onClick={() => setIsSearchModalOpen(true)}
data-testid="search-container"
>
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400 pointer-events-none" />
<div className="pl-10 pr-16 py-1.5 bg-gray-50 border border-gray-200 rounded-md flex items-center space-x-2 hover:bg-gray-100 transition-colors">
<span className="text-sm text-gray-500">search in</span>
<img
src="/attached_assets/sapiens_black_logo.png"
alt="SAPIENS"
className="h-4 w-auto"
/>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={() => setLocation("/auctions")}
data-testid="button-auctions"
>
Auctions
</Button>
{isAuthenticated && user ? (
<>
<Button
variant="ghost"
size="sm"
onClick={handleAdminPage}
data-testid="button-admin-dashboard"
>
Admin Dashboard
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="sm"
data-testid="button-settings"
>
<Settings className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
<DropdownMenuLabel>Theme</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => handleThemeChange('light')}
className="cursor-pointer"
data-testid="theme-light"
>
<Sun className="h-4 w-4 mr-2" />
Light
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => handleThemeChange('dark')}
className="cursor-pointer"
data-testid="theme-dark"
>
<Moon className="h-4 w-4 mr-2" />
Dark
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => handleThemeChange('system')}
className="cursor-pointer"
data-testid="theme-system"
>
<Monitor className="h-4 w-4 mr-2" />
System
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>Language</DropdownMenuLabel>
{languages.map((lang) => (
<DropdownMenuItem
key={lang.code}
onClick={() => handleLanguageChange(lang.code)}
className="cursor-pointer"
data-testid={`language-${lang.code}`}
>
<Globe className="h-4 w-4 mr-2" />
{lang.name}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<div className="flex items-center space-x-2 px-3 py-1 bg-gray-100 rounded-md cursor-pointer hover:bg-gray-200 transition-colors" data-testid="user-profile-chip">
<User className="h-4 w-4 text-gray-600" />
<span className="text-sm font-medium text-gray-700" data-testid="user-name">
{user.firstName} {user.lastName}
</span>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={handleLogout}
className="cursor-pointer text-red-600"
data-testid="button-logout"
>
<LogOut className="h-4 w-4 mr-2" />
Logout
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
) : (
<>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="sm"
data-testid="button-settings"
>
<Settings className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
<DropdownMenuLabel>Theme</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => handleThemeChange('light')}
className="cursor-pointer"
data-testid="theme-light"
>
<Sun className="h-4 w-4 mr-2" />
Light
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => handleThemeChange('dark')}
className="cursor-pointer"
data-testid="theme-dark"
>
<Moon className="h-4 w-4 mr-2" />
Dark
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => handleThemeChange('system')}
className="cursor-pointer"
data-testid="theme-system"
>
<Monitor className="h-4 w-4 mr-2" />
System
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>Language</DropdownMenuLabel>
{languages.map((lang) => (
<DropdownMenuItem
key={lang.code}
onClick={() => handleLanguageChange(lang.code)}
className="cursor-pointer"
data-testid={`language-${lang.code}`}
>
<Globe className="h-4 w-4 mr-2" />
{lang.name}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
<Button
variant="ghost"
size="sm"
onClick={() => setIsLoginModalOpen(true)}
data-testid="button-login"
>
<User className="h-4 w-4" />
</Button>
</>
)}
</div>
</div>
</div>
</header>
{/* Main Content */}
<MainContent />
{/* Login Modal */}
<LoginModal
isOpen={isLoginModalOpen}
onClose={() => setIsLoginModalOpen(false)}
/>
{/* Search Modal */}
<SearchModal
isOpen={isSearchModalOpen}
onClose={() => setIsSearchModalOpen(false)}
/>
</div>
);
}