<?php
require_once __DIR__ . '/../config/bootstrap.php';
require_once __DIR__ . '/../config/auth.php';
require_once __DIR__ . '/../config/functions.php';
if (!is_admin()) {
http_response_code(403);
die("Доступ запрещён");
}
$order_id = (int)($_GET['id'] ?? 0);
if ($order_id <= 0) {
die("Неверный ID заказа");
}
try {
$stmt = $pdo->prepare("
SELECT o.*, u.name, u.email, u.phone,
d.code as discount_code, d.percent as discount_percent
FROM orders o
JOIN users u ON o.user_id = u.id
LEFT JOIN discounts d ON o.discount_id = d.id
WHERE o.id = ?
");
$stmt->execute([$order_id]);
$order = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$order) {
die("Заказ не найден");
}
$stmt = $pdo->prepare("
SELECT oi.*, p.filename, f.name as format_name, f.price as format_price
FROM order_items oi
LEFT JOIN photos p ON oi.photo_id = p.id
LEFT JOIN formats f ON oi.format_id = f.id
WHERE oi.order_id = ?
ORDER BY oi.id
");
$stmt->execute([$order_id]);
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
die("Ошибка загрузки данных заказа: " . htmlspecialchars($e->getMessage()));
}
require_once __DIR__ . '/../includes/header.php';
?>
<div class="container my-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="mb-0">
<i class="bi bi-receipt"></i> Заказ #<?= e($order['id']) ?>
</h1>
<div>
<a href="/admin/orders.php" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Назад к списку
</a>
<button class="btn btn-danger" onclick="deleteOrder(<?= e($order['id']) ?>)">
<i class="bi bi-trash"></i> Удалить
</button>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<div class="glass p-4 card-ui fade-in mb-4">
<h5 class="fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-info-circle"></i> Информация о заказе
</h5>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<strong><i class="bi bi-person"></i> Клиент:</strong><br>
<div class="ps-3">
<?= e($order['name']) ?><br>
<small class="text-muted"><?= e($order['email']) ?></small>
</div>
</div>
<div class="mb-3">
<strong><i class="bi bi-telephone"></i> Телефон:</strong><br>
<div class="ps-3"><?= e($order['phone'] ?? 'не указан') ?></div>
</div>
<div class="mb-3">
<strong><i class="bi bi-calendar"></i> Дата заказа:</strong><br>
<div class="ps-3"><?= date('d.m.Y H:i', strtotime($order['created_at'])) ?></div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<strong><i class="bi bi-geo-alt"></i> Адрес доставки:</strong><br>
<div class="ps-3"><?= nl2br(e($order['address'])) ?></div>
</div>
<div class="mb-3">
<strong><i class="bi bi-chat-text"></i> Комментарий:</strong><br>
<div class="ps-3"><?= nl2br(e($order['comment'] ?? 'нет')) ?></div>
</div>
<div class="mb-3">
<strong><i class="bi bi-tag"></i> Скидка:</strong><br>
<div class="ps-3">
<?php if ($order['discount_code']): ?>
<span class="badge bg-success">
<?= e($order['discount_code']) ?> (<?= e($order['discount_percent']) ?>%)
</span>
<?php else: ?>
<span class="text-muted">нет</span>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div class="mt-3">
<strong><i class="bi bi-flag"></i> Статус заказа:</strong>
<div class="d-flex align-items-center mt-2">
<select class="form-select w-auto" id="status-select"
onchange="updateStatus(<?= e($order['id']) ?>, this.value)">
<?php
$statuses = [
'Новый' => 'bg-secondary',
'В обработке' => 'bg-info',
'Печать' => 'bg-warning',
'Доставляется' => 'bg-primary',
'Доставлен' => 'bg-success',
'Отменен' => 'bg-danger'
];
foreach ($statuses as $status => $class):
$selected = ($order['status'] ?? 'Новый') === $status ? 'selected' : '';
?>
<option value="<?= e($status) ?>" <?= $selected ?>>
<?= e($status) ?>
</option>
<?php endforeach; ?>
</select>
<span class="badge <?= $statuses[$order['status'] ?? 'Новый'] ?> ms-3">
<?= e($order['status'] ?? 'Новый') ?>
</span>
</div>
</div>
</div>
<div class="glass p-4 card-ui fade-in">
<h5 class="fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-cart-check"></i> Товары в заказе
</h5>
<?php if (empty($items)): ?>
<div class="alert alert-warning">
<i class="bi bi-exclamation-circle"></i> В заказе нет товаров
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>Фото</th>
<th>Формат</th>
<th class="text-center">Кол-во</th>
<th class="text-end">Цена за шт.</th>
<th class="text-end">Сумма</th>
</tr>
</thead>
<tbody>
<?php
$total = 0;
foreach ($items as $item):
$item_total = ($item['price'] ?? 0) * ($item['quantity'] ?? 1);
$total += $item_total;
?>
<tr>
<td>
<?php if (!empty($item['filename'])):
$photo_url = BASE_URL . 'uploads/photos/' . $item['filename'];
$photo_path = UPLOAD_DIR . 'photos/' . $item['filename'];
?>
<?php if (file_exists($photo_path)): ?>
<a href="<?= e($photo_url) ?>" target="_blank">
<img src="<?= e($photo_url) ?>"
alt="Фото"
class="rounded"
style="width: 60px; height: 60px; object-fit: cover;">
</a>
<?php else: ?>
<div class="bg-light rounded d-flex align-items-center justify-content-center"
style="width: 60px; height: 60px;">
<i class="bi bi-image text-muted"></i>
</div>
<?php endif; ?>
<?php else: ?>
<div class="bg-light rounded d-flex align-items-center justify-content-center"
style="width: 60px; height: 60px;">
<i class="bi bi-image text-muted"></i>
</div>
<?php endif; ?>
</td>
<td>
<div class="fw-bold"><?= e($item['format_name'] ?? 'Не указан') ?></div>
<?php if (!empty($item['photo_id'])): ?>
<small class="text-muted">ID фото: <?= e($item['photo_id']) ?></small>
<?php endif; ?>
</td>
<td class="text-center">
<span class="badge bg-primary rounded-pill">
<?= e($item['quantity'] ?? 1) ?> шт.
</span>
</td>
<td class="text-end">
<?= number_format($item['price'] ?? 0, 2) ?> ₽
</td>
<td class="text-end fw-bold">
<?= number_format($item_total, 2) ?> ₽
</td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot class="table-group-divider">
<tr>
<td colspan="4" class="text-end fw-bold">Сумма заказа:</td>
<td class="text-end fw-bold"><?= number_format($total, 2) ?> ₽</td>
</tr>
<?php if ($order['discount_amount'] > 0): ?>
<tr class="text-success">
<td colspan="4" class="text-end fw-bold">
Скидка (<?= e($order['discount_percent'] ?? 0) ?>%):
</td>
<td class="text-end fw-bold">-<?= number_format($order['discount_amount'] ?? 0, 2) ?> ₽</td>
</tr>
<?php endif; ?>
<tr class="table-active">
<td colspan="4" class="text-end fw-bold fs-5">Итого к оплате:</td>
<td class="text-end fw-bold fs-5 text-primary">
<?= number_format($order['total'] ?? $total, 2) ?> ₽
</td>
</tr>
</tfoot>
</table>
</div>
<?php endif; ?>
</div>
</div>
<div class="col-lg-4">
<!-- Действия -->
<div class="glass p-4 card-ui fade-in mb-4">
<h5 class="fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-lightning-charge"></i> Действия
</h5>
<div class="d-grid gap-2">
<button class="btn btn-success" onclick="markAsCompleted(<?= e($order['id']) ?>)">
<i class="bi bi-check-circle"></i> Отметить как выполненный
</button>
<button class="btn btn-warning" onclick="printOrder(<?= e($order['id']) ?>)">
<i class="bi bi-printer"></i> Распечатать заказ
</button>
<a href="mailto:<?= e($order['email']) ?>?subject=Заказ%20#<?= e($order['id']) ?>"
class="btn btn-outline-primary">
<i class="bi bi-envelope"></i> Написать клиенту
</a>
<a href="tel:<?= e($order['phone'] ?? '') ?>"
class="btn btn-outline-secondary <?= empty($order['phone']) ? 'disabled' : '' ?>">
<i class="bi bi-telephone"></i> Позвонить клиенту
</a>
</div>
</div>
<div class="glass p-4 card-ui fade-in">
<h5 class="fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-bar-chart"></i> Статистика
</h5>
<div class="list-group list-group-flush">
<div class="list-group-item d-flex justify-content-between">
<span>ID заказа:</span>
<strong>#<?= e($order['id']) ?></strong>
</div>
<div class="list-group-item d-flex justify-content-between">
<span>Клиент ID:</span>
<strong><?= e($order['user_id']) ?></strong>
</div>
<div class="list-group-item d-flex justify-content-between">
<span>Товаров:</span>
<strong><?= count($items) ?> шт.</strong>
</div>
<div class="list-group-item d-flex justify-content-between">
<span>Сумма заказа:</span>
<strong><?= number_format($order['total'], 2) ?> ₽</strong>
</div>
<div class="list-group-item d-flex justify-content-between">
<span>Скидка:</span>
<strong><?= number_format($order['discount_amount'] ?? 0, 2) ?> ₽</strong>
</div>
<div class="list-group-item d-flex justify-content-between">
<span>Статус:</span>
<span class="badge <?= $statuses[$order['status'] ?? 'Новый'] ?>">
<?= e($order['status'] ?? 'Новый') ?>
</span>
</div>
</div>
</div>
<div class="glass p-4 card-ui fade-in mt-4">
<h5 class="fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-truck"></i> Доставка
</h5>
<div class="alert alert-info">
<i class="bi bi-info-circle"></i>
<div class="small">
<strong>Информация:</strong><br>
• Адрес: <?= e($order['address']) ?><br>
• Телефон: <?= e($order['phone'] ?? 'не указан') ?><br>
• Комментарий: <?= e($order['comment'] ?? 'нет') ?>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function updateStatus(orderId, status) {
if (!confirm("Изменить статус заказа #" + orderId + " на \"" + status + "\"?")) {
document.getElementById('status-select').value = '<?= e($order['status'] ?? 'Новый') ?>';
return;
}
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '<?= $_SESSION['csrf_token'] ?? '' ?>';
fetch('/ajax/admin/update_status.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({
id: orderId,
status: status,
csrf: csrfToken
})
})
.then(res => res.json())
.then(data => {
if (data.success) {
alert('Статус успешно обновлён');
location.reload();
} else {
alert('Ошибка: ' + (data.error || 'Неизвестная ошибка'));
location.reload();
}
})
.catch(error => {
console.error('Error:', error);
alert('Ошибка соединения с сервером');
location.reload();
});
}
function deleteOrder(orderId) {
if (!confirm("Вы уверены, что хотите удалить заказ #" + orderId + "? Это действие нельзя отменить.")) {
return;
}
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '<?= $_SESSION['csrf_token'] ?? '' ?>';
fetch('/ajax/admin/delete_order.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({
id: orderId,
csrf: csrfToken
})
})
.then(res => res.json())
.then(data => {
if (data.success) {
alert('Заказ удалён');
window.location.href = '/admin/orders.php';
} else {
alert('Ошибка: ' + (data.error || 'Неизвестная ошибка'));
}
})
.catch(error => {
console.error('Error:', error);
alert('Ошибка соединения с сервером');
});
}
function markAsCompleted(orderId) {
if (!confirm("Отметить заказ #" + orderId + " как выполненный?")) {
return;
}
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '<?= $_SESSION['csrf_token'] ?? '' ?>';
fetch('/ajax/admin/update_status.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({
id: orderId,
status: 'Доставлен',
csrf: csrfToken
})
})
.then(res => res.json())
.then(data => {
if (data.success) {
alert('Заказ отмечен как выполненный');
location.reload();
} else {
alert('Ошибка: ' + (data.error || 'Неизвестная ошибка'));
}
})
.catch(error => {
console.error('Error:', error);
alert('Ошибка соединения с сервером');
});
}
function printOrder(orderId) {
window.open('/admin/order_print.php?id=' + orderId, '_blank');
}
if (!document.querySelector('meta[name="csrf-token"]')) {
const meta = document.createElement('meta');
meta.name = 'csrf-token';
meta.content = '<?= $_SESSION['csrf_token'] ?? '' ?>';
document.head.appendChild(meta);
}
</script>
<?php
require_once __DIR__ . '/../includes/footer.php';
?>