Files
sst_site/.history/views/admin/services/edit_20251026221035.ejs
2025-10-26 22:14:47 +09:00

411 lines
22 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 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-edit mr-2"></i>Редактировать услугу</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
<li class="breadcrumb-item"><a href="/admin/services">Услуги</a></li>
<li class="breadcrumb-item active">Редактировать</li>
</ol>
</div>
</div>
</div>
</div>
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<form id="serviceForm">
<input type="hidden" id="serviceId" value="<%= service.id %>">
<div class="row">
<div class="col-md-8">
<!-- Basic Information -->
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Основная информация</h3>
</div>
<div class="card-body">
<div class="form-group">
<label for="name">Название услуги *</label>
<input type="text" class="form-control" id="name" name="name" value="<%= service.name %>" required>
</div>
<div class="form-group">
<label for="shortDescription">Краткое описание</label>
<textarea class="form-control" id="shortDescription" name="shortDescription" rows="2"><%= service.shortDescription || '' %></textarea>
</div>
<div class="form-group">
<label for="description">Полное описание</label>
<textarea class="form-control" id="description" name="description" rows="6"><%= service.description || '' %></textarea>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="category">Категория *</label>
<select class="form-control" id="category" name="category" required>
<option value="">Выберите категорию</option>
<option value="web-development" <%= service.category === 'web-development' ? 'selected' : '' %>>Веб-разработка</option>
<option value="mobile-development" <%= service.category === 'mobile-development' ? 'selected' : '' %>>Мобильная разработка</option>
<option value="ui-ux-design" <%= service.category === 'ui-ux-design' ? 'selected' : '' %>>UI/UX Дизайн</option>
<option value="consulting" <%= service.category === 'consulting' ? 'selected' : '' %>>Консалтинг</option>
<option value="support" <%= service.category === 'support' ? 'selected' : '' %>>Поддержка</option>
<option value="other" <%= service.category === 'other' ? 'selected' : '' %>>Другое</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="icon">Иконка</label>
<input type="text" class="form-control" id="icon" name="icon" value="<%= service.icon || 'fas fa-cog' %>">
<small class="form-text text-muted">FontAwesome класс иконки</small>
</div>
</div>
</div>
<div class="form-group">
<label for="estimatedTime">Время выполнения</label>
<input type="text" class="form-control" id="estimatedTime" name="estimatedTime" value="<%= service.estimatedTime || '' %>">
</div>
</div>
</div>
<!-- Pricing -->
<div class="card card-info">
<div class="card-header">
<h3 class="card-title">Ценообразование</h3>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="basePrice">Базовая цена ($)</label>
<input type="number" class="form-control" id="basePrice" name="pricing[basePrice]" value="<%= service.pricing?.basePrice || '' %>" min="0" step="0.01">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="currency">Валюта</label>
<select class="form-control" id="currency" name="pricing[currency]">
<option value="USD" <%= service.pricing?.currency === 'USD' ? 'selected' : '' %>>USD ($)</option>
<option value="EUR" <%= service.pricing?.currency === 'EUR' ? 'selected' : '' %>>EUR (€)</option>
<option value="KRW" <%= service.pricing?.currency === 'KRW' ? 'selected' : '' %>>KRW (₩)</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<label for="pricingType">Тип ценообразования</label>
<select class="form-control" id="pricingType" name="pricing[type]">
<option value="fixed" <%= service.pricing?.type === 'fixed' ? 'selected' : '' %>>Фиксированная цена</option>
<option value="hourly" <%= service.pricing?.type === 'hourly' ? 'selected' : '' %>>Почасовая оплата</option>
<option value="project" <%= service.pricing?.type === 'project' ? 'selected' : '' %>>За проект</option>
<option value="subscription" <%= service.pricing?.type === 'subscription' ? 'selected' : '' %>>Подписка</option>
</select>
</div>
</div>
</div>
<!-- Features -->
<div class="card card-success">
<div class="card-header">
<h3 class="card-title">Функции и возможности</h3>
</div>
<div class="card-body">
<div id="featuresContainer">
<% if (service.features && service.features.length > 0) { %>
<% service.features.forEach((feature, index) => { %>
<div class="feature-item mb-3">
<div class="row">
<div class="col-md-8">
<input type="text" class="form-control" name="features[<%= index %>][name]" value="<%= feature.name %>">
</div>
<div class="col-md-3">
<select class="form-control" name="features[<%= index %>][included]">
<option value="true" <%= feature.included ? 'selected' : '' %>>Включено</option>
<option value="false" <%= !feature.included ? 'selected' : '' %>>Не включено</option>
</select>
</div>
<div class="col-md-1">
<button type="button" class="btn btn-danger btn-sm remove-feature">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
<% }) %>
<% } else { %>
<div class="feature-item mb-3">
<div class="row">
<div class="col-md-8">
<input type="text" class="form-control" name="features[0][name]" placeholder="Название функции">
</div>
<div class="col-md-3">
<select class="form-control" name="features[0][included]">
<option value="true">Включено</option>
<option value="false">Не включено</option>
</select>
</div>
<div class="col-md-1">
<button type="button" class="btn btn-danger btn-sm remove-feature">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
<% } %>
</div>
<button type="button" class="btn btn-sm btn-outline-primary" id="addFeature">
<i class="fas fa-plus mr-1"></i> Добавить функцию
</button>
</div>
</div>
</div>
<div class="col-md-4">
<!-- Status & Settings -->
<div class="card card-warning">
<div class="card-header">
<h3 class="card-title">Настройки</h3>
</div>
<div class="card-body">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="isActive" name="isActive" <%= service.isActive ? 'checked' : '' %>>
<label class="custom-control-label" for="isActive">Активная услуга</label>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="featured" name="featured" <%= service.featured ? 'checked' : '' %>>
<label class="custom-control-label" for="featured">Рекомендуемая услуга</label>
</div>
</div>
<div class="form-group">
<label for="order">Порядок отображения</label>
<input type="number" class="form-control" id="order" name="order" value="<%= service.order || 0 %>" min="0">
</div>
</div>
</div>
<!-- Tags -->
<div class="card card-secondary">
<div class="card-header">
<h3 class="card-title">Теги</h3>
</div>
<div class="card-body">
<div class="form-group">
<label for="tags">Теги (через запятую)</label>
<input type="text" class="form-control" id="tags" name="tags" value="<%= service.tags ? service.tags.join(', ') : '' %>">
<small class="form-text text-muted">Разделите теги запятыми</small>
</div>
</div>
</div>
<!-- SEO -->
<div class="card card-dark">
<div class="card-header">
<h3 class="card-title">SEO настройки</h3>
</div>
<div class="card-body">
<div class="form-group">
<label for="seoTitle">SEO заголовок</label>
<input type="text" class="form-control" id="seoTitle" name="seo[title]" value="<%= service.seo?.title || '' %>">
</div>
<div class="form-group">
<label for="seoDescription">SEO описание</label>
<textarea class="form-control" id="seoDescription" name="seo[description]" rows="3"><%= service.seo?.description || '' %></textarea>
</div>
<div class="form-group">
<label for="seoKeywords">Ключевые слова</label>
<input type="text" class="form-control" id="seoKeywords" name="seo[keywords]" value="<%= service.seo?.keywords || '' %>">
</div>
</div>
</div>
</div>
</div>
<!-- Submit Buttons -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<button type="submit" class="btn btn-success">
<i class="fas fa-save mr-1"></i> Сохранить изменения
</button>
<a href="/admin/services" class="btn btn-secondary ml-2">
<i class="fas fa-times mr-1"></i> Отмена
</a>
<button type="button" class="btn btn-danger ml-2" onclick="deleteService()">
<i class="fas fa-trash mr-1"></i> Удалить услугу
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</section>
<script>
$(document).ready(function() {
const service = <%- JSON.stringify(service) %>;
let featureIndex = service.features ? service.features.length : 1;
// Add feature
$('#addFeature').click(function() {
const featureHtml = `
<div class="feature-item mb-3">
<div class="row">
<div class="col-md-8">
<input type="text" class="form-control" name="features[${featureIndex}][name]" placeholder="Название функции">
</div>
<div class="col-md-3">
<select class="form-control" name="features[${featureIndex}][included]">
<option value="true">Включено</option>
<option value="false">Не включено</option>
</select>
</div>
<div class="col-md-1">
<button type="button" class="btn btn-danger btn-sm remove-feature">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
`;
$('#featuresContainer').append(featureHtml);
featureIndex++;
});
// Remove feature
$(document).on('click', '.remove-feature', function() {
$(this).closest('.feature-item').remove();
});
// Form submission
$('#serviceForm').submit(function(e) {
e.preventDefault();
const serviceId = $('#serviceId').val();
const formData = new FormData(this);
const data = {};
// Convert FormData to object
for (let [key, value] of formData.entries()) {
if (key.includes('[') && key.includes(']')) {
// Handle nested objects (pricing, seo, features)
const matches = key.match(/(\w+)\[(\w+|\d+)\](?:\[(\w+)\])?/);
if (matches) {
const [, parent, child, grandchild] = matches;
if (!data[parent]) data[parent] = {};
if (grandchild) {
// features array handling
if (!data[parent][child]) data[parent][child] = {};
data[parent][child][grandchild] = value;
} else {
data[parent][child] = value;
}
}
} else {
data[key] = value;
}
}
// Convert features object to array
if (data.features) {
const featuresArray = [];
Object.keys(data.features).forEach(index => {
if (data.features[index].name) {
featuresArray.push({
name: data.features[index].name,
included: data.features[index].included === 'true'
});
}
});
data.features = featuresArray;
}
// Convert checkboxes
data.isActive = $('#isActive').is(':checked');
data.featured = $('#featured').is(':checked');
// Convert tags to array
if (data.tags) {
data.tags = data.tags.split(',').map(tag => tag.trim()).filter(tag => tag);
}
fetch(`/api/admin/services/${serviceId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
if (result.success) {
toastr.success('Услуга успешно обновлена!');
setTimeout(() => {
window.location.href = '/admin/services';
}, 1500);
} else {
toastr.error(result.message || 'Ошибка при обновлении услуги');
}
})
.catch(error => {
console.error('Error:', error);
toastr.error('Произошла ошибка при обновлении услуги');
});
});
});
function deleteService() {
const serviceId = $('#serviceId').val();
Swal.fire({
title: 'Удалить услугу?',
text: 'Это действие невозможно отменить!',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#3085d6',
confirmButtonText: 'Да, удалить!',
cancelButtonText: 'Отмена'
}).then((result) => {
if (result.isConfirmed) {
fetch(`/api/admin/services/${serviceId}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
window.location.href = '/admin/services';
});
} else {
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
}
})
.catch(error => {
console.error('Error:', error);
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
});
}
});
}
</script>