Update the hero section layout and fix image processing errors

Refactor the hero section to a multi-card layout and adjust image processing parameters by changing `max_tokens` to `max_completion_tokens` and removing an unsupported `temperature` value.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 517dfa7b-26ac-463d-a6e1-a58c6df97188
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: dc1a7e29-d86e-41b6-8c1b-d753e4842371
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/517dfa7b-26ac-463d-a6e1-a58c6df97188/ls5p9ni
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sebastjanartic 2026-03-01 09:07:42 +00:00
parent 7eaeadaf07
commit 0d19bcb47e
4 changed files with 36 additions and 33 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -257,24 +257,28 @@ function SideCard({ article, focalPoints }: { article: Article; focalPoints?: Re
return (
<Link href={`/article/${article.slug}`}>
<div className="relative group cursor-pointer rounded-lg overflow-hidden bg-card border border-card-border h-full flex flex-col" data-testid={`card-side-${article.id}`}>
<div className="relative flex-shrink-0 flex-1 min-h-0">
<div className="relative flex-1 min-h-0">
<div className="overflow-hidden h-full">
<img src={thumbUrl(article.coverImage)} alt={article.title} className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" style={{ objectPosition: objPos }} loading="lazy" />
</div>
{isVideo && (
<div className="absolute inset-0 flex items-center justify-center">
<div className="w-9 h-9 rounded-full bg-primary/90 flex items-center justify-center group-hover:bg-primary transition-colors">
<div className="w-10 h-10 rounded-full bg-primary/90 flex items-center justify-center group-hover:bg-primary transition-colors">
<Play className="w-4 h-4 text-white ml-0.5" fill="white" />
</div>
</div>
)}
</div>
<div className="p-2.5 flex-shrink-0">
<div className="flex items-center gap-2 mb-0.5">
<span className="text-[10px] font-medium text-primary">{article.author}</span>
<span className="text-muted-foreground text-[10px]">{timeAgo(new Date(article.publishedAt))}</span>
<div className="p-3 flex-shrink-0">
<div className="flex items-center gap-2 mb-1">
<span className="text-xs font-medium text-primary">{article.author}</span>
<span className="text-muted-foreground text-xs">{timeAgo(new Date(article.publishedAt))}</span>
</div>
<h3 className="font-bold text-card-foreground text-sm leading-snug line-clamp-2 group-hover:text-primary transition-colors">{article.title}</h3>
<div className="flex items-center gap-1.5 mt-2 text-muted-foreground text-xs">
<Eye className="w-3 h-3" />
{article.views.toLocaleString()}
</div>
<h3 className="font-semibold text-card-foreground text-xs leading-snug line-clamp-2 group-hover:text-primary transition-colors">{article.title}</h3>
</div>
</div>
</Link>
@ -334,11 +338,12 @@ function TopStoriesList({ articles }: { articles: Article[] }) {
function FeaturedHeroCard({ article, focalPoints }: { article: Article; focalPoints?: Record<string, { x: number; y: number }> }) {
const isVideo = article.category === "Video";
const objPos = getObjectPosition(article.coverImage, focalPoints);
return (
<Link href={`/article/${article.slug}`}>
<div className="relative group cursor-pointer rounded-lg overflow-hidden h-full" data-testid={`card-featured-hero-${article.id}`}>
<div className="relative h-full min-h-[260px]">
<img src={article.coverImage || ""} alt={article.title} className="w-full h-full object-cover absolute inset-0 transition-transform duration-700 group-hover:scale-105" style={{ objectPosition: "center top" }} loading="lazy" />
<div className="relative group cursor-pointer rounded-lg overflow-hidden bg-card border border-card-border h-full flex flex-col" data-testid={`card-featured-hero-${article.id}`}>
<div className="relative flex-1 min-h-[300px]">
<img src={article.coverImage || ""} alt={article.title} className="w-full h-full object-cover absolute inset-0 transition-transform duration-700 group-hover:scale-105" style={{ objectPosition: objPos }} loading="lazy" />
{isVideo && (
<div className="absolute inset-0 flex items-center justify-center z-10">
<div className="w-14 h-14 rounded-full bg-primary/90 flex items-center justify-center group-hover:bg-primary transition-colors shadow-lg">
@ -346,13 +351,17 @@ function FeaturedHeroCard({ article, focalPoints }: { article: Article; focalPoi
</div>
</div>
)}
<div className="absolute inset-0 bg-gradient-to-t from-black/90 via-black/30 to-transparent" />
<div className="absolute bottom-0 left-0 right-0 p-4">
<div className="flex items-center gap-2 mb-1.5">
<span className="text-[10px] font-medium text-primary">{article.author}</span>
<span className="text-white/50 text-[10px]">{timeAgo(new Date(article.publishedAt))}</span>
</div>
<h3 className="text-white font-bold text-base md:text-lg leading-tight line-clamp-3 group-hover:text-primary/90 transition-colors">{article.title}</h3>
</div>
<div className="p-4 flex-shrink-0">
<div className="flex items-center gap-2 mb-1.5">
<span className="text-xs font-medium text-primary">{article.category}</span>
<span className="text-muted-foreground text-xs">{timeAgo(new Date(article.publishedAt))}</span>
</div>
<h3 className="font-bold text-card-foreground text-lg leading-tight line-clamp-3 group-hover:text-primary transition-colors">{article.title}</h3>
<p className="text-sm text-muted-foreground mt-2 leading-relaxed line-clamp-3">{article.excerpt}</p>
<div className="flex items-center gap-2 mt-3 text-muted-foreground text-xs">
<Eye className="w-3.5 h-3.5" />
{article.views.toLocaleString()}
</div>
</div>
</div>
@ -378,23 +387,18 @@ function FeaturedCarousel({ articles, popular, galleryImages, focalPoints }: { a
const start = page * pageSize;
const hero = articles[start];
const bottom = articles.slice(start + 1, start + 3);
const sideCards = articles.slice(start + 1, start + 3);
return (
<section data-testid="featured-carousel" onMouseEnter={() => setPaused(true)} onMouseLeave={() => setPaused(false)}>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
<div className="lg:col-span-2">
<div className="grid grid-cols-1 gap-4">
{hero && <FeaturedHeroCard article={hero} focalPoints={focalPoints} />}
<div className="grid grid-cols-2 gap-4">
{bottom.map((a) => (
<MediumCard key={a.id} article={a} focalPoints={focalPoints} />
))}
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-5 gap-4">
<div className="lg:col-span-3">
{hero && <FeaturedHeroCard article={hero} focalPoints={focalPoints} />}
</div>
<div className="lg:col-span-1">
{popular && popular.length > 0 && <TopStoriesList articles={popular} />}
<div className="lg:col-span-2 grid grid-rows-2 gap-4">
{sideCards.map((a) => (
<SideCard key={a.id} article={a} focalPoints={focalPoints} />
))}
</div>
</div>
{totalPages > 1 && (

View File

@ -69,7 +69,7 @@ export async function analyzeFocalPoint(imagePath: string): Promise<{ x: number;
]
}
],
max_tokens: 60,
max_completion_tokens: 60,
});
const text = response.choices[0]?.message?.content?.trim() || "";

View File

@ -66,8 +66,7 @@ Antworte NUR mit einem JSON-Objekt in diesem exakten Format (kein Markdown, kein
}`
}
],
temperature: 0.9,
max_tokens: 2000,
max_completion_tokens: 2000,
});
const content = response.choices[0]?.message?.content || "";