feat: Implement photo change detection

This commit is contained in:
gpt-engineer-app[bot]
2025-10-03 15:54:46 +00:00
parent 86fb99c696
commit b047291eb6
3 changed files with 117 additions and 11 deletions

View File

@@ -1,6 +1,9 @@
import { useState, useEffect } from 'react';
import { Badge } from '@/components/ui/badge';
import { Skeleton } from '@/components/ui/skeleton';
import { FieldDiff, ImageDiff, LocationDiff } from './FieldComparison';
import { detectChanges } from '@/lib/submissionChangeDetection';
import { PhotoAdditionPreview, PhotoEditPreview, PhotoDeletionPreview } from './PhotoComparison';
import { detectChanges, type ChangesSummary } from '@/lib/submissionChangeDetection';
import type { SubmissionItemData } from '@/types/submissions';
import type { SubmissionItemWithDeps } from '@/lib/submissionItemsService';
import { Building2, Train, MapPin, Building, User, ImageIcon, Trash2, Edit, Plus, AlertTriangle } from 'lucide-react';
@@ -9,6 +12,7 @@ interface SubmissionChangesDisplayProps {
item: SubmissionItemData | SubmissionItemWithDeps;
view?: 'summary' | 'detailed';
showImages?: boolean;
submissionId?: string;
}
// Helper to determine change magnitude
@@ -24,9 +28,25 @@ function getChangeMagnitude(totalChanges: number, hasImages: boolean, action: st
export function SubmissionChangesDisplay({
item,
view = 'summary',
showImages = true
showImages = true,
submissionId
}: SubmissionChangesDisplayProps) {
const changes = detectChanges(item);
const [changes, setChanges] = useState<ChangesSummary | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const loadChanges = async () => {
setLoading(true);
const detectedChanges = await detectChanges(item, submissionId);
setChanges(detectedChanges);
setLoading(false);
};
loadChanges();
}, [item, submissionId]);
if (loading || !changes) {
return <Skeleton className="h-16 w-full" />;
}
// Get appropriate icon for entity type
const getEntityIcon = () => {
@@ -83,6 +103,18 @@ export function SubmissionChangesDisplay({
{changes.imageChanges.map((change, idx) => (
<ImageDiff key={`img-${idx}`} change={change} compact />
))}
{changes.photoChanges.map((change, idx) => {
if (change.type === 'added' && change.photos) {
return <PhotoAdditionPreview key={`photo-${idx}`} photos={change.photos} compact />;
}
if (change.type === 'edited' && change.photo) {
return <PhotoEditPreview key={`photo-${idx}`} photo={change.photo} compact />;
}
if (change.type === 'deleted' && change.photo) {
return <PhotoDeletionPreview key={`photo-${idx}`} photo={change.photo} compact />;
}
return null;
})}
{changes.hasLocationChange && (
<Badge variant="outline" className="text-blue-600 dark:text-blue-400">
Location
@@ -156,6 +188,26 @@ export function SubmissionChangesDisplay({
</div>
)}
{showImages && changes.photoChanges.length > 0 && (
<div className="flex flex-col gap-2">
<h4 className="text-sm font-medium">Photo Changes</h4>
<div className="grid gap-2">
{changes.photoChanges.map((change, idx) => {
if (change.type === 'added' && change.photos) {
return <PhotoAdditionPreview key={idx} photos={change.photos} compact={false} />;
}
if (change.type === 'edited' && change.photo) {
return <PhotoEditPreview key={idx} photo={change.photo} compact={false} />;
}
if (change.type === 'deleted' && change.photo) {
return <PhotoDeletionPreview key={idx} photo={change.photo} compact={false} />;
}
return null;
})}
</div>
</div>
)}
{changes.hasLocationChange && (
<div className="flex flex-col gap-2">
<h4 className="text-sm font-medium">Location Change</h4>