Fix general settings route and req.user references
- Update frontend settings service to use correct /api/admin/settings/general route - Fix all req.user to req.admin references in adminSettings.js - Ensures settings can be saved without authentication errors
This commit is contained in:
@@ -10,14 +10,14 @@ import { GalleryView } from '../components/gallery';
|
||||
import { analyticsService } from '../services/analytics.service';
|
||||
|
||||
export const GalleryPage: React.FC = () => {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
const { slug, token } = useParams<{ slug: string; token?: string }>();
|
||||
const { isAuthenticated, login, event } = useGalleryAuth();
|
||||
const [password, setPassword] = useState('');
|
||||
const [isLoggingIn, setIsLoggingIn] = useState(false);
|
||||
const [loginError, setLoginError] = useState<string | null>(null);
|
||||
|
||||
// Fetch gallery info (public data)
|
||||
const { data: galleryInfo, isLoading: isLoadingInfo, error: infoError } = useGalleryInfo(slug!);
|
||||
const { data: galleryInfo, isLoading: isLoadingInfo, error: infoError } = useGalleryInfo(slug!, token);
|
||||
|
||||
// Calculate days until expiration
|
||||
const daysUntilExpiration = galleryInfo
|
||||
|
||||
@@ -13,12 +13,14 @@ import {
|
||||
X,
|
||||
AlertTriangle,
|
||||
Copy,
|
||||
CheckCircle
|
||||
CheckCircle,
|
||||
Upload
|
||||
} from 'lucide-react';
|
||||
import { format, parseISO, differenceInDays } from 'date-fns';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { Button, Input, Card, Loading } from '../../components/common';
|
||||
import { PhotoUpload } from '../../components/admin';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { eventsService } from '../../services/events.service';
|
||||
import { galleryService } from '../../services/gallery.service';
|
||||
@@ -42,6 +44,7 @@ export const EventDetailsPage: React.FC = () => {
|
||||
expires_at: '',
|
||||
});
|
||||
const [copiedLink, setCopiedLink] = useState(false);
|
||||
const [showPhotoUpload, setShowPhotoUpload] = useState(false);
|
||||
|
||||
// Fetch event details
|
||||
const { data: event, isLoading: eventLoading } = useQuery({
|
||||
@@ -50,11 +53,12 @@ export const EventDetailsPage: React.FC = () => {
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
// Fetch event statistics
|
||||
// Fetch event statistics (skip if event doesn't exist or from admin context)
|
||||
const { data: stats } = useQuery({
|
||||
queryKey: ['admin-event-stats', event?.slug],
|
||||
queryFn: () => galleryService.getGalleryStats(event!.slug),
|
||||
enabled: !!event?.slug,
|
||||
enabled: false, // Disable stats from admin panel as it requires gallery auth
|
||||
retry: false,
|
||||
});
|
||||
|
||||
// Update mutation
|
||||
@@ -203,15 +207,17 @@ export const EventDetailsPage: React.FC = () => {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<a
|
||||
href={event.share_link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-primary-600 hover:text-primary-700 border border-primary-600 rounded-lg hover:bg-primary-50 transition-colors"
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
View Gallery
|
||||
</a>
|
||||
{event.share_link && (
|
||||
<a
|
||||
href={event.share_link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-primary-600 hover:text-primary-700 border border-primary-600 rounded-lg hover:bg-primary-50 transition-colors"
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
View Gallery
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -357,6 +363,57 @@ export const EventDetailsPage: React.FC = () => {
|
||||
</p>
|
||||
</Card>
|
||||
|
||||
{/* Photo Management */}
|
||||
<Card padding="md">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-lg font-semibold text-neutral-900">Photo Management</h2>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
leftIcon={<Upload className="w-4 h-4" />}
|
||||
onClick={() => setShowPhotoUpload(!showPhotoUpload)}
|
||||
>
|
||||
Upload Photos
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{showPhotoUpload && (
|
||||
<div className="mb-4">
|
||||
<PhotoUpload
|
||||
eventId={parseInt(id!)}
|
||||
onUploadComplete={() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['admin-event', id] });
|
||||
toast.success('Photos uploaded successfully');
|
||||
setShowPhotoUpload(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between py-2 px-3 bg-neutral-50 rounded-lg">
|
||||
<span className="text-sm text-neutral-600">Total Photos</span>
|
||||
<span className="text-sm font-medium">{event.photo_count || 0}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between py-2 px-3 bg-neutral-50 rounded-lg">
|
||||
<span className="text-sm text-neutral-600">Total Size</span>
|
||||
<span className="text-sm font-medium">
|
||||
{event.total_size ? `${(event.total_size / (1024 * 1024)).toFixed(1)} MB` : '0 MB'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 p-3 bg-blue-50 rounded-lg">
|
||||
<p className="text-sm text-blue-800">
|
||||
<strong>Storage Location:</strong> /storage/events/active/{event.slug}/
|
||||
</p>
|
||||
<p className="text-xs text-blue-600 mt-1">
|
||||
Photos can also be added by placing them in the 'individual' or 'collages' folders.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Actions */}
|
||||
{!event.is_archived && (
|
||||
<Card padding="md">
|
||||
|
||||
@@ -346,17 +346,19 @@ export const EventsListPage: React.FC = () => {
|
||||
<Edit className="w-4 h-4" />
|
||||
View Details
|
||||
</button>
|
||||
<a
|
||||
href={event.share_link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-full text-left px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-100 flex items-center gap-2"
|
||||
onClick={() => setActiveDropdown(null)}
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
View Gallery
|
||||
</a>
|
||||
{!event.is_archived && (
|
||||
{event.share_link ? (
|
||||
<a
|
||||
href={event.share_link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-full text-left px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-100 flex items-center gap-2"
|
||||
onClick={() => setActiveDropdown(null)}
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
View Gallery
|
||||
</a>
|
||||
) : null}
|
||||
{!event.is_archived ? (
|
||||
<button
|
||||
onClick={() => {
|
||||
archiveMutation.mutate(event.id);
|
||||
@@ -367,8 +369,8 @@ export const EventsListPage: React.FC = () => {
|
||||
<Archive className="w-4 h-4" />
|
||||
Archive Event
|
||||
</button>
|
||||
)}
|
||||
{event.is_archived && (
|
||||
) : null}
|
||||
{event.is_archived ? (
|
||||
<button
|
||||
onClick={() => {
|
||||
toast.info('Download archive coming soon');
|
||||
@@ -379,7 +381,7 @@ export const EventsListPage: React.FC = () => {
|
||||
<Download className="w-4 h-4" />
|
||||
Download Archive
|
||||
</button>
|
||||
)}
|
||||
) : null}
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm('Are you sure you want to delete this event?')) {
|
||||
|
||||
Reference in New Issue
Block a user