Add minimalist editable CMS content section

This commit is contained in:
2026-03-24 15:57:37 +01:00
parent 8170ce7ece
commit 3378427e07
4 changed files with 185 additions and 34 deletions
+126 -2
View File
@@ -57,7 +57,9 @@ $editing = null;
$editIndex = null;
$editingEn = [];
$editingDe = [];
$view = (isset($_GET['view']) && $_GET['view'] === 'settings') ? 'settings' : 'recipes';
$allowedViews = ['recipes', 'settings', 'content'];
$view = $_GET['view'] ?? 'recipes';
$view = in_array($view, $allowedViews, true) ? $view : 'recipes';
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(16));
@@ -163,6 +165,59 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'save_
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'save_content') {
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['token'] ?? '')) {
$errors[] = 'Invalid form token, please retry.';
} else {
$cms = $siteSettings['cms'] ?? ['de' => [], 'en' => []];
$contentKeys = [
'landing_eyebrow',
'landing_line_1',
'landing_line_2',
'landing_line_3',
'landing_cta',
'coming_soon_badge',
'coming_soon_suffix',
'footer_designed_by',
'footer_contact_label',
'home_title',
'home_description',
'coming_feature_1',
'coming_feature_2',
'coming_feature_3',
];
foreach (['de', 'en'] as $langKey) {
foreach ($contentKeys as $field) {
$postKey = $field . '_' . $langKey;
$cms[$langKey][$field] = trim((string) ($_POST[$postKey] ?? ($cms[$langKey][$field] ?? '')));
}
}
$requiredCms = ['landing_line_1', 'landing_line_2', 'landing_line_3', 'landing_cta', 'home_title', 'home_description'];
foreach ($requiredCms as $field) {
if (($cms['de'][$field] ?? '') === '' && ($cms['en'][$field] ?? '') === '') {
$errors[] = "Content field \"$field\" needs DE or EN value.";
}
if (($cms['de'][$field] ?? '') === '') {
$cms['de'][$field] = $cms['en'][$field] ?? '';
}
if (($cms['en'][$field] ?? '') === '') {
$cms['en'][$field] = $cms['de'][$field] ?? '';
}
}
if (empty($errors)) {
$siteSettings['cms'] = $cms;
if (save_site_settings($siteSettings)) {
$message = 'Content saved.';
} else {
$errors[] = 'Could not save CMS content. Check permissions on data/site.json.';
}
}
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delete') {
$slugDel = trim($_POST['slug'] ?? '');
$before = count($allRecipes);
@@ -350,6 +405,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
<div style="display:flex; gap:8px; align-items:center;">
<div class="admin-tabs">
<a href="/admin.php" class="<?php echo $view === 'recipes' ? 'active' : ''; ?>">Recipes</a>
<a href="/admin.php?view=content" class="<?php echo $view === 'content' ? 'active' : ''; ?>">Content</a>
<a href="/admin.php?view=settings" class="<?php echo $view === 'settings' ? 'active' : ''; ?>">Site settings</a>
</div>
<a class="button" href="/index.php" style="padding:10px 14px;">View site</a>
@@ -368,7 +424,75 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
</div>
<?php endif; ?>
<?php if ($view === 'settings'): ?>
<?php if ($view === 'content'): ?>
<?php $cms = $siteSettings['cms']; ?>
<form class="admin-form" method="post">
<input type="hidden" name="action" value="save_content">
<input type="hidden" name="token" value="<?php echo e($_SESSION['csrf_token']); ?>">
<h2>Homepage Content (DE)</h2>
<label>Landing eyebrow</label>
<input type="text" name="landing_eyebrow_de" value="<?php echo e($cms['de']['landing_eyebrow'] ?? ''); ?>">
<div class="row">
<div><label>Landing line 1 *</label><input type="text" name="landing_line_1_de" value="<?php echo e($cms['de']['landing_line_1'] ?? ''); ?>" required></div>
<div><label>Landing line 2 *</label><input type="text" name="landing_line_2_de" value="<?php echo e($cms['de']['landing_line_2'] ?? ''); ?>" required></div>
</div>
<div class="row">
<div><label>Landing line 3 *</label><input type="text" name="landing_line_3_de" value="<?php echo e($cms['de']['landing_line_3'] ?? ''); ?>" required></div>
<div><label>Landing CTA *</label><input type="text" name="landing_cta_de" value="<?php echo e($cms['de']['landing_cta'] ?? ''); ?>" required></div>
</div>
<div class="row">
<div><label>Coming soon badge</label><input type="text" name="coming_soon_badge_de" value="<?php echo e($cms['de']['coming_soon_badge'] ?? ''); ?>"></div>
<div><label>Coming soon suffix</label><input type="text" name="coming_soon_suffix_de" value="<?php echo e($cms['de']['coming_soon_suffix'] ?? ''); ?>"></div>
</div>
<label>Homepage title *</label>
<input type="text" name="home_title_de" value="<?php echo e($cms['de']['home_title'] ?? ''); ?>" required>
<label>Homepage meta description *</label>
<textarea name="home_description_de" required><?php echo e($cms['de']['home_description'] ?? ''); ?></textarea>
<h3>Coming soon feature bullets</h3>
<div class="row">
<div><input type="text" name="coming_feature_1_de" value="<?php echo e($cms['de']['coming_feature_1'] ?? ''); ?>"></div>
<div><input type="text" name="coming_feature_2_de" value="<?php echo e($cms['de']['coming_feature_2'] ?? ''); ?>"></div>
<div><input type="text" name="coming_feature_3_de" value="<?php echo e($cms['de']['coming_feature_3'] ?? ''); ?>"></div>
</div>
<div class="row">
<div><label>Footer line</label><input type="text" name="footer_designed_by_de" value="<?php echo e($cms['de']['footer_designed_by'] ?? ''); ?>"></div>
<div><label>Footer contact label</label><input type="text" name="footer_contact_label_de" value="<?php echo e($cms['de']['footer_contact_label'] ?? ''); ?>"></div>
</div>
<hr>
<h2>Homepage Content (EN)</h2>
<label>Landing eyebrow</label>
<input type="text" name="landing_eyebrow_en" value="<?php echo e($cms['en']['landing_eyebrow'] ?? ''); ?>">
<div class="row">
<div><label>Landing line 1 *</label><input type="text" name="landing_line_1_en" value="<?php echo e($cms['en']['landing_line_1'] ?? ''); ?>" required></div>
<div><label>Landing line 2 *</label><input type="text" name="landing_line_2_en" value="<?php echo e($cms['en']['landing_line_2'] ?? ''); ?>" required></div>
</div>
<div class="row">
<div><label>Landing line 3 *</label><input type="text" name="landing_line_3_en" value="<?php echo e($cms['en']['landing_line_3'] ?? ''); ?>" required></div>
<div><label>Landing CTA *</label><input type="text" name="landing_cta_en" value="<?php echo e($cms['en']['landing_cta'] ?? ''); ?>" required></div>
</div>
<div class="row">
<div><label>Coming soon badge</label><input type="text" name="coming_soon_badge_en" value="<?php echo e($cms['en']['coming_soon_badge'] ?? ''); ?>"></div>
<div><label>Coming soon suffix</label><input type="text" name="coming_soon_suffix_en" value="<?php echo e($cms['en']['coming_soon_suffix'] ?? ''); ?>"></div>
</div>
<label>Homepage title *</label>
<input type="text" name="home_title_en" value="<?php echo e($cms['en']['home_title'] ?? ''); ?>" required>
<label>Homepage meta description *</label>
<textarea name="home_description_en" required><?php echo e($cms['en']['home_description'] ?? ''); ?></textarea>
<h3>Coming soon feature bullets</h3>
<div class="row">
<div><input type="text" name="coming_feature_1_en" value="<?php echo e($cms['en']['coming_feature_1'] ?? ''); ?>"></div>
<div><input type="text" name="coming_feature_2_en" value="<?php echo e($cms['en']['coming_feature_2'] ?? ''); ?>"></div>
<div><input type="text" name="coming_feature_3_en" value="<?php echo e($cms['en']['coming_feature_3'] ?? ''); ?>"></div>
</div>
<div class="row">
<div><label>Footer line</label><input type="text" name="footer_designed_by_en" value="<?php echo e($cms['en']['footer_designed_by'] ?? ''); ?>"></div>
<div><label>Footer contact label</label><input type="text" name="footer_contact_label_en" value="<?php echo e($cms['en']['footer_contact_label'] ?? ''); ?>"></div>
</div>
<button type="submit" class="button" style="width: fit-content;">Save content</button>
</form>
<?php elseif ($view === 'settings'): ?>
<?php $im = $siteSettings['imprint']; $pv = $siteSettings['privacy']; ?>
<form class="admin-form" method="post">
<input type="hidden" name="action" value="save_settings">