Files
sapiens-web3/client/src/components/MainContent.tsx
kimjaehyeon0101 5a6d98208d Update home and landing pages to show consistent UI regardless of login status
Refactor routing and page components to ensure the main content is displayed identically for both logged-in and logged-out users, removing conditional rendering based on authentication status in the main router and consolidating content display logic into a new `MainContent` component.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 069d4324-6c40-4355-955e-c714a50de1ea
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/069d4324-6c40-4355-955e-c714a50de1ea/InMLMqG
2025-09-29 16:40:42 +00:00

140 lines
5.2 KiB
TypeScript

import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import type { MediaOutlet } from "@shared/schema";
import { useAuth } from "@/hooks/useAuth";
const categories = [
{ id: "people", name: "People", key: "People" },
{ id: "topics", name: "Topics", key: "Topics" },
{ id: "companies", name: "Companies", key: "Companies" }
];
export default function MainContent() {
const [selectedCategory, setSelectedCategory] = useState("People");
const { user } = useAuth();
const { data: mediaOutlets = [], isLoading } = useQuery<MediaOutlet[]>({
queryKey: ["/api/media-outlets", selectedCategory],
queryFn: async () => {
const res = await fetch(`/api/media-outlets?category=${selectedCategory}`, {
credentials: "include",
});
if (!res.ok) {
throw new Error(`${res.status}: ${res.statusText}`);
}
return res.json();
},
});
const { data: allOutlets = [] } = useQuery<MediaOutlet[]>({
queryKey: ["/api/media-outlets"],
queryFn: async () => {
const res = await fetch("/api/media-outlets", {
credentials: "include",
});
if (!res.ok) {
throw new Error(`${res.status}: ${res.statusText}`);
}
return res.json();
},
});
// Count outlets by category
const getCategoryCount = (category: string) => {
return allOutlets.filter(outlet =>
outlet.category.toLowerCase() === category.toLowerCase()
).length;
};
return (
<div className="min-h-screen bg-gray-50">
{/* Category Tabs */}
<div className="bg-white border-b">
<div className="max-w-7xl mx-auto px-6">
<div className="flex space-x-0">
{categories.map((category) => (
<button
key={category.id}
onClick={() => setSelectedCategory(category.key)}
className={`px-8 py-4 text-sm font-medium border-b-2 transition-colors ${
selectedCategory === category.key
? "border-blue-500 text-blue-600"
: "border-transparent text-gray-500 hover:text-gray-700"
}`}
data-testid={`tab-${category.id}`}
>
{category.name}
<span className="ml-2 text-gray-400">
{getCategoryCount(category.key)}
</span>
</button>
))}
</div>
</div>
</div>
{/* Media Outlets Grid */}
<div className="max-w-7xl mx-auto px-6 py-8">
{isLoading ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{Array.from({ length: 12 }).map((_, i) => (
<Card key={i} className="animate-pulse">
<CardContent className="p-4">
<div className="flex items-center space-x-3">
<div className="w-12 h-12 bg-gray-200 rounded-full"></div>
<div className="flex-1">
<div className="h-4 bg-gray-200 rounded mb-2"></div>
<div className="h-3 bg-gray-200 rounded w-2/3"></div>
</div>
</div>
</CardContent>
</Card>
))}
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{mediaOutlets.map((outlet) => (
<Card
key={outlet.id}
className="hover:shadow-md transition-shadow cursor-pointer bg-white"
data-testid={`card-outlet-${outlet.id}`}
>
<CardContent className="p-4">
<div className="flex items-center space-x-3">
<div className="w-12 h-12 rounded-full bg-gray-100 flex items-center justify-center overflow-hidden">
{outlet.imageUrl ? (
<img
src={outlet.imageUrl}
alt={outlet.name}
className="w-full h-full object-cover"
/>
) : (
<div className="w-8 h-8 bg-gray-300 rounded-full flex items-center justify-center">
<span className="text-gray-600 text-sm font-medium">
{outlet.name.charAt(0)}
</span>
</div>
)}
</div>
<div className="flex-1 min-w-0">
<h3 className="font-medium text-gray-900 truncate">
{outlet.name}
</h3>
<p className="text-sm text-gray-500 truncate">
{outlet.category === "people" && "Media Personality"}
{outlet.category === "topics" && "Industry Topic"}
{outlet.category === "companies" && "Technology Company"}
</p>
</div>
</div>
</CardContent>
</Card>
))}
</div>
)}
</div>
</div>
);
}