feat: роли customer/admin, админ-панель, admin@site.com
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<%- include('../partials/layout-start') %>
|
||||
|
||||
<div class="admin-header">
|
||||
<h1>Админ-панель</h1>
|
||||
<nav class="admin-nav">
|
||||
<a href="/admin" class="admin-nav__link admin-nav__link--active">Обзор</a>
|
||||
<a href="/admin/orders" class="admin-nav__link">Заказы</a>
|
||||
<a href="/admin/users" class="admin-nav__link">Пользователи</a>
|
||||
<a href="/admin/products" class="admin-nav__link">Товары</a>
|
||||
<a href="/" class="admin-nav__link">В магазин</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<span class="stat-card__label">Пользователи</span>
|
||||
<strong class="stat-card__value"><%= stats.users %></strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-card__label">Товары</span>
|
||||
<strong class="stat-card__value"><%= stats.products %></strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-card__label">Заказы</span>
|
||||
<strong class="stat-card__value"><%= stats.orders %></strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-card__label">Выручка</span>
|
||||
<strong class="stat-card__value"><%= formatPrice(stats.revenue) %></strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Последние заказы</h2>
|
||||
<% if (!recentOrders.length) { %>
|
||||
<p class="muted">Заказов пока нет.</p>
|
||||
<% } else { %>
|
||||
<table class="cart-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>№</th>
|
||||
<th>Клиент</th>
|
||||
<th>Статус</th>
|
||||
<th>Сумма</th>
|
||||
<th>Дата</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% const statusLabels = { pending: 'Ожидает', paid: 'Оплачен', shipped: 'Отправлен', cancelled: 'Отменён' }; %>
|
||||
<% recentOrders.forEach(o => { %>
|
||||
<tr>
|
||||
<td>#<%= o.id %></td>
|
||||
<td><%= o.customer_name %><br><span class="muted"><%= o.user_email %></span></td>
|
||||
<td><span class="status status--<%= o.status %>"><%= statusLabels[o.status] || o.status %></span></td>
|
||||
<td><%= formatPrice(o.total_cents) %></td>
|
||||
<td><%= new Date(o.created_at).toLocaleString('ru-RU') %></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% } %>
|
||||
|
||||
<%- include('../partials/layout-end') %>
|
||||
@@ -0,0 +1,53 @@
|
||||
<%- include('../partials/layout-start') %>
|
||||
|
||||
<div class="admin-header">
|
||||
<h1>Заказы</h1>
|
||||
<nav class="admin-nav">
|
||||
<a href="/admin" class="admin-nav__link">Обзор</a>
|
||||
<a href="/admin/orders" class="admin-nav__link admin-nav__link--active">Заказы</a>
|
||||
<a href="/admin/users" class="admin-nav__link">Пользователи</a>
|
||||
<a href="/admin/products" class="admin-nav__link">Товары</a>
|
||||
<a href="/" class="admin-nav__link">В магазин</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<% const statusLabels = { pending: 'Ожидает', paid: 'Оплачен', shipped: 'Отправлен', cancelled: 'Отменён' }; %>
|
||||
|
||||
<table class="cart-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>№</th>
|
||||
<th>Клиент</th>
|
||||
<th>Статус</th>
|
||||
<th>Сумма</th>
|
||||
<th>Дата</th>
|
||||
<th>Действие</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% orders.forEach(o => { %>
|
||||
<tr>
|
||||
<td>#<%= o.id %></td>
|
||||
<td>
|
||||
<%= o.customer_name %><br>
|
||||
<span class="muted"><%= o.customer_email %></span>
|
||||
</td>
|
||||
<td><span class="status status--<%= o.status %>"><%= statusLabels[o.status] || o.status %></span></td>
|
||||
<td><%= formatPrice(o.total_cents) %></td>
|
||||
<td><%= new Date(o.created_at).toLocaleString('ru-RU') %></td>
|
||||
<td>
|
||||
<form method="post" action="/admin/orders/<%= o.id %>/status" class="inline-form admin-status-form">
|
||||
<select name="status" class="input input--sm">
|
||||
<% ['pending','paid','shipped','cancelled'].forEach(s => { %>
|
||||
<option value="<%= s %>" <%= o.status === s ? 'selected' : '' %>><%= statusLabels[s] %></option>
|
||||
<% }) %>
|
||||
</select>
|
||||
<button type="submit" class="btn btn--ghost btn--sm">OK</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%- include('../partials/layout-end') %>
|
||||
@@ -0,0 +1,39 @@
|
||||
<%- include('../partials/layout-start') %>
|
||||
|
||||
<div class="admin-header">
|
||||
<h1>Товары</h1>
|
||||
<nav class="admin-nav">
|
||||
<a href="/admin" class="admin-nav__link">Обзор</a>
|
||||
<a href="/admin/orders" class="admin-nav__link">Заказы</a>
|
||||
<a href="/admin/users" class="admin-nav__link">Пользователи</a>
|
||||
<a href="/admin/products" class="admin-nav__link admin-nav__link--active">Товары</a>
|
||||
<a href="/" class="admin-nav__link">В магазин</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<table class="cart-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Название</th>
|
||||
<th>Категория</th>
|
||||
<th>Цена</th>
|
||||
<th>Остаток</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% products.forEach(p => { %>
|
||||
<tr>
|
||||
<td><%= p.id %></td>
|
||||
<td><%= p.name %></td>
|
||||
<td><%= p.category_name || '—' %></td>
|
||||
<td><%= formatPrice(p.price_cents) %></td>
|
||||
<td><%= p.stock %></td>
|
||||
<td><a href="/product/<%= p.slug %>">На сайте</a></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%- include('../partials/layout-end') %>
|
||||
@@ -0,0 +1,39 @@
|
||||
<%- include('../partials/layout-start') %>
|
||||
|
||||
<div class="admin-header">
|
||||
<h1>Пользователи</h1>
|
||||
<nav class="admin-nav">
|
||||
<a href="/admin" class="admin-nav__link">Обзор</a>
|
||||
<a href="/admin/orders" class="admin-nav__link">Заказы</a>
|
||||
<a href="/admin/users" class="admin-nav__link admin-nav__link--active">Пользователи</a>
|
||||
<a href="/admin/products" class="admin-nav__link">Товары</a>
|
||||
<a href="/" class="admin-nav__link">В магазин</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<table class="cart-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Имя</th>
|
||||
<th>Email</th>
|
||||
<th>Роль</th>
|
||||
<th>Регистрация</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% users.forEach(u => { %>
|
||||
<tr>
|
||||
<td><%= u.id %></td>
|
||||
<td><%= u.name %></td>
|
||||
<td><%= u.email %></td>
|
||||
<td>
|
||||
<span class="role-badge role-badge--<%= u.role %>"><%= roleLabels[u.role] || u.role %></span>
|
||||
</td>
|
||||
<td><%= new Date(u.created_at).toLocaleString('ru-RU') %></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%- include('../partials/layout-end') %>
|
||||
Reference in New Issue
Block a user