refactor: rename project from wedding-photo-sharing to PicPeak
- Update Docker image names and network configurations - Rename package.json project names to picpeak-backend/frontend - Update CI/CD configurations (Drone CI and GitHub Actions) - Update documentation and setup scripts - Update application branding in source code - Change default database name to picpeak - Update PM2 ecosystem config 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
This commit is contained in:
@@ -18,6 +18,7 @@ import { GALLERY_THEME_PRESETS } from '../../types/theme.types';
|
||||
import { api } from '../../config/api';
|
||||
import { Upload, Menu } from 'lucide-react';
|
||||
import { galleryService } from '../../services/gallery.service';
|
||||
import { useWatermarkSettings } from '../../hooks/useWatermarkSettings';
|
||||
|
||||
interface GalleryViewProps {
|
||||
slug: string;
|
||||
@@ -48,9 +49,21 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
const [isSelectionMode, setIsSelectionMode] = useState(false);
|
||||
const [selectedPhotos, setSelectedPhotos] = useState<Set<number>>(new Set());
|
||||
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
|
||||
const { watermarkEnabled } = useWatermarkSettings();
|
||||
|
||||
// Fetch photos
|
||||
const { data, isLoading, error } = useGalleryPhotos(slug);
|
||||
|
||||
// Debug logging
|
||||
useEffect(() => {
|
||||
console.log('Event prop:', event);
|
||||
console.log('Event prop hero_photo_id:', event?.hero_photo_id);
|
||||
if (data) {
|
||||
console.log('Gallery data:', data);
|
||||
console.log('Event data from API:', data.event);
|
||||
console.log('Hero photo ID from API:', data.event?.hero_photo_id);
|
||||
}
|
||||
}, [data, event]);
|
||||
const downloadAllMutation = useDownloadAllPhotos();
|
||||
|
||||
// Handle window resize
|
||||
@@ -88,18 +101,19 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
|
||||
// Apply theme when settings are loaded
|
||||
useEffect(() => {
|
||||
if (settingsData && event) {
|
||||
if (settingsData && data?.event) {
|
||||
let themeToApply = null;
|
||||
const fullEvent = data.event; // Use the full event data from API
|
||||
|
||||
if (event.color_theme) {
|
||||
if (fullEvent.color_theme) {
|
||||
try {
|
||||
// Check if it's a valid JSON string
|
||||
if (event.color_theme.startsWith('{')) {
|
||||
const eventTheme = JSON.parse(event.color_theme);
|
||||
if (fullEvent.color_theme.startsWith('{')) {
|
||||
const eventTheme = JSON.parse(fullEvent.color_theme);
|
||||
themeToApply = eventTheme;
|
||||
} else {
|
||||
// Handle legacy theme names - check if it's a preset
|
||||
const preset = GALLERY_THEME_PRESETS[event.color_theme];
|
||||
const preset = GALLERY_THEME_PRESETS[fullEvent.color_theme];
|
||||
if (preset) {
|
||||
themeToApply = preset.config;
|
||||
} else {
|
||||
@@ -126,10 +140,12 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
// Use setTimeout to ensure this runs after any global theme application
|
||||
const timer = setTimeout(() => {
|
||||
// If there's a hero photo, add it to gallery settings
|
||||
if (event.hero_photo_id && themeToApply.gallerySettings) {
|
||||
themeToApply.gallerySettings.heroImageId = event.hero_photo_id;
|
||||
} else if (event.hero_photo_id) {
|
||||
themeToApply.gallerySettings = { heroImageId: event.hero_photo_id };
|
||||
if (fullEvent.hero_photo_id && themeToApply.gallerySettings) {
|
||||
themeToApply.gallerySettings.heroImageId = fullEvent.hero_photo_id;
|
||||
console.log('Setting hero photo ID in existing gallery settings:', fullEvent.hero_photo_id);
|
||||
} else if (fullEvent.hero_photo_id) {
|
||||
themeToApply.gallerySettings = { heroImageId: fullEvent.hero_photo_id };
|
||||
console.log('Creating gallery settings with hero photo ID:', fullEvent.hero_photo_id);
|
||||
}
|
||||
setTheme(themeToApply);
|
||||
}, 0);
|
||||
@@ -137,7 +153,7 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
}, [settingsData, event, setTheme]); // Include all dependencies
|
||||
}, [settingsData, data, setTheme]); // Use data instead of event prop
|
||||
|
||||
// Calculate days until expiration
|
||||
const daysUntilExpiration = differenceInDays(parseISO(event.expires_at), new Date());
|
||||
@@ -175,8 +191,17 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Transform URLs for watermarks if enabled
|
||||
if (watermarkEnabled) {
|
||||
photos = photos.map(photo => ({
|
||||
...photo,
|
||||
url: `/api/gallery/${slug}/photo/${photo.id}`,
|
||||
thumbnail_url: `/api/gallery/${slug}/photo/${photo.id}` // Use watermarked version for thumbnails too
|
||||
}));
|
||||
}
|
||||
|
||||
return photos;
|
||||
}, [data?.photos, selectedCategoryId, searchTerm, sortBy]);
|
||||
}, [data?.photos, selectedCategoryId, searchTerm, sortBy, watermarkEnabled, slug]);
|
||||
|
||||
const handleDownloadAll = () => {
|
||||
downloadAllMutation.mutate(slug);
|
||||
@@ -307,7 +332,7 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
totalPhotos={data?.photos.length || 0}
|
||||
isMobile={isMobile}
|
||||
galleryLayout={theme.galleryLayout}
|
||||
allowUploads={event.allow_user_uploads}
|
||||
allowUploads={data?.event?.allow_user_uploads || event?.allow_user_uploads || false}
|
||||
onUploadClick={() => setShowUploadModal(true)}
|
||||
/>
|
||||
) : null}
|
||||
@@ -320,23 +345,24 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
showDownloadAll={!showSidebar}
|
||||
onDownloadAll={handleDownloadAll}
|
||||
isDownloading={downloadAllMutation.isPending}
|
||||
menuButton={showSidebar ? (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
leftIcon={<Menu className="w-4 h-4" />}
|
||||
onClick={() => setSidebarOpen(!sidebarOpen)}
|
||||
aria-label={t('gallery.toggleMenu')}
|
||||
>
|
||||
<span className="hidden sm:inline">{t('common.menu')}</span>
|
||||
</Button>
|
||||
) : undefined}
|
||||
headerExtra={(() => {
|
||||
const items = [];
|
||||
|
||||
if (showSidebar) {
|
||||
items.push(
|
||||
<Button
|
||||
key="menu-button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
leftIcon={<Menu className="w-4 h-4" />}
|
||||
onClick={() => setSidebarOpen(!sidebarOpen)}
|
||||
aria-label={t('gallery.toggleMenu')}
|
||||
>
|
||||
<span className="hidden sm:inline">{t('common.menu')}</span>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
console.log('Header extra - data loaded:', !!data);
|
||||
console.log('Header extra - allow uploads:', data?.event?.allow_user_uploads);
|
||||
console.log('Header extra - showSidebar:', showSidebar);
|
||||
console.log('Header extra - isMobile:', isMobile);
|
||||
|
||||
if (daysUntilExpiration <= 1 && daysUntilExpiration > 0) {
|
||||
items.push(
|
||||
@@ -345,7 +371,8 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
}
|
||||
|
||||
// Upload button only on desktop when sidebar is shown
|
||||
if (event.allow_user_uploads && showSidebar && !isMobile) {
|
||||
const allowUploads = data?.event?.allow_user_uploads || event?.allow_user_uploads;
|
||||
if (allowUploads && showSidebar && !isMobile) {
|
||||
items.push(
|
||||
<Button
|
||||
key="upload-button"
|
||||
@@ -360,7 +387,7 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
}
|
||||
|
||||
// Upload button for non-sidebar layouts
|
||||
if (event.allow_user_uploads && !showSidebar) {
|
||||
if (allowUploads && !showSidebar) {
|
||||
items.push(
|
||||
<Button
|
||||
key="upload-button"
|
||||
@@ -376,7 +403,7 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
);
|
||||
}
|
||||
|
||||
return <>{items}</>;
|
||||
return items.length > 0 ? <>{items}</> : null;
|
||||
})()}
|
||||
>
|
||||
{/* Expiration Banner */}
|
||||
@@ -420,10 +447,10 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
|
||||
</div>
|
||||
|
||||
{/* Upload Modal */}
|
||||
{showUploadModal && (
|
||||
{showUploadModal && (data?.event?.allow_user_uploads || event?.allow_user_uploads) && (
|
||||
<UserPhotoUpload
|
||||
eventId={event.id}
|
||||
categoryId={event.upload_category_id}
|
||||
eventId={data?.event?.id || event?.id}
|
||||
categoryId={data?.event?.upload_category_id || event?.upload_category_id}
|
||||
onUploadComplete={() => {
|
||||
setShowUploadModal(false);
|
||||
// Refetch photos after upload
|
||||
|
||||
Reference in New Issue
Block a user