189 lines
8.7 KiB
PHP
189 lines
8.7 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../../inc/auth.php';
|
|
require_once __DIR__ . '/../../inc/functions.php';
|
|
|
|
$session = auth_require('owner');
|
|
$pdo = getDB();
|
|
$message = '';
|
|
|
|
// Create / Update
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$id = (int)($_POST['id'] ?? 0);
|
|
$title = trim($_POST['title'] ?? '');
|
|
$text = trim($_POST['text'] ?? '');
|
|
$effect = trim($_POST['effect'] ?? '');
|
|
$sort = (int)($_POST['sort_order'] ?? 0);
|
|
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
|
$csrf = $_POST['csrf_token'] ?? '';
|
|
|
|
if (!auth_csrf_verify($csrf)) {
|
|
$message = 'Ошибка безопасности.';
|
|
} elseif ($title === '' || $text === '' || $effect === '') {
|
|
$message = 'Заполните все обязательные поля.';
|
|
} else {
|
|
try {
|
|
if ($id > 0) {
|
|
$stmt = $pdo->prepare("UPDATE cases SET title=?, text=?, effect=?, sort_order=?, is_active=? WHERE id=?");
|
|
$stmt->execute([$title, $text, $effect, $sort, $isActive, $id]);
|
|
} else {
|
|
$stmt = $pdo->prepare("INSERT INTO cases (title, text, effect, sort_order, is_active) VALUES (?, ?, ?, ?, ?)");
|
|
$stmt->execute([$title, $text, $effect, $sort, $isActive]);
|
|
}
|
|
$message = $id > 0 ? 'Пример обновлён.' : 'Пример добавлен.';
|
|
} catch (\Exception $e) {
|
|
$message = 'Ошибка БД: ' . $e->getMessage();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Delete
|
|
if (isset($_GET['delete'])) {
|
|
$did = (int)$_GET['delete'];
|
|
$csrf = $_GET['csrf'] ?? '';
|
|
if (auth_csrf_verify($csrf)) {
|
|
$stmt = $pdo->prepare("DELETE FROM cases WHERE id=?");
|
|
$stmt->execute([$did]);
|
|
header('Location: /service/pages/owner/cases.php');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Edit mode
|
|
$editId = (int)($_GET['edit'] ?? 0);
|
|
$editRow = null;
|
|
if ($editId > 0) {
|
|
$stmt = $pdo->prepare("SELECT * FROM cases WHERE id=?");
|
|
$stmt->execute([$editId]);
|
|
$editRow = $stmt->fetch();
|
|
}
|
|
|
|
// List
|
|
$stmt = $pdo->query("SELECT * FROM cases ORDER BY sort_order ASC, id ASC");
|
|
$cases = $stmt->fetchAll();
|
|
|
|
if (empty($_SESSION['csrf_token'])) {
|
|
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
|
}
|
|
|
|
require __DIR__ . '/../../inc/header.php';
|
|
?>
|
|
|
|
<div class="cases-admin">
|
|
<div class="page-header">
|
|
<h1>Примеры из практики</h1>
|
|
<p class="page-subtitle">Управляйте каруселью на главной странице сайта.</p>
|
|
</div>
|
|
|
|
<?php if ($message): ?>
|
|
<div class="alert <?= strpos($message, 'Ошибка') === false ? 'alert-success' : 'alert-danger' ?>"><?= htmlspecialchars($message) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="cases-admin__form">
|
|
<h2><?= $editRow ? 'Редактировать' : 'Добавить пример' ?></h2>
|
|
<form method="post">
|
|
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
|
|
<input type="hidden" name="id" value="<?= $editRow ? $editRow['id'] : 0 ?>">
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Заголовок *</label>
|
|
<input type="text" name="title" value="<?= htmlspecialchars($editRow ? $editRow['title'] : '') ?>" required maxlength="500">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Порядок</label>
|
|
<input type="number" name="sort_order" value="<?= $editRow ? $editRow['sort_order'] : 0 ?>" min="0">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Описание проблемы *</label>
|
|
<textarea name="text" rows="3" required><?= htmlspecialchars($editRow ? $editRow['text'] : '') ?></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Эффект *</label>
|
|
<textarea name="effect" rows="2" required><?= htmlspecialchars($editRow ? $editRow['effect'] : '') ?></textarea>
|
|
</div>
|
|
|
|
<div class="form-group form-group--checkbox">
|
|
<input type="checkbox" id="is_active" name="is_active" <?= (!$editRow || $editRow['is_active']) ? 'checked' : '' ?>>
|
|
<label for="is_active">Активен</label>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="submit" class="btn btn-primary"><?= $editRow ? 'Сохранить' : 'Добавить' ?></button>
|
|
<?php if ($editRow): ?>
|
|
<a href="/service/pages/owner/cases.php" class="btn btn-secondary">Отмена</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:40px">#</th>
|
|
<th>Заголовок</th>
|
|
<th style="width:60px">Порядок</th>
|
|
<th style="width:70px">Статус</th>
|
|
<th style="width:120px">Действия</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($cases)): ?>
|
|
<tr><td colspan="5" style="text-align:center;padding:24px;color:var(--text-muted);">Нет примеров</td></tr>
|
|
<?php endif; ?>
|
|
<?php foreach ($cases as $c): ?>
|
|
<tr>
|
|
<td><?= $c['id'] ?></td>
|
|
<td><?= htmlspecialchars($c['title']) ?></td>
|
|
<td><?= $c['sort_order'] ?></td>
|
|
<td>
|
|
<span class="badge <?= $c['is_active'] ? 'badge-green' : 'badge-gray' ?>">
|
|
<?= $c['is_active'] ? 'Да' : 'Нет' ?>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<a href="?edit=<?= $c['id'] ?>" class="btn btn-sm btn-info" data-tooltip="Редактировать">✎</a>
|
|
<a href="?delete=<?= $c['id'] ?>&csrf=<?= urlencode($_SESSION['csrf_token']) ?>" class="btn btn-sm btn-danger" onclick="return confirm('Удалить?')" data-tooltip="Удалить">✕</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.cases-admin { padding: 24px; }
|
|
.page-header { margin-bottom: 24px; }
|
|
.page-header h1 { font-size: 24px; color: var(--text-primary); margin-bottom: 8px; }
|
|
.page-subtitle { font-size: 13px; color: var(--text-muted); }
|
|
.cases-admin__form { background: var(--bg-card); padding: 24px; border-radius: 12px; margin-bottom: 32px; border: 1px solid var(--border); }
|
|
.cases-admin__form h2 { font-size: 18px; margin-bottom: 16px; color: var(--text-primary); }
|
|
.form-row { display: grid; grid-template-columns: 1fr 100px; gap: 16px; }
|
|
.form-group { margin-bottom: 14px; }
|
|
.form-group label { display: block; margin-bottom: 4px; font-weight: 600; font-size: 13px; color: var(--text-secondary); }
|
|
.form-group input, .form-group textarea { width: 100%; padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px; font-size: 14px; font-family: inherit; background: var(--bg-input); color: var(--text-primary); }
|
|
.form-group input:focus, .form-group textarea:focus { outline: none; border-color: var(--accent); }
|
|
.form-group--checkbox { display: flex; align-items: center; gap: 8px; color: var(--text-secondary); }
|
|
.form-group--checkbox input { width: auto; }
|
|
.form-actions { display: flex; gap: 10px; margin-top: 16px; }
|
|
.table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
|
.table th, .table td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--border); color: var(--text-primary); }
|
|
.table th { font-weight: 600; color: var(--text-muted); font-size: 11px; text-transform: uppercase; background: var(--bg-card); }
|
|
.badge { display: inline-block; padding: 3px 10px; border-radius: 12px; font-size: 11px; font-weight: 600; }
|
|
.badge-green { background: rgba(34,197,94,0.2); color: var(--success); }
|
|
.badge-gray { background: rgba(136,153,187,0.2); color: var(--text-secondary); }
|
|
.btn-sm { padding: 4px 10px; font-size: 13px; border: none; border-radius: 4px; cursor: pointer; text-decoration: none; }
|
|
.btn-info { background: var(--accent); color: #fff; }
|
|
.btn-danger { background: var(--danger); color: #fff; }
|
|
.alert { padding: 12px 16px; border-radius: 8px; margin-bottom: 16px; font-size: 13px; }
|
|
.alert-success { background: rgba(34,197,94,0.15); color: var(--success); border: 1px solid rgba(34,197,94,0.3); }
|
|
.alert-danger { background: rgba(239,68,68,0.15); color: var(--danger); border: 1px solid rgba(239,68,68,0.3); }
|
|
.table-responsive { overflow-x: auto; }
|
|
</style>
|
|
|
|
<?php require __DIR__ . '/../../inc/footer.php'; ?>
|