Add profile image enlargement and refine article display

Implement image enlargement for profile pictures, add relative time display for articles using "X min ago", and ensure articles are sorted by publication date.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 0fb68265-c270-4198-9584-3d9be9bddb41
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/0fb68265-c270-4198-9584-3d9be9bddb41/rOJiPGe
This commit is contained in:
kimjaehyeon0101
2025-09-30 04:33:42 +00:00
parent 329c58f70f
commit 8e4d12d99e
9 changed files with 1836 additions and 41 deletions

View File

@ -1,6 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import { Card, CardContent } from "@/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Dialog, DialogContent } from "@/components/ui/dialog";
import type { MediaOutlet } from "@shared/schema";
import { useAuth } from "@/hooks/useAuth";
import Footer from "@/components/Footer";
@ -17,6 +18,7 @@ const categories = [
export default function MainContent() {
const { user } = useAuth();
const [sortBy, setSortBy] = useState<"alphabetical" | "traffic">("alphabetical");
const [enlargedImage, setEnlargedImage] = useState<string | null>(null);
const { data: allOutlets = [], isLoading } = useQuery<MediaOutlet[]>({
queryKey: ["/api/media-outlets"],
@ -48,29 +50,39 @@ export default function MainContent() {
};
const renderOutletCard = (outlet: MediaOutlet) => (
<Link key={outlet.id} href={`/media/${outlet.slug}`} data-testid={`link-outlet-${outlet.id}`}>
<Card
className="hover:shadow-md transition-shadow cursor-pointer bg-white"
data-testid={`card-outlet-${outlet.id}`}
>
<CardContent className="p-2">
<div className="flex items-center space-x-2">
<div className="w-10 h-10 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"
style={{objectPosition: 'center top'}}
/>
) : (
<div className="w-6 h-6 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>
<Card
key={outlet.id}
className="hover:shadow-md transition-shadow cursor-pointer bg-white"
data-testid={`card-outlet-${outlet.id}`}
>
<CardContent className="p-2">
<div className="flex items-center space-x-2">
<div
className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center overflow-hidden cursor-pointer hover:ring-2 hover:ring-blue-400 transition-all"
onClick={(e) => {
e.stopPropagation();
if (outlet.imageUrl) {
setEnlargedImage(outlet.imageUrl);
}
}}
data-testid={`image-profile-${outlet.id}`}
>
{outlet.imageUrl ? (
<img
src={outlet.imageUrl}
alt={outlet.name}
className="w-full h-full object-cover"
style={{objectPosition: 'center top'}}
/>
) : (
<div className="w-6 h-6 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>
<Link href={`/media/${outlet.slug}`} className="flex-1 min-w-0" data-testid={`link-outlet-${outlet.id}`}>
<div className="flex-1 min-w-0">
<h3 className="font-medium text-gray-900 truncate">
{outlet.name}
@ -79,10 +91,10 @@ export default function MainContent() {
{outlet.description || "Media Outlet"}
</p>
</div>
</div>
</CardContent>
</Card>
</Link>
</Link>
</div>
</CardContent>
</Card>
);
return (
@ -151,6 +163,20 @@ export default function MainContent() {
{/* Footer */}
<Footer />
{/* Image Enlargement Dialog */}
<Dialog open={!!enlargedImage} onOpenChange={() => setEnlargedImage(null)}>
<DialogContent className="max-w-3xl p-0 bg-transparent border-none">
{enlargedImage && (
<img
src={enlargedImage}
alt="Enlarged profile"
className="w-full h-auto rounded-lg"
data-testid="dialog-enlarged-image"
/>
)}
</DialogContent>
</Dialog>
</div>
);
}