AdminLTE3

This commit is contained in:
2025-10-26 22:14:47 +09:00
parent 291fc63a4c
commit 9974811a3e
226 changed files with 88284 additions and 3406 deletions

View File

@@ -1,121 +1,206 @@
<!-- Services List -->
<div class="bg-white shadow rounded-lg">
<div class="px-4 py-5 sm:px-6 border-b border-gray-200">
<div class="flex items-center justify-between">
<h3 class="text-lg leading-6 font-medium text-gray-900">
<i class="fas fa-cog mr-2"></i>
Управление услугами
</h3>
<a href="/admin/services/add" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md text-sm font-medium">
<i class="fas fa-plus mr-1"></i>
Добавить услугу
</a>
</div>
</div>
<div class="bg-white shadow overflow-hidden sm:rounded-md">
<ul role="list" class="divide-y divide-gray-200">
<% if (services && services.length > 0) { %>
<% services.forEach(service => { %>
<li>
<div class="px-4 py-4 flex items-center justify-between">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<div class="h-10 w-10 rounded-full bg-blue-100 flex items-center justify-center">
<i class="<%= service.icon || 'fas fa-cog' %> text-blue-600"></i>
</div>
</div>
<div class="ml-4">
<div class="flex items-center">
<div class="text-sm font-medium text-gray-900"><%= service.name %></div>
<% if (service.featured) { %>
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">
<i class="fas fa-star mr-1"></i>
Рекомендуемая
</span>
<% } %>
<% if (!service.isActive) { %>
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
Неактивна
</span>
<% } %>
</div>
<div class="text-sm text-gray-500">
<%= service.category %> •
<% if (service.pricing && service.pricing.basePrice) { %>
от $<%= service.pricing.basePrice %>
<% } %>
</div>
</div>
</div>
<div class="flex items-center space-x-2">
<a href="/services#<%= service.id %>" target="_blank" class="text-blue-600 hover:text-blue-900">
<i class="fas fa-external-link-alt"></i>
</a>
<a href="/admin/services/edit/<%= service.id %>" class="text-indigo-600 hover:text-indigo-900">
<i class="fas fa-edit"></i>
</a>
<button onclick="deleteService('<%= service.id %>')" class="text-red-600 hover:text-red-900">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</li>
<% }) %>
<% } else { %>
<li>
<div class="px-4 py-8 text-center">
<i class="fas fa-cog text-4xl text-gray-300 mb-4"></i>
<p class="text-gray-500">Услуги не найдены</p>
<a href="/admin/services/add" class="mt-2 inline-block bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md text-sm font-medium">
Добавить первую услугу
</a>
</div>
</li>
<% } %>
</ul>
</div>
<!-- Pagination -->
<% if (pagination && pagination.total > 1) { %>
<div class="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6">
<div class="flex-1 flex justify-between sm:hidden">
<% if (pagination.hasPrev) { %>
<a href="?page=<%= pagination.current - 1 %>" class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
Предыдущая
<!-- Content Header (Page header) -->
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1><i class="fas fa-cogs mr-2"></i>Управление услугами</h1>
</div>
<div class="col-sm-6">
<div class="float-sm-right">
<a href="/admin/services/add" class="btn btn-primary">
<i class="fas fa-plus mr-1"></i>
Добавить услугу
</a>
<% } %>
<% if (pagination.hasNext) { %>
<a href="?page=<%= pagination.current + 1 %>" class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
Следующая
</a>
<% } %>
</div>
</div>
</div>
<% } %>
</div>
</div>
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Список услуг</h3>
<div class="card-tools">
<div class="input-group input-group-sm" style="width: 150px;">
<input type="text" name="table_search" class="form-control float-right" placeholder="Поиск">
<div class="input-group-append">
<button type="submit" class="btn btn-default">
<i class="fas fa-search"></i>
</button>
</div>
</div>
</div>
</div>
<div class="card-body table-responsive p-0">
<% if (services && services.length > 0) { %>
<table class="table table-hover text-nowrap">
<thead>
<tr>
<th>ID</th>
<th>Название</th>
<th>Категория</th>
<th>Статус</th>
<th>Цена от</th>
<th>Время</th>
<th>Рекомендуемая</th>
<th>Создано</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
<% services.forEach(service => { %>
<tr>
<td>
<small class="text-muted">#<%= service.id.slice(-8) %></small>
</td>
<td>
<div class="d-flex align-items-center">
<i class="<%= service.icon || 'fas fa-cog' %> mr-2 text-primary"></i>
<strong><%= service.name %></strong>
</div>
<% if (service.shortDescription) { %>
<small class="text-muted d-block">
<%= service.shortDescription.substring(0, 80) %><%= service.shortDescription.length > 80 ? '...' : '' %>
</small>
<% } %>
</td>
<td>
<span class="badge badge-info"><%= service.category %></span>
</td>
<td>
<% if (service.isActive) { %>
<span class="badge badge-success">Активна</span>
<% } else { %>
<span class="badge badge-secondary">Неактивна</span>
<% } %>
</td>
<td>
<% if (service.pricing && service.pricing.basePrice) { %>
<span class="text-success font-weight-bold">$<%= service.pricing.basePrice %></span>
<% } else { %>
<span class="text-muted">Не указана</span>
<% } %>
</td>
<td>
<% if (service.estimatedTime) { %>
<i class="fas fa-clock mr-1 text-info"></i>
<%= service.estimatedTime %>
<% } else { %>
<span class="text-muted">-</span>
<% } %>
</td>
<td>
<% if (service.featured) { %>
<i class="fas fa-star text-warning" title="Рекомендуемая услуга"></i>
<% } else { %>
<i class="far fa-star text-muted"></i>
<% } %>
</td>
<td>
<small class="text-muted">
<%= new Date(service.createdAt).toLocaleDateString('ru-RU') %>
</small>
</td>
<td>
<div class="btn-group btn-group-sm">
<a href="/services#<%= service.id %>" target="_blank" class="btn btn-info btn-sm" title="Посмотреть на сайте">
<i class="fas fa-eye"></i>
</a>
<a href="/admin/services/edit/<%= service.id %>" class="btn btn-warning btn-sm" title="Редактировать">
<i class="fas fa-edit"></i>
</a>
<button onclick="deleteService('<%= service.id %>')" class="btn btn-danger btn-sm" title="Удалить">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
<% }) %>
</tbody>
</table>
<% } else { %>
<div class="p-4 text-center">
<i class="fas fa-cogs text-muted" style="font-size: 4rem;"></i>
<h4 class="mt-3 text-muted">Услуги не найдены</h4>
<p class="text-muted">Добавьте первую услугу для начала работы</p>
<a href="/admin/services/add" class="btn btn-primary">
<i class="fas fa-plus mr-1"></i>
Добавить услугу
</a>
</div>
<% } %>
</div>
<!-- Pagination -->
<% if (pagination && pagination.total > 1) { %>
<div class="card-footer clearfix">
<ul class="pagination pagination-sm m-0 float-right">
<% if (pagination.hasPrev) { %>
<li class="page-item">
<a class="page-link" href="?page=<%= pagination.current - 1 %>">&laquo;</a>
</li>
<% } %>
<% for (let i = 1; i <= pagination.total; i++) { %>
<li class="page-item <%= i === pagination.current ? 'active' : '' %>">
<a class="page-link" href="?page=<%= i %>"><%= i %></a>
</li>
<% } %>
<% if (pagination.hasNext) { %>
<li class="page-item">
<a class="page-link" href="?page=<%= pagination.current + 1 %>">&raquo;</a>
</li>
<% } %>
</ul>
</div>
<% } %>
</div>
</div>
</div>
</div>
</section>
<script>
function deleteService(id) {
if (confirm('Вы уверены, что хотите удалить эту услугу?')) {
fetch(`/api/admin/services/${id}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Ошибка при удалении услуги');
}
})
.catch(error => {
console.error('Error:', error);
alert('Ошибка при удалении услуги');
});
}
Swal.fire({
title: 'Удалить услугу?',
text: 'Это действие невозможно отменить!',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#3085d6',
confirmButtonText: 'Да, удалить!',
cancelButtonText: 'Отмена'
}).then((result) => {
if (result.isConfirmed) {
fetch(`/api/admin/services/${id}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
location.reload();
});
} else {
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
}
})
.catch(error => {
console.error('Error:', error);
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
});
}
});
}
</script>