refactor: rename project from wedding-photo-sharing to PicPeak
Create Release / check-version-change (push) Successful in 2m25s
Automatic Version Bump / version-bump (push) Failing after 8m2s
Create Release / create-release (push) Has been skipped

- 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:
2025-07-12 09:22:14 +02:00
co-authored by Claude
parent d065132bb7
commit 288b0c25e6
42 changed files with 1116 additions and 422 deletions
+59 -32
View File
@@ -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