mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 03:11:12 -05:00
Fix image upload and moderation display
This commit is contained in:
@@ -1210,13 +1210,137 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
) : (item.submission_type === 'manufacturer' ||
|
||||||
|
item.submission_type === 'designer' ||
|
||||||
|
item.submission_type === 'operator' ||
|
||||||
|
item.submission_type === 'property_owner') ? (
|
||||||
|
<div>
|
||||||
|
<div className="text-sm text-muted-foreground mb-3 flex items-center gap-2">
|
||||||
|
<Badge variant="outline" className="capitalize">
|
||||||
|
{item.submission_type}
|
||||||
|
</Badge>
|
||||||
|
<Badge variant={item.content.action === 'create' ? 'default' : 'secondary'}>
|
||||||
|
{item.content.action === 'create' ? 'New' : 'Edit'}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-3">
|
||||||
|
{/* Basic Information */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium">Name: </span>
|
||||||
|
<span className="text-sm">{item.content.name}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium">Slug: </span>
|
||||||
|
<span className="text-sm font-mono text-muted-foreground">{item.content.slug}</span>
|
||||||
|
</div>
|
||||||
|
{item.content.person_type && (
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium">Type: </span>
|
||||||
|
<span className="text-sm capitalize">{item.content.person_type}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{item.content.description && (
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium">Description: </span>
|
||||||
|
<p className="text-sm text-muted-foreground mt-1">{item.content.description}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{item.content.website_url && (
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium">Website: </span>
|
||||||
|
<a href={item.content.website_url} target="_blank" rel="noopener noreferrer"
|
||||||
|
className="text-sm text-primary hover:underline">
|
||||||
|
{item.content.website_url}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{item.content.founded_year && (
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium">Founded: </span>
|
||||||
|
<span className="text-sm">{item.content.founded_year}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{item.content.headquarters_location && (
|
||||||
|
<div>
|
||||||
|
<span className="text-sm font-medium">Headquarters: </span>
|
||||||
|
<span className="text-sm">{item.content.headquarters_location}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Images */}
|
||||||
|
{item.content.images?.uploaded && item.content.images.uploaded.length > 0 && (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="text-sm font-medium">Images ({item.content.images.uploaded.length}):</div>
|
||||||
|
<div className="grid grid-cols-2 gap-2">
|
||||||
|
{item.content.images.uploaded.map((image: any, index: number) => (
|
||||||
|
<div key={index} className="space-y-1">
|
||||||
|
<div className="relative min-h-[100px] bg-muted/30 rounded border overflow-hidden cursor-pointer"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedPhotos(item.content.images.uploaded.map((img: any, i: number) => ({
|
||||||
|
id: `${item.id}-${i}`,
|
||||||
|
url: img.url,
|
||||||
|
filename: `Image ${i + 1}`,
|
||||||
|
caption: img.caption
|
||||||
|
})));
|
||||||
|
setSelectedPhotoIndex(index);
|
||||||
|
setPhotoModalOpen(true);
|
||||||
|
}}>
|
||||||
|
<img
|
||||||
|
src={image.url}
|
||||||
|
alt={image.caption || `Image ${index + 1}`}
|
||||||
|
className="w-full h-32 object-cover rounded hover:opacity-80 transition-opacity"
|
||||||
|
onError={(e) => {
|
||||||
|
console.error('Failed to load company image:', image.url);
|
||||||
|
(e.target as HTMLImageElement).style.display = 'none';
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center bg-black/50 text-white opacity-0 hover:opacity-100 transition-opacity">
|
||||||
|
<Eye className="w-5 h-5" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{image.caption && (
|
||||||
|
<p className="text-xs text-muted-foreground">{image.caption}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Image Role Assignments */}
|
||||||
|
{(item.content.images.banner || item.content.images.card) && (
|
||||||
|
<div className="mt-2 pt-2 border-t space-y-1">
|
||||||
|
<div className="text-xs font-medium text-muted-foreground">Image Assignments:</div>
|
||||||
|
{item.content.images.banner !== undefined && (
|
||||||
|
<div className="text-xs">
|
||||||
|
<span className="font-medium">Banner: </span>
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
{item.content.images.banner === null ? 'None' : `Image ${item.content.images.banner + 1}`}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{item.content.images.card !== undefined && (
|
||||||
|
<div className="text-xs">
|
||||||
|
<span className="font-medium">Card: </span>
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
{item.content.images.card === null ? 'None' : `Image ${item.content.images.card + 1}`}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<div className="text-sm text-muted-foreground mb-2">
|
<div className="text-sm text-muted-foreground mb-2">
|
||||||
Type: {item.content.submission_type}
|
Type: {item.submission_type}
|
||||||
</div>
|
</div>
|
||||||
<pre className="text-sm whitespace-pre-wrap">
|
<pre className="text-sm whitespace-pre-wrap">
|
||||||
{JSON.stringify(item.content.content, null, 2)}
|
{JSON.stringify(item.content, null, 2)}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { ImageAssignments } from '@/components/upload/EntityMultiImageUploader';
|
import { ImageAssignments } from '@/components/upload/EntityMultiImageUploader';
|
||||||
|
import { uploadPendingImages } from './imageUploadHelper';
|
||||||
|
|
||||||
export interface CompanyFormData {
|
export interface CompanyFormData {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -17,6 +18,16 @@ export async function submitCompanyCreation(
|
|||||||
companyType: 'manufacturer' | 'designer' | 'operator' | 'property_owner',
|
companyType: 'manufacturer' | 'designer' | 'operator' | 'property_owner',
|
||||||
userId: string
|
userId: string
|
||||||
) {
|
) {
|
||||||
|
// Upload any pending local images first
|
||||||
|
let processedImages = data.images;
|
||||||
|
if (data.images?.uploaded && data.images.uploaded.length > 0) {
|
||||||
|
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||||
|
processedImages = {
|
||||||
|
...data.images,
|
||||||
|
uploaded: uploadedImages
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// All users submit for moderation
|
// All users submit for moderation
|
||||||
const { error } = await supabase
|
const { error } = await supabase
|
||||||
.from('content_submissions')
|
.from('content_submissions')
|
||||||
@@ -33,7 +44,7 @@ export async function submitCompanyCreation(
|
|||||||
founded_year: data.founded_year,
|
founded_year: data.founded_year,
|
||||||
headquarters_location: data.headquarters_location,
|
headquarters_location: data.headquarters_location,
|
||||||
company_type: companyType,
|
company_type: companyType,
|
||||||
images: data.images as any // Include image assignments in submission
|
images: processedImages as any // Include uploaded image assignments in submission
|
||||||
} as any,
|
} as any,
|
||||||
status: 'pending'
|
status: 'pending'
|
||||||
}]);
|
}]);
|
||||||
@@ -57,6 +68,16 @@ export async function submitCompanyUpdate(
|
|||||||
if (fetchError) throw fetchError;
|
if (fetchError) throw fetchError;
|
||||||
if (!existingCompany) throw new Error('Company not found');
|
if (!existingCompany) throw new Error('Company not found');
|
||||||
|
|
||||||
|
// Upload any pending local images first
|
||||||
|
let processedImages = data.images;
|
||||||
|
if (data.images?.uploaded && data.images.uploaded.length > 0) {
|
||||||
|
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||||
|
processedImages = {
|
||||||
|
...data.images,
|
||||||
|
uploaded: uploadedImages
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// All users submit for moderation
|
// All users submit for moderation
|
||||||
const { error } = await supabase
|
const { error } = await supabase
|
||||||
.from('content_submissions')
|
.from('content_submissions')
|
||||||
@@ -73,7 +94,7 @@ export async function submitCompanyUpdate(
|
|||||||
website_url: data.website_url,
|
website_url: data.website_url,
|
||||||
founded_year: data.founded_year,
|
founded_year: data.founded_year,
|
||||||
headquarters_location: data.headquarters_location,
|
headquarters_location: data.headquarters_location,
|
||||||
images: data.images as any // Include image role assignments in submission
|
images: processedImages as any // Include uploaded image role assignments in submission
|
||||||
} as any,
|
} as any,
|
||||||
status: 'pending'
|
status: 'pending'
|
||||||
}]);
|
}]);
|
||||||
|
|||||||
Reference in New Issue
Block a user