mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 15:11:12 -05:00
Refactor: Implement photo upload plan
This commit is contained in:
23
src/components/companies/DesignerPhotoGallery.tsx
Normal file
23
src/components/companies/DesignerPhotoGallery.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { EntityPhotoGallery } from '@/components/upload/EntityPhotoGallery';
|
||||
|
||||
interface DesignerPhotoGalleryProps {
|
||||
designerId: string;
|
||||
designerName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for designer photo galleries
|
||||
* Uses the generic EntityPhotoGallery component internally
|
||||
*/
|
||||
export function DesignerPhotoGallery({
|
||||
designerId,
|
||||
designerName
|
||||
}: DesignerPhotoGalleryProps) {
|
||||
return (
|
||||
<EntityPhotoGallery
|
||||
entityId={designerId}
|
||||
entityType="designer"
|
||||
entityName={designerName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
23
src/components/companies/ManufacturerPhotoGallery.tsx
Normal file
23
src/components/companies/ManufacturerPhotoGallery.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { EntityPhotoGallery } from '@/components/upload/EntityPhotoGallery';
|
||||
|
||||
interface ManufacturerPhotoGalleryProps {
|
||||
manufacturerId: string;
|
||||
manufacturerName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for manufacturer photo galleries
|
||||
* Uses the generic EntityPhotoGallery component internally
|
||||
*/
|
||||
export function ManufacturerPhotoGallery({
|
||||
manufacturerId,
|
||||
manufacturerName
|
||||
}: ManufacturerPhotoGalleryProps) {
|
||||
return (
|
||||
<EntityPhotoGallery
|
||||
entityId={manufacturerId}
|
||||
entityType="manufacturer"
|
||||
entityName={manufacturerName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
23
src/components/companies/OperatorPhotoGallery.tsx
Normal file
23
src/components/companies/OperatorPhotoGallery.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { EntityPhotoGallery } from '@/components/upload/EntityPhotoGallery';
|
||||
|
||||
interface OperatorPhotoGalleryProps {
|
||||
operatorId: string;
|
||||
operatorName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for operator photo galleries
|
||||
* Uses the generic EntityPhotoGallery component internally
|
||||
*/
|
||||
export function OperatorPhotoGallery({
|
||||
operatorId,
|
||||
operatorName
|
||||
}: OperatorPhotoGalleryProps) {
|
||||
return (
|
||||
<EntityPhotoGallery
|
||||
entityId={operatorId}
|
||||
entityType="operator"
|
||||
entityName={operatorName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
23
src/components/companies/PropertyOwnerPhotoGallery.tsx
Normal file
23
src/components/companies/PropertyOwnerPhotoGallery.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { EntityPhotoGallery } from '@/components/upload/EntityPhotoGallery';
|
||||
|
||||
interface PropertyOwnerPhotoGalleryProps {
|
||||
propertyOwnerId: string;
|
||||
propertyOwnerName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for property owner photo galleries
|
||||
* Uses the generic EntityPhotoGallery component internally
|
||||
*/
|
||||
export function PropertyOwnerPhotoGallery({
|
||||
propertyOwnerId,
|
||||
propertyOwnerName
|
||||
}: PropertyOwnerPhotoGalleryProps) {
|
||||
return (
|
||||
<EntityPhotoGallery
|
||||
entityId={propertyOwnerId}
|
||||
entityType="property_owner"
|
||||
entityName={propertyOwnerName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -172,8 +172,10 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
|
||||
// Handle both old format (context as object) and new format (context as string)
|
||||
let contextType = null;
|
||||
let entityId = null;
|
||||
let rideId = null;
|
||||
let parkId = null;
|
||||
let companyId = null;
|
||||
|
||||
if (typeof contentObj.context === 'object' && contentObj.context !== null) {
|
||||
// OLD FORMAT: context is an object like {ride_id: "...", park_id: "..."}
|
||||
@@ -183,11 +185,20 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
} else if (typeof contentObj.context === 'string') {
|
||||
// NEW FORMAT: context is a string, IDs are at top level
|
||||
contextType = contentObj.context;
|
||||
entityId = contentObj.entity_id;
|
||||
rideId = contentObj.ride_id;
|
||||
parkId = contentObj.park_id;
|
||||
companyId = contentObj.company_id;
|
||||
}
|
||||
|
||||
if (contextType === 'ride' && rideId) {
|
||||
// Determine entity ID based on context type
|
||||
if (!entityId) {
|
||||
if (contextType === 'ride') entityId = rideId;
|
||||
else if (contextType === 'park') entityId = parkId;
|
||||
else if (['manufacturer', 'operator', 'designer', 'property_owner'].includes(contextType)) entityId = companyId;
|
||||
}
|
||||
|
||||
if (contextType === 'ride' && entityId) {
|
||||
const { data: rideData } = await supabase
|
||||
.from('rides')
|
||||
.select(`
|
||||
@@ -196,23 +207,34 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
name
|
||||
)
|
||||
`)
|
||||
.eq('id', rideId)
|
||||
.eq('id', entityId)
|
||||
.single();
|
||||
|
||||
if (rideData) {
|
||||
(submission as any).entity_name = rideData.name;
|
||||
(submission as any).park_name = rideData.parks?.name;
|
||||
}
|
||||
} else if (contextType === 'park' && parkId) {
|
||||
} else if (contextType === 'park' && entityId) {
|
||||
const { data: parkData } = await supabase
|
||||
.from('parks')
|
||||
.select('name')
|
||||
.eq('id', parkId)
|
||||
.eq('id', entityId)
|
||||
.single();
|
||||
|
||||
if (parkData) {
|
||||
(submission as any).entity_name = parkData.name;
|
||||
}
|
||||
} else if (['manufacturer', 'operator', 'designer', 'property_owner'].includes(contextType) && entityId) {
|
||||
const { data: companyData } = await supabase
|
||||
.from('companies')
|
||||
.select('name, company_type')
|
||||
.eq('id', entityId)
|
||||
.single();
|
||||
|
||||
if (companyData) {
|
||||
(submission as any).entity_name = companyData.name;
|
||||
(submission as any).company_type = companyData.company_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
20
src/components/parks/ParkPhotoGallery.tsx
Normal file
20
src/components/parks/ParkPhotoGallery.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { EntityPhotoGallery } from '@/components/upload/EntityPhotoGallery';
|
||||
|
||||
interface ParkPhotoGalleryProps {
|
||||
parkId: string;
|
||||
parkName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards-compatible wrapper for ParkPhotoGallery
|
||||
* Uses the generic EntityPhotoGallery component internally
|
||||
*/
|
||||
export function ParkPhotoGallery({ parkId, parkName }: ParkPhotoGalleryProps) {
|
||||
return (
|
||||
<EntityPhotoGallery
|
||||
entityId={parkId}
|
||||
entityType="park"
|
||||
entityName={parkName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,12 @@
|
||||
/**
|
||||
* @deprecated This component is deprecated. Use UppyPhotoSubmissionUpload instead.
|
||||
* This file is kept for backwards compatibility only.
|
||||
*
|
||||
* For new implementations, use:
|
||||
* - UppyPhotoSubmissionUpload for direct uploads
|
||||
* - EntityPhotoGallery for entity-specific photo galleries
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Upload, X, Camera } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
@@ -207,6 +207,15 @@ export function UppyPhotoSubmissionUpload({
|
||||
},
|
||||
};
|
||||
|
||||
// Debug logging for verification
|
||||
console.log('Photo Submission Data:', {
|
||||
entity_id: finalEntityId,
|
||||
context: finalEntityType,
|
||||
parent_id: finalParentId,
|
||||
photo_count: photos.length,
|
||||
submission_data: submissionData
|
||||
});
|
||||
|
||||
const { error } = await supabase
|
||||
.from('content_submissions')
|
||||
.insert(submissionData);
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ReviewsSection } from '@/components/reviews/ReviewsSection';
|
||||
import { RideCard } from '@/components/rides/RideCard';
|
||||
import { Park, Ride } from '@/types/database';
|
||||
import { ParkLocationMap } from '@/components/maps/ParkLocationMap';
|
||||
import { EntityPhotoGallery } from '@/components/upload/EntityPhotoGallery';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
export default function ParkDetail() {
|
||||
const {
|
||||
@@ -424,13 +425,11 @@ export default function ParkDetail() {
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="photos" className="mt-6">
|
||||
<div className="text-center py-12">
|
||||
<Camera className="w-16 h-16 text-muted-foreground mx-auto mb-4" />
|
||||
<h3 className="text-xl font-semibold mb-2">Photo Gallery Coming Soon</h3>
|
||||
<p className="text-muted-foreground">
|
||||
Photo galleries and media uploads will be available soon
|
||||
</p>
|
||||
</div>
|
||||
<EntityPhotoGallery
|
||||
entityId={park.id}
|
||||
entityType="park"
|
||||
entityName={park.name}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</main>
|
||||
|
||||
@@ -627,6 +627,7 @@ export default function RideDetail() {
|
||||
<RidePhotoGallery
|
||||
rideId={ride.id}
|
||||
rideName={ride.name}
|
||||
parkId={(ride as any).currentParkId}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
Reference in New Issue
Block a user