refactor(admin): move event details page to admin section

- Moved EventDetailsPage from /events/:slug/details to /admin/events/:slug/details
- Added admin authentication check with redirect to login/home
- Updated all navigation links across the app:
  - EventsPage: "View details (admin)" button
  - EventChatPage: "View QR Code (admin)" link
  - EventCard: handleViewDetails navigation
- Fixed relative imports after moving to admin folder

This page contains admin-only features (QR codes, participants list,
matching config, scheduler config, matching runs) and should only be
accessible to administrators.
This commit is contained in:
Radosław Gierwiało
2025-12-03 19:52:00 +01:00
parent 179aaa8f16
commit eb5aacd797
5 changed files with 36 additions and 17 deletions

View File

@@ -10,7 +10,7 @@ import ResetPasswordPage from './pages/ResetPasswordPage';
import DashboardPage from './pages/DashboardPage'; import DashboardPage from './pages/DashboardPage';
import EventsPage from './pages/EventsPage'; import EventsPage from './pages/EventsPage';
import EventChatPage from './pages/EventChatPage'; import EventChatPage from './pages/EventChatPage';
import EventDetailsPage from './pages/EventDetailsPage'; import EventDetailsPage from './pages/admin/EventDetailsPage';
import EventCheckinPage from './pages/EventCheckinPage'; import EventCheckinPage from './pages/EventCheckinPage';
import MatchChatPage from './pages/MatchChatPage'; import MatchChatPage from './pages/MatchChatPage';
import MatchesPage from './pages/MatchesPage'; import MatchesPage from './pages/MatchesPage';
@@ -144,7 +144,7 @@ function App() {
} }
/> />
<Route <Route
path="/events/:slug/details" path="/admin/events/:slug/details"
element={ element={
<ProtectedRoute> <ProtectedRoute>
<EventDetailsPage /> <EventDetailsPage />

View File

@@ -13,7 +13,7 @@ const EventCard = ({ event, delay = 0, isNew = false, showCheckin = false }) =>
const navigate = useNavigate(); const navigate = useNavigate();
const handleJoinEvent = () => navigate(`/events/${event.slug}/chat`); const handleJoinEvent = () => navigate(`/events/${event.slug}/chat`);
const handleViewDetails = () => navigate(`/events/${event.slug}/details`); const handleViewDetails = () => navigate(`/admin/events/${event.slug}/details`);
return ( return (
<div <div

View File

@@ -380,10 +380,10 @@ const EventChatPage = () => {
</Link> </Link>
{import.meta.env.DEV && ( {import.meta.env.DEV && (
<Link <Link
to={`/events/${slug}/details`} to={`/admin/events/${slug}/details`}
className="px-6 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors" className="px-6 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors"
> >
View QR Code (dev) View QR Code (admin)
</Link> </Link>
)} )}
</div> </div>

View File

@@ -180,10 +180,10 @@ const EventsPage = () => {
{/* Development mode: Show details link */} {/* Development mode: Show details link */}
{import.meta.env.DEV && ( {import.meta.env.DEV && (
<button <button
onClick={() => navigate(`/events/${event.slug}/details`)} onClick={() => navigate(`/admin/events/${event.slug}/details`)}
className="w-full px-4 py-2 border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50 transition-colors text-sm" className="w-full px-4 py-2 border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50 transition-colors text-sm"
> >
View details (dev) View details (admin)
</button> </button>
)} )}
</div> </div>

View File

@@ -1,23 +1,42 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { useParams, Link } from 'react-router-dom'; import { useParams, Link, useNavigate } from 'react-router-dom';
import { Calendar, MapPin } from 'lucide-react'; import { Calendar, MapPin } from 'lucide-react';
import Layout from '../components/layout/Layout'; import Layout from '../../components/layout/Layout';
import { eventsAPI } from '../services/api'; import { eventsAPI } from '../../services/api';
import QRCodeSection from '../components/events/QRCodeSection'; import QRCodeSection from '../../components/events/QRCodeSection';
import ParticipantsSection from '../components/events/ParticipantsSection'; import ParticipantsSection from '../../components/events/ParticipantsSection';
import MatchingConfigSection from '../components/events/MatchingConfigSection'; import MatchingConfigSection from '../../components/events/MatchingConfigSection';
import ScheduleConfigSection from '../components/events/ScheduleConfigSection'; import ScheduleConfigSection from '../../components/events/ScheduleConfigSection';
import MatchingRunsSection from '../components/events/MatchingRunsSection'; import MatchingRunsSection from '../../components/events/MatchingRunsSection';
export default function EventDetailsPage() { export default function EventDetailsPage() {
const { slug } = useParams(); const { slug } = useParams();
const navigate = useNavigate();
const [user, setUser] = useState(null);
const [eventDetails, setEventDetails] = useState(null); const [eventDetails, setEventDetails] = useState(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState(''); const [error, setError] = useState('');
// Check if user is admin
useEffect(() => { useEffect(() => {
const userData = localStorage.getItem('user');
if (userData) {
const parsedUser = JSON.parse(userData);
setUser(parsedUser);
if (!parsedUser.isAdmin) {
navigate('/');
}
} else {
navigate('/login');
}
}, [navigate]);
useEffect(() => {
if (user?.isAdmin) {
fetchEventDetails(); fetchEventDetails();
}, [slug]); }
}, [slug, user]);
const fetchEventDetails = async () => { const fetchEventDetails = async () => {
try { try {