Lab_6
This commit is contained in:
@@ -1,61 +1,183 @@
|
||||
// src/pages/CatalogPage.jsx
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import EventList from '../components/EventList';
|
||||
import EventForm from '../components/EventForm';
|
||||
import useEvents from '../hooks/useEvents';
|
||||
import useFormState from '../hooks/useFormState';
|
||||
|
||||
const API_URL = 'http://localhost:8080/api/events';
|
||||
|
||||
const CatalogPage = () => {
|
||||
const { events, loading, error, addEvent, updateEvent, deleteEvent } = useEvents();
|
||||
const { formData, currentEvent, isFormOpen, openForm, closeForm, handleFormChange } = useFormState();
|
||||
const [events, setEvents] = useState([]);
|
||||
const [currentEvent, setCurrentEvent] = useState(null);
|
||||
const [isFormOpen, setIsFormOpen] = useState(false);
|
||||
const [sortOrder, setSortOrder] = useState('asc');
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
// Функция для открытия формы для РЕДАКТИРОВАНИЯ
|
||||
const handleEditClick = (event) => {
|
||||
openForm(event); // Передаём конкретное событие
|
||||
};
|
||||
|
||||
// Функция для открытия формы для ДОБАВЛЕНИЯ
|
||||
const handleAddClick = () => {
|
||||
openForm(null); // Явно передаём null
|
||||
};
|
||||
|
||||
const handleFormSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
if (currentEvent) {
|
||||
await updateEvent(currentEvent.id, formData);
|
||||
const getSortedEvents = (eventsList, order) => {
|
||||
if (!eventsList || !Array.isArray(eventsList)) return [];
|
||||
return [...eventsList].sort((a, b) => {
|
||||
const titleA = a.title ? a.title.toLowerCase() : '';
|
||||
const titleB = b.title ? b.title.toLowerCase() : '';
|
||||
if (order === 'asc') {
|
||||
return titleA < titleB ? -1 : titleA > titleB ? 1 : 0;
|
||||
} else {
|
||||
await addEvent(formData);
|
||||
return titleA > titleB ? -1 : titleA < titleB ? 1 : 0;
|
||||
}
|
||||
closeForm();
|
||||
} catch (err) {
|
||||
console.error('Ошибка сохранения:', err);
|
||||
});
|
||||
};
|
||||
|
||||
const sortedEvents = getSortedEvents(events, sortOrder);
|
||||
|
||||
useEffect(() => {
|
||||
fetchEvents();
|
||||
}, []);
|
||||
|
||||
const fetchEvents = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(API_URL);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Ошибка HTTP: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
setEvents(data);
|
||||
setError(null);
|
||||
} catch (error) {
|
||||
console.error('Ошибка при загрузке событий:', error);
|
||||
setError('Не удалось загрузить события. Проверьте, запущен ли сервер на порту 8080.');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) return <p className="text-center">Загрузка событий...</p>;
|
||||
if (error) return <p className="text-center text-danger">Ошибка: {error}</p>;
|
||||
const handleAddClick = () => {
|
||||
setCurrentEvent(null);
|
||||
setIsFormOpen(true);
|
||||
};
|
||||
|
||||
const handleEditClick = (event) => {
|
||||
setCurrentEvent(event);
|
||||
setIsFormOpen(true);
|
||||
};
|
||||
|
||||
const handleFormSubmit = async (eventData) => {
|
||||
try {
|
||||
if (currentEvent) {
|
||||
// Обновление существующего события
|
||||
const response = await fetch(`${API_URL}/${currentEvent.id}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(eventData),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Ошибка обновления: ${response.status}`);
|
||||
}
|
||||
const updatedEvent = await response.json();
|
||||
setEvents(events.map(e => e.id === currentEvent.id ? updatedEvent : e));
|
||||
} else {
|
||||
// Создание нового события
|
||||
const response = await fetch(API_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(eventData),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Ошибка создания: ${response.status}`);
|
||||
}
|
||||
const newEvent = await response.json();
|
||||
setEvents([...events, newEvent]);
|
||||
}
|
||||
setIsFormOpen(false);
|
||||
} catch (error) {
|
||||
console.error('Ошибка при сохранении события:', error);
|
||||
alert('Ошибка при сохранении события: ' + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteClick = async (id) => {
|
||||
if (window.confirm('Вы уверены, что хотите удалить это событие?')) {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Ошибка удаления: ${response.status}`);
|
||||
}
|
||||
setEvents(events.filter(e => e.id !== id));
|
||||
} catch (error) {
|
||||
console.error('Ошибка при удалении события:', error);
|
||||
alert('Ошибка при удалении события: ' + error.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormClose = () => {
|
||||
setIsFormOpen(false);
|
||||
};
|
||||
|
||||
const handleSortAsc = () => {
|
||||
setSortOrder('asc');
|
||||
};
|
||||
|
||||
const handleSortDesc = () => {
|
||||
setSortOrder('desc');
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <div className="container-fluid">Загрузка событий...</div>;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="container-fluid">
|
||||
<div style={{ color: '#ff4444', padding: '20px', textAlign: 'center' }}>
|
||||
<h3>Ошибка подключения</h3>
|
||||
<p>{error}</p>
|
||||
<button className="btn btn-neon" onClick={fetchEvents}>
|
||||
Попробовать снова
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container-fluid">
|
||||
<h1>Каталог стримов и событий</h1>
|
||||
<p>Выбирай из нашего ассортимента уникальных стримов, концертов и кибермероприятий.</p>
|
||||
|
||||
|
||||
{/* Кнопки сортировки */}
|
||||
<div className="mb-3">
|
||||
<button className={`btn btn-sort ${sortOrder === 'asc' ? 'btn-sort-active' : 'btn-sort-inactive'}`}
|
||||
onClick={handleSortAsc}>
|
||||
Сортировать А-Я
|
||||
</button>
|
||||
<button className={`btn btn-sort ${sortOrder === 'desc' ? 'btn-sort-active' : 'btn-sort-inactive'}`}
|
||||
onClick={handleSortDesc}>
|
||||
Сортировать Я-А
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<EventList
|
||||
events={events}
|
||||
onEdit={handleEditClick} // Передаём новую функцию для редактирования
|
||||
onDelete={deleteEvent}
|
||||
onAddClick={handleAddClick} // Передаём новую функцию для добавления
|
||||
events={sortedEvents}
|
||||
onEdit={handleEditClick}
|
||||
onDelete={handleDeleteClick}
|
||||
/>
|
||||
|
||||
<div className="text-center mt-4">
|
||||
<button className="btn btn-neon btn-lg" onClick={handleAddClick}>
|
||||
<i className="bi bi-plus-circle me-2"></i>Добавить новое событие
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{isFormOpen && (
|
||||
<EventForm
|
||||
formData={formData}
|
||||
currentEvent={currentEvent}
|
||||
onChange={handleFormChange}
|
||||
initialData={currentEvent}
|
||||
onSubmit={handleFormSubmit}
|
||||
onClose={closeForm}
|
||||
onClose={handleFormClose}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user