Add media gallery with album organization and Puck integration

Backend:
- Add Album and MediaFile models for tenant-scoped media storage
- Add TenantStorageUsage model for per-tenant storage quota tracking
- Create StorageQuotaService with EntitlementService integration
- Add AlbumViewSet, MediaFileViewSet with bulk operations
- Add StorageUsageView for quota monitoring

Frontend:
- Create MediaGalleryPage with album management and file upload
- Add drag-and-drop upload with storage quota validation
- Create ImagePickerField custom Puck field for gallery integration
- Update Image, Testimonial components to use ImagePicker
- Add background image picker to Puck design controls
- Add gallery to sidebar navigation

Also includes:
- Puck marketing components (Hero, SplitContent, etc.)
- Enhanced ContactForm and BusinessHours components
- Platform login page improvements
- Site builder draft/preview enhancements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-13 19:59:31 -05:00
parent e7733449dd
commit fbefccf436
58 changed files with 11590 additions and 477 deletions

View File

@@ -5,6 +5,7 @@
import React, { createContext, useContext, useEffect, ReactNode } from 'react';
import { useSandboxStatus, useToggleSandbox } from '../hooks/useSandbox';
import { useEntitlements } from '../hooks/useEntitlements';
interface SandboxContextType {
/** Whether the app is currently in sandbox/test mode */
@@ -28,6 +29,10 @@ interface SandboxProviderProps {
export const SandboxProvider: React.FC<SandboxProviderProps> = ({ children }) => {
const { data: status, isLoading } = useSandboxStatus();
const toggleMutation = useToggleSandbox();
const { hasFeature } = useEntitlements();
// Check if tenant has API access - sandbox toggle requires API access
const hasApiAccess = hasFeature('api_access');
const toggleSandbox = async (enableSandbox: boolean) => {
await toggleMutation.mutateAsync(enableSandbox);
@@ -42,7 +47,8 @@ export const SandboxProvider: React.FC<SandboxProviderProps> = ({ children }) =>
const value: SandboxContextType = {
isSandbox: status?.sandbox_mode ?? false,
sandboxEnabled: status?.sandbox_enabled ?? false,
// Only show sandbox toggle if both: sandbox is enabled for business AND tenant has API access
sandboxEnabled: (status?.sandbox_enabled ?? false) && hasApiAccess,
isLoading,
toggleSandbox,
isToggling: toggleMutation.isPending,