Files
flixcooks-website/index.php
T

355 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require __DIR__ . '/helpers.php';
// Language & inputs
$lang = strtolower((string) (filter_input(INPUT_GET, 'lang', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?: 'en')) === 'de' ? 'de' : 'en';
$q = trim((string) (filter_input(INPUT_GET, 'q', FILTER_UNSAFE_RAW) ?? ''));
$tag = trim((string) (filter_input(INPUT_GET, 'tag', FILTER_UNSAFE_RAW) ?? ''));
// Language copy
$copy = [
'en' => [
'home' => 'Home',
'latest' => 'Latest',
'basics' => 'Basics',
'eyebrow' => 'Seasonal, unfussy, ridiculously tasty.',
'headline' => 'Cook better <span>weeknights</span> and brighter <span>weekends</span>.',
'subhead' => 'Search for a craving, filter by vibe, or jump into this week\'s featured recipe.',
'search_placeholder' => 'Search for pasta, brunch, sauce...',
'search_button' => 'Search',
'tag_clear' => 'Clear',
'featured' => 'Featured',
'latest_drops' => 'Latest drops',
'count_suffix_default' => ' recipes ready to cook.',
'count_suffix_filtered' => ' recipes matching your filter.',
'kitchen_basics' => 'Kitchen basics',
'basics_sub' => 'Quick wins that upgrade everything else.',
'servings' => 'servings',
'cook_it' => 'Cook it',
'coming_features' => 'Coming soon',
'coming_features_sub' => 'Features Im shipping next.',
],
'de' => [
'home' => 'Start',
'latest' => 'Neueste',
'basics' => 'Basics',
'eyebrow' => 'Saisonal, unkompliziert, richtig lecker.',
'headline' => 'Besser kochen unter der Woche, glänzen am Wochenende.',
'subhead' => 'Suche nach einem Gericht, filtere nach Stimmung oder starte mit dem Highlight der Woche.',
'search_placeholder' => 'Suche nach Pasta, Brunch, Sauce...',
'search_button' => 'Suchen',
'tag_clear' => 'Zurücksetzen',
'featured' => 'Highlight',
'latest_drops' => 'Frisch dazugekommen',
'count_suffix_default' => ' Rezepte bereit zum Kochen.',
'count_suffix_filtered' => ' Rezepte passend zum Filter.',
'kitchen_basics' => 'Küchenbasics',
'basics_sub' => 'Kleine Tricks, die alles besser machen.',
'servings' => 'Portionen',
'cook_it' => 'Nachkochen',
'coming_features' => 'Demnächst',
'coming_features_sub' => 'Features, an denen ich gerade baue.',
],
];
$t = $copy[$lang];
$allRecipes = load_recipes();
$siteSettings = load_site_settings();
$cms = $siteSettings['cms'][$lang] ?? [];
$localizedAll = localize_recipes($allRecipes, $lang);
$recipes = filter_recipes($allRecipes, $q ?: null, $tag ?: null, $lang);
$recipes = array_values(array_filter($recipes, fn($r) => empty($r['coming_soon']))); // hide coming soon from main list
$comingSoon = array_values(array_filter($localizedAll, fn($r) => !empty($r['coming_soon'])));
$placeholderTitle = $lang === 'de' ? 'Bald verfügbar' : 'Coming soon';
$comingSoonDisplay = array_pad($comingSoon, 5, [
'hero' => '/assets/placeholder.svg',
'title' => $placeholderTitle,
]);
$featured = null;
foreach ($allRecipes as $recipe) {
if (!empty($recipe['featured']) && empty($recipe['coming_soon'])) {
$featured = $recipe;
break;
}
}
$featured = $featured ?? ($allRecipes[0] ?? null);
$featured = $featured ? localize_recipe($featured, $lang) : null;
// Build tag cloud
$allTags = [];
foreach ($localizedAll as $recipe) {
foreach ($recipe['tags'] ?? [] as $tTag) {
$allTags[] = $tTag;
}
}
$allTags = array_values(array_unique($allTags));
$comingFeatures = array_values(array_filter([
trim((string) ($cms['coming_feature_1'] ?? '')),
trim((string) ($cms['coming_feature_2'] ?? '')),
trim((string) ($cms['coming_feature_3'] ?? '')),
], 'strlen'));
$pageTitle = trim((string) ($cms['home_title'] ?? '')) ?: ($lang === 'de'
? 'FlixCooks | Moderner Foodblog für schnelle Alltagsküche'
: 'FlixCooks | Modern food blog for busy home cooks');
$description = trim((string) ($cms['home_description'] ?? '')) ?: ($lang === 'de'
? 'Frische, schnelle Rezepte mit klaren Schritten und großem Geschmack. Gebaut für Hetzner Webhosting in einfachem PHP.'
: 'Fresh, fast recipes with clear steps, smart prep notes, and big flavor. Built for Hetzner web hosting in plain PHP.');
$langSwitchLabel = $lang === 'de' ? 'DE' : 'EN';
$langSwitchHref = lang_url($lang === 'de' ? 'en' : 'de');
$navHome = $t['home'];
$navLatest = $t['latest'];
$navBasics = $t['basics'];
$quickStartRecipes = array_slice($recipes, 0, 3);
$latestRecipes = array_slice($recipes, 0, 6);
$recipeCount = count($recipes);
$totalMinutes = array_sum(array_map(fn($recipe) => (int) ($recipe['total_time'] ?? 0), $recipes));
$averageMinutes = $recipeCount > 0 ? (int) ceil($totalMinutes / $recipeCount) : 0;
$activeTag = $tag !== '' ? $tag : null;
$tagCount = count($allTags);
$copy['en'] += [
'discover_title' => 'Find your next easy favorite.',
'discover_text' => 'Everything below the landing area is simplified for smaller screens: search, tap a tag, and jump into a recipe without cramped text blocks.',
'browse_tags' => 'Browse tags',
'quick_start_title' => 'Quick start',
'quick_start_text' => 'Open one of the recipes with the shortest path from craving to plate.',
'library_title' => 'Recipe library',
'library_text' => 'Clean cards, shorter descriptions, and tap-friendly actions for mobile browsing.',
'stats_recipes' => 'live recipes',
'stats_average' => 'avg. total time',
'stats_tags' => 'browseable tags',
'empty_title' => 'No recipes found yet',
'empty_text' => 'Try another search term or clear the active tag to see every recipe again.',
'view_recipe' => 'View recipe',
];
$copy['de'] += [
'discover_title' => 'Finde schnell dein nächstes Lieblingsrezept.',
'discover_text' => 'Alles unterhalb der Landingpage ist für kleine Screens vereinfacht: suchen, Tag antippen und ohne gequetschte Textblöcke ins Rezept springen.',
'browse_tags' => 'Tags entdecken',
'quick_start_title' => 'Schnell starten',
'quick_start_text' => 'Öffne eines der Rezepte mit dem kürzesten Weg von Appetit zu Teller.',
'library_title' => 'Rezeptübersicht',
'library_text' => 'Saubere Karten, kürzere Beschreibungen und gut tappbare Aktionen für Mobile.',
'stats_recipes' => 'Rezepte online',
'stats_average' => 'Ø Gesamtzeit',
'stats_tags' => 'durchsuchbare Tags',
'empty_title' => 'Noch keine Rezepte gefunden',
'empty_text' => 'Probiere einen anderen Suchbegriff oder entferne den aktiven Tag, um wieder alle Rezepte zu sehen.',
'view_recipe' => 'Rezept ansehen',
];
$t = $copy[$lang];
// Small helpers for URLs
$langQuery = ['lang' => $lang];
$recipeUrl = fn(array $recipe) => '/recipe.php?' . http_build_query(['slug' => $recipe['slug']] + $langQuery);
$tagUrl = fn(string $tagValue) => '/index.php?' . http_build_query(['tag' => $tagValue] + $langQuery);
include __DIR__ . '/partials/head.php';
?>
<?php // ── LANDING SECTION ─────────────────────────────────────────────────── ?>
<section class="landing" id="landing" aria-label="Landing">
<div class="landing__blobs" aria-hidden="true">
<div class="blob blob--a"></div>
<div class="blob blob--b"></div>
<div class="blob blob--c"></div>
</div>
<div class="landing__chips" aria-hidden="true">
<div class="chip chip--1">
<img src="/assets/pasta-tomato.jpg" alt="">
<span><?php echo $lang === 'de' ? 'Pasta' : 'Pasta'; ?></span>
</div>
<div class="chip chip--2">
<img src="/assets/steak.jpg" alt="">
<span><?php echo $lang === 'de' ? 'Steak' : 'Steak'; ?></span>
</div>
<div class="chip chip--3">
<img src="/assets/pancakes.jpg" alt="">
<span><?php echo $lang === 'de' ? 'Pfannkuchen' : 'Pancakes'; ?></span>
</div>
<div class="chip chip--4">
<img src="/assets/haferkuchen.JPEG" alt="">
<span><?php echo $lang === 'de' ? 'Kuchen' : 'Cake'; ?></span>
</div>
</div>
<div class="landing__copy">
<p class="landing__eyebrow">
<?php echo e($cms['landing_eyebrow'] ?? ($lang === 'de'
? 'Saisonal · Unkompliziert · Richtig lecker'
: 'Seasonal · Unfussy · Ridiculously tasty')); ?>
</p>
<h1 class="landing__headline">
<span class="line line--1"><?php echo e($cms['landing_line_1'] ?? ($lang === 'de' ? 'Besser kochen' : 'Cook better')); ?></span>
<span class="line line--2"><?php echo e($cms['landing_line_2'] ?? ($lang === 'de' ? 'unter der Woche.' : 'weeknights.')); ?></span>
<span class="line line--3"><?php echo e($cms['landing_line_3'] ?? ($lang === 'de' ? 'Glänzen am Wochenende.' : 'Brighter weekends.')); ?></span>
</h1>
<p class="landing__sub"><?php echo e($t['subhead']); ?></p>
<a href="#recipes-start" class="landing__cta" id="landingCta">
<span><?php echo e($cms['landing_cta'] ?? ($lang === 'de' ? 'Rezepte entdecken' : 'Explore recipes')); ?></span>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12l7 7 7-7"/></svg>
</a>
</div>
<div class="landing__scroll-nudge" aria-hidden="true">
<div class="scroll-line"></div>
<span>scroll</span>
</div>
</section>
<?php include __DIR__ . '/partials/header.php'; ?>
<div id="recipes-start">
<script>
document.getElementById('landingCta').addEventListener('click', function(e){
e.preventDefault();
document.getElementById('recipes-start').scrollIntoView({ behavior: 'smooth' });
});
</script>
<?php if (!empty($comingSoon)): ?>
<div class="coming-strip" aria-label="Coming soon recipes">
<div class="coming-strip__head">
<p class="pill pill--ghost"><?php echo e($cms['coming_soon_badge'] ?? ($lang === 'de' ? 'Bald verfügbar' : 'Coming soon')); ?></p>
<small><?php echo count($comingSoon); ?> <?php echo e($cms['coming_soon_suffix'] ?? ($lang === 'de' ? 'in Arbeit' : 'in progress')); ?></small>
</div>
<div class="coming-strip__row">
<?php foreach (array_slice($comingSoonDisplay, 0, 5) as $cs): ?>
<div class="coming-chip">
<div class="coming-chip__image">
<img src="<?php echo e($cs['hero'] ?? '/assets/placeholder.svg'); ?>" alt="<?php echo e($cs['title'] ?? 'Coming soon'); ?>">
</div>
<div class="coming-chip__title"><?php echo e($cs['title'] ?? 'New recipe'); ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<section class="discover-shell" id="basics">
<div class="discover-shell__main">
<div class="section-header section-header--stack">
<p class="eyebrow"><?php echo e($t['basics']); ?></p>
<h2><?php echo e($t['discover_title']); ?></h2>
<p><?php echo e($t['discover_text']); ?></p>
</div>
<form class="search discover-search" method="get" action="/index.php">
<input type="hidden" name="lang" value="<?php echo e($lang); ?>">
<label class="sr-only" for="recipe-search"><?php echo e($t['search_placeholder']); ?></label>
<input id="recipe-search" type="text" name="q" placeholder="<?php echo e($t['search_placeholder']); ?>" value="<?php echo e($q); ?>">
<?php if ($tag): ?>
<input type="hidden" name="tag" value="<?php echo e($tag); ?>">
<?php endif; ?>
<button type="submit"><?php echo e($t['search_button']); ?></button>
</form>
<div class="discover-stats" aria-label="Recipe overview">
<div class="discover-stat">
<strong><?php echo e((string) $recipeCount); ?></strong>
<span><?php echo e($t['stats_recipes']); ?></span>
</div>
<div class="discover-stat">
<strong><?php echo e(format_minutes($averageMinutes)); ?></strong>
<span><?php echo e($t['stats_average']); ?></span>
</div>
<div class="discover-stat">
<strong><?php echo e((string) $tagCount); ?></strong>
<span><?php echo e($t['stats_tags']); ?></span>
</div>
</div>
<div class="tag-panel">
<div class="tag-panel__head">
<h3><?php echo e($t['browse_tags']); ?></h3>
<?php if ($activeTag): ?>
<a class="tag clear" href="/index.php?lang=<?php echo e($lang); ?>#basics"><?php echo e($t['tag_clear']); ?></a>
<?php endif; ?>
</div>
<div class="tag-row tag-row--panel">
<?php foreach ($allTags as $tTag): ?>
<a class="tag<?php echo strtolower($tTag) === strtolower($activeTag ?? '') ? ' active' : ''; ?>" href="<?php echo e($tagUrl($tTag)); ?>#basics">#<?php echo e($tTag); ?></a>
<?php endforeach; ?>
</div>
</div>
</div>
<?php if ($featured): ?>
<aside class="discover-shell__feature hero-card">
<img src="<?php echo e($featured['hero']); ?>" alt="<?php echo e($featured['title']); ?>">
<div class="hero-card__body">
<p class="pill"><?php echo e($t['featured']); ?></p>
<h3><?php echo e($featured['title']); ?></h3>
<p><?php echo e($featured['description']); ?></p>
<div class="meta">
<span>⏱ <?php echo format_minutes((int) ($featured['total_time'] ?? 0)); ?></span>
<span>🍽 <?php echo e($featured['servings']); ?> <?php echo e($t['servings']); ?></span>
</div>
<a class="button" href="<?php echo e($recipeUrl($featured)); ?>"><?php echo e($t['cook_it']); ?></a>
</div>
</aside>
<?php endif; ?>
</section>
<section class="latest" id="latest">
<div class="section-header section-header--stack">
<h2><?php echo e($t['library_title']); ?></h2>
<p><?php echo $recipeCount; ?><?php echo $q || $tag ? $t['count_suffix_filtered'] : $t['count_suffix_default']; ?></p>
</div>
<?php if (!empty($latestRecipes)): ?>
<div class="grid">
<?php foreach ($latestRecipes as $recipe): ?>
<article class="card">
<a href="<?php echo e($recipeUrl($recipe)); ?>" class="card__image">
<img src="<?php echo e($recipe['hero']); ?>" alt="<?php echo e($recipe['title']); ?>">
<?php if (!empty($recipe['category'])): ?>
<span class="pill pill--ghost"><?php echo e($recipe['category']); ?></span>
<?php endif; ?>
</a>
<div class="card__body">
<h3><a href="<?php echo e($recipeUrl($recipe)); ?>"><?php echo e($recipe['title']); ?></a></h3>
<p><?php echo e($recipe['description']); ?></p>
<div class="meta">
<span>⏱ <?php echo format_minutes((int) ($recipe['total_time'] ?? 0)); ?></span>
<span>🙂 <?php echo e($recipe['difficulty']); ?></span>
</div>
<?php if (!empty($recipe['tags'])): ?>
<div class="tags">
<?php foreach ($recipe['tags'] as $tTag): ?>
<a href="<?php echo e($tagUrl($tTag)); ?>" class="tag">#<?php echo e($tTag); ?></a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</article>
<?php endforeach; ?>
</div>
<?php else: ?>
<article class="empty-state">
<h3><?php echo e($t['empty_title']); ?></h3>
<p><?php echo e($t['empty_text']); ?></p>
<a class="button" href="/index.php?lang=<?php echo e($lang); ?>"><?php echo e($t['tag_clear']); ?></a>
</article>
<?php endif; ?>
</section>
<section class="coming-features" id="coming-features">
<div class="section-header section-header--stack">
<h2><?php echo e($t['coming_features']); ?></h2>
<p><?php echo e($t['coming_features_sub']); ?></p>
</div>
<div class="feature-grid">
<?php foreach ($comingFeatures as $feature): ?>
<article class="feature-card">
<div class="feature-icon" aria-hidden="true">✨</div>
<p><?php echo e($feature); ?></p>
</article>
<?php endforeach; ?>
</div>
</section>
</div><!-- /#recipes-start -->
<?php include __DIR__ . '/partials/footer.php'; ?>