From 52d5b65fa374ef4a7f6fc4287274cf897fe9d228 Mon Sep 17 00:00:00 2001 From: kalugin66 Date: Mon, 27 Jul 2026 01:17:40 +0500 Subject: [PATCH] =?UTF-8?q?=D0=91=D1=80=D0=BE=D0=BD=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/adminBookings/index.js | 13 +- public/admin.html | 314 +++++++++++++++++++++++++-------- 2 files changed, 246 insertions(+), 81 deletions(-) diff --git a/modules/adminBookings/index.js b/modules/adminBookings/index.js index 6fbc8b6..091c05a 100644 --- a/modules/adminBookings/index.js +++ b/modules/adminBookings/index.js @@ -45,6 +45,12 @@ function getBookingsForAdmin(req, res) { const search = req.query.search || ''; const statusFilter = req.query.status || ''; const since = req.query.since || ''; + const sort = req.query.sort || 'created_at'; + const order = (req.query.order || 'desc').toLowerCase(); + + const sortCols = { created_at: 'b.created_at', checkin_date: 'b.checkin_date', total_price: 'b.total_price' }; + const sortCol = sortCols[sort] || 'b.created_at'; + const sortDir = order === 'asc' ? 'ASC' : 'DESC'; let whereClause = '1=1'; const params = []; @@ -56,8 +62,9 @@ function getBookingsForAdmin(req, res) { } if (statusFilter && statusFilter !== 'all') { - whereClause += ' AND b.status = ?'; - params.push(statusFilter); + const statuses = statusFilter.split(','); + whereClause += ' AND b.status IN (' + statuses.map(() => '?').join(',') + ')'; + params.push(...statuses); } if (since) { @@ -79,7 +86,7 @@ function getBookingsForAdmin(req, res) { LEFT JOIN promocodes p ON b.promocode_id = p.id LEFT JOIN rooms r ON b.room_id = r.id WHERE ${whereClause} - ORDER BY b.checkin_date ASC + ORDER BY ${sortCol} ${sortDir} LIMIT ? OFFSET ?`, [...params, limit, offset], (err, rows) => { if (err) { console.error(err); diff --git a/public/admin.html b/public/admin.html index e7aa6f3..f895b50 100644 --- a/public/admin.html +++ b/public/admin.html @@ -85,15 +85,43 @@ body { font-family: 'Inter', sans-serif; background: #f1f5f9; margin: 0; font-si .review-text-full::-webkit-scrollbar-track { background: #e2e8f0; border-radius: 3px; } .review-text-full::-webkit-scrollbar-thumb { background: #94a3b8; border-radius: 3px; } -tr.row-checkin-soon { background: #fffbeb !important; border-left: 4px solid #f59e0b; } -tr.row-checkout-today { background: #fef2f2 !important; border-left: 4px solid #ef4444; } +/* Booking cards */ +.bookings-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; } +.booking-card { background: #fff; border: 1px solid #e2e8f0; border-radius: 12px; overflow: hidden; cursor: pointer; transition: transform 0.2s ease, box-shadow 0.2s ease; display: flex; } +.booking-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,0.1); } +.card-bar { width: 4px; flex-shrink: 0; } +.card-bar-новая { background: #3b82f6; } +.card-bar-оплачена { background: #22c55e; } +.card-bar-зарезервирована { background: #f59e0b; } +.card-bar-заселена { background: #a855f7; } +.card-bar-выехала { background: #94a3b8; } +.card-bar-отменена { background: #ef4444; } +.card-inner { flex: 1; padding: 14px; min-width: 0; } +.card-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } +.card-id { font-size: 0.7rem; color: #94a3b8; } +.card-name { font-size: 1rem; font-weight: 700; color: #0f172a; margin-bottom: 4px; } +.card-phone { font-size: 0.78rem; color: #64748b; margin-bottom: 8px; } +.card-meta { display: flex; gap: 14px; font-size: 0.78rem; color: #475569; margin-bottom: 6px; } +.card-dates { font-size: 0.82rem; color: #0f172a; margin-bottom: 8px; } +.card-nights { font-size: 0.72rem; color: #94a3b8; } +.card-price-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; } +.card-disc-badge { background: #fef3c7; color: #92400e; padding: 1px 7px; border-radius: 10px; font-size: 0.72rem; font-weight: 600; } +.card-base-price { font-size: 0.78rem; color: #94a3b8; text-decoration: line-through; } +.card-total { font-size: 0.95rem; font-weight: 700; color: #0f172a; } +.card-promo { font-size: 0.72rem; color: #6366f1; margin-bottom: 4px; } +.card-comment { font-size: 0.72rem; color: #64748b; background: #f8fafc; padding: 3px 8px; border-radius: 6px; margin-bottom: 8px; } +.card-actions { display: flex; gap: 6px; align-items: center; padding-top: 8px; border-top: 1px solid #f1f5f9; } +.card-soon { background: #fffbeb; } +.card-today { background: #fef2f2; } +.status-tabs { display: flex; gap: 8px; margin-bottom: 16px; } +.status-tab { padding: 7px 18px; border-radius: 20px; border: 1px solid #e2e8f0; background: #fff; font-size: 0.82rem; font-weight: 500; cursor: pointer; transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease; } +.status-tab:hover { border-color: var(--primary); color: var(--primary); } +.status-tab.active { background: var(--primary); color: #fff; border-color: var(--primary); } .filter-bar { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-bottom: 20px; } .filter-bar select, .filter-bar button { padding: 8px 14px; border-radius: 10px; border: 1px solid #e2e8f0; font-size: 0.85rem; background: #fff; cursor: pointer; } .filter-bar select:focus { border-color: var(--primary); outline: none; } .filter-bar .filter-label { font-weight: 600; font-size: 0.85rem; color: #64748b; } -.filter-bar .sort-btn { background: var(--primary); color: #fff; border: none; } -.filter-bar .sort-btn:hover { background: #1d4ed8; } .history-timeline { border-left: 2px solid #e2e8f0; padding-left: 20px; } .history-item { position: relative; padding: 12px 0; border-bottom: 1px solid #f1f5f9; } @@ -308,20 +336,23 @@ tr.row-checkout-today { background: #fef2f2 !important; border-left: 4px solid #
- - Фильтр: - - - Сортировка: - - -
-
- - - -
ИмяТелефонНомерВзр.Дет.ЗаездВыездПожеланияКомментарийБаза (₽)Скидка (%)Сумма скидки (₽)Итого (₽)ПромокодСтатусДействия
+
+
+ + + +
+ + +
+ + + + +
+
+
@@ -871,6 +902,49 @@ tr.row-checkout-today { background: #fef2f2 !important; border-left: 4px solid #
+ +