From 1add3d5a05b24d4b57de14a0cc7b2705cd753d05 Mon Sep 17 00:00:00 2001
From: kimjaehyeon0101 <47347352-kimjaehyeon0101@users.noreply.replit.com>
Date: Mon, 29 Sep 2025 20:22:57 +0000
Subject: [PATCH] Update media outlet pages to match home screen UI and add
search
Revise UI of media outlet pages to align with the home screen's design, incorporating a search feature and updating styling and internationalization.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 069d4324-6c40-4355-955e-c714a50de1ea
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/069d4324-6c40-4355-955e-c714a50de1ea/gVirbWH
---
client/src/components/SearchModal.tsx | 2 -
client/src/pages/Home.tsx | 13 +-
client/src/pages/MediaOutlet.tsx | 279 ++++++++++++++++++++++----
3 files changed, 239 insertions(+), 55 deletions(-)
diff --git a/client/src/components/SearchModal.tsx b/client/src/components/SearchModal.tsx
index f37ab59..b89c076 100644
--- a/client/src/components/SearchModal.tsx
+++ b/client/src/components/SearchModal.tsx
@@ -21,8 +21,6 @@ export default function SearchModal({ isOpen, onClose }: SearchModalProps) {
const [searchQuery, setSearchQuery] = useState("");
const [debouncedQuery, setDebouncedQuery] = useState("");
- console.log("SearchModal rendered with isOpen:", isOpen);
-
// Debounce search query
useEffect(() => {
const timer = setTimeout(() => {
diff --git a/client/src/pages/Home.tsx b/client/src/pages/Home.tsx
index 1022a83..7e44bb1 100644
--- a/client/src/pages/Home.tsx
+++ b/client/src/pages/Home.tsx
@@ -54,18 +54,16 @@ export default function Home() {
window.location.href = "/"}
/>
{
- console.log("Search div clicked, opening modal...");
- setIsSearchModalOpen(true);
- }}
+ onClick={() => setIsSearchModalOpen(true)}
data-testid="search-container"
>
@@ -75,10 +73,7 @@ export default function Home() {
className="w-80 pl-10 bg-gray-50 border-gray-200 cursor-pointer"
data-testid="input-search"
readOnly
- onClick={() => {
- console.log("Search input clicked, opening modal...");
- setIsSearchModalOpen(true);
- }}
+ onClick={() => setIsSearchModalOpen(true)}
/>
diff --git a/client/src/pages/MediaOutlet.tsx b/client/src/pages/MediaOutlet.tsx
index 201ad90..ad3d731 100644
--- a/client/src/pages/MediaOutlet.tsx
+++ b/client/src/pages/MediaOutlet.tsx
@@ -2,16 +2,27 @@ import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { useRoute, useLocation } from "wouter";
import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
-import { Gavel, Clock, TrendingUp } from "lucide-react";
+import { Gavel, Clock, TrendingUp, Search, Settings, User, LogOut, Grid, List } from "lucide-react";
+import { useAuth } from "@/hooks/useAuth";
+import { useToast } from "@/hooks/use-toast";
+import { queryClient } from "@/lib/queryClient";
import ArticleCard from "@/components/ArticleCard";
+import Footer from "@/components/Footer";
+import LoginModal from "@/components/LoginModal";
+import SearchModal from "@/components/SearchModal";
import type { MediaOutlet, Article, Auction } from "@shared/schema";
export default function MediaOutlet() {
const [, params] = useRoute("/media/:slug");
const [, setLocation] = useLocation();
const [viewMode, setViewMode] = useState<"grid" | "list">("grid");
+ const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);
+ const [isSearchModalOpen, setIsSearchModalOpen] = useState(false);
+ const { user, isAuthenticated } = useAuth();
+ const { toast } = useToast();
const { data: outlet, isLoading: outletLoading } = useQuery
({
queryKey: ["/api/media-outlets", params?.slug],
@@ -28,11 +39,39 @@ export default function MediaOutlet() {
enabled: !!params?.slug
});
+ const handleLogout = async () => {
+ try {
+ const response = await fetch("/api/logout", {
+ method: "POST",
+ credentials: "include",
+ });
+
+ if (response.ok) {
+ toast({
+ title: "Logout Successful",
+ description: "You have been successfully logged out.",
+ });
+
+ queryClient.invalidateQueries({ queryKey: ["/api/auth/user"] });
+ }
+ } catch (error) {
+ toast({
+ title: "Logout Error",
+ description: "An error occurred during logout.",
+ variant: "destructive",
+ });
+ }
+ };
+
+ const handleAdminPage = () => {
+ window.location.href = "/admin";
+ };
+
const formatCurrency = (amount: string | null) => {
- if (!amount) return "₩0";
- return new Intl.NumberFormat('ko-KR', {
+ if (!amount) return "$0";
+ return new Intl.NumberFormat('en-US', {
style: 'currency',
- currency: 'KRW'
+ currency: 'USD'
}).format(parseFloat(amount));
};
@@ -41,65 +80,203 @@ export default function MediaOutlet() {
const now = new Date();
const diff = end.getTime() - now.getTime();
- if (diff <= 0) return "경매 종료";
+ if (diff <= 0) return "Auction Ended";
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
- if (days > 0) return `${days}일 ${hours}시간 남음`;
- if (hours > 0) return `${hours}시간 남음`;
- return "1시간 미만 남음";
+ if (days > 0) return `${days}d ${hours}h remaining`;
+ if (hours > 0) return `${hours}h remaining`;
+ return "Less than 1h remaining";
};
if (outletLoading) {
return (
-
+
+ {/* Header - Same as Home */}
+
+
+
+
+

+
+
+
+
setIsSearchModalOpen(true)}
+ data-testid="search-container"
+ >
+
+
+
+
+ {isAuthenticated && user ? (
+ <>
+
+
+
+
+
+ {user.firstName} {user.lastName}
+
+
+
+
+ >
+ ) : (
+
+ )}
+
+
+
+
+
+
+
-
-
+
+
{Array.from({ length: 6 }).map((_, i) => (
-
+
))}
+
);
}
if (!outlet) {
return (
-
+
Media Outlet Not Found
-
The media outlet you're looking for doesn't exist.
-
+
The media outlet you're looking for doesn't exist.
+
);
}
return (
-