Implement strict type enforcement plan

This commit is contained in:
gpt-engineer-app[bot]
2025-10-16 14:10:35 +00:00
parent 3bcd9e03fa
commit bc4a444138
25 changed files with 161 additions and 132 deletions

View File

@@ -6,15 +6,15 @@ import { Button } from '@/components/ui/button';
interface ArrayFieldDiffProps {
fieldName: string;
oldArray: any[];
newArray: any[];
oldArray: unknown[];
newArray: unknown[];
compact?: boolean;
}
interface ArrayDiffItem {
type: 'added' | 'removed' | 'modified' | 'unchanged';
oldValue?: any;
newValue?: any;
oldValue?: unknown;
newValue?: unknown;
index: number;
}
@@ -146,7 +146,7 @@ function ArrayDiffItemDisplay({ diff }: { diff: ArrayDiffItem }) {
}
}
function ObjectDisplay({ value, className = '' }: { value: any; className?: string }) {
function ObjectDisplay({ value, className = '' }: { value: unknown; className?: string }) {
if (!value || typeof value !== 'object') {
return <span className={className}>{formatFieldValue(value)}</span>;
}
@@ -166,7 +166,7 @@ function ObjectDisplay({ value, className = '' }: { value: any; className?: stri
/**
* Compute differences between two arrays
*/
function computeArrayDiff(oldArray: any[], newArray: any[]): ArrayDiffItem[] {
function computeArrayDiff(oldArray: unknown[], newArray: unknown[]): ArrayDiffItem[] {
const results: ArrayDiffItem[] = [];
const maxLength = Math.max(oldArray.length, newArray.length);
@@ -196,7 +196,7 @@ function computeArrayDiff(oldArray: any[], newArray: any[]): ArrayDiffItem[] {
/**
* Deep equality check
*/
function isEqual(a: any, b: any): boolean {
function isEqual(a: unknown, b: unknown): boolean {
if (a === b) return true;
if (a == null || b == null) return a === b;
if (typeof a !== typeof b) return false;

View File

@@ -52,14 +52,14 @@ interface ImageAssignments {
interface SubmissionItemData {
id: string;
item_data: any;
original_data?: any;
item_data: Record<string, unknown>;
original_data?: Record<string, unknown>;
}
export const EntityEditPreview = ({ submissionId, entityType, entityName }: EntityEditPreviewProps) => {
const [loading, setLoading] = useState(true);
const [itemData, setItemData] = useState<any>(null);
const [originalData, setOriginalData] = useState<any>(null);
const [itemData, setItemData] = useState<Record<string, unknown> | null>(null);
const [originalData, setOriginalData] = useState<Record<string, unknown> | null>(null);
const [changedFields, setChangedFields] = useState<string[]>([]);
const [bannerImageUrl, setBannerImageUrl] = useState<string | null>(null);
const [cardImageUrl, setCardImageUrl] = useState<string | null>(null);
@@ -88,8 +88,8 @@ export const EntityEditPreview = ({ submissionId, entityType, entityName }: Enti
if (items && items.length > 0) {
const firstItem = items[0];
setItemData(firstItem.item_data);
setOriginalData(firstItem.original_data);
setItemData(firstItem.item_data as Record<string, unknown>);
setOriginalData(firstItem.original_data as Record<string, unknown> | null);
// Check for photo edit/delete operations
if (firstItem.item_type === 'photo_edit' || firstItem.item_type === 'photo_delete') {
@@ -102,11 +102,15 @@ export const EntityEditPreview = ({ submissionId, entityType, entityName }: Enti
// Parse changed fields
const changed: string[] = [];
const data = firstItem.item_data as any;
const data = firstItem.item_data as Record<string, unknown>;
// Check for image changes
if (data.images) {
const images: ImageAssignments = data.images;
if (data.images && typeof data.images === 'object') {
const images = data.images as {
uploaded?: Array<{ url: string; cloudflare_id: string }>;
banner_assignment?: number | null;
card_assignment?: number | null;
};
// Safety check: verify uploaded array exists and is valid
if (!images.uploaded || !Array.isArray(images.uploaded)) {
@@ -143,7 +147,7 @@ export const EntityEditPreview = ({ submissionId, entityType, entityName }: Enti
// Check for other field changes by comparing with original_data
if (firstItem.original_data) {
const originalData = firstItem.original_data as any;
const originalData = firstItem.original_data as Record<string, unknown>;
const excludeFields = ['images', 'updated_at', 'created_at'];
Object.keys(data).forEach(key => {
if (!excludeFields.includes(key)) {
@@ -195,7 +199,7 @@ export const EntityEditPreview = ({ submissionId, entityType, entityName }: Enti
</Badge>
</div>
{itemData?.cloudflare_image_url && (
{itemData?.cloudflare_image_url && typeof itemData.cloudflare_image_url === 'string' && (
<Card className="overflow-hidden">
<CardContent className="p-2">
<img
@@ -212,19 +216,19 @@ export const EntityEditPreview = ({ submissionId, entityType, entityName }: Enti
<div>
<span className="font-medium">Old caption: </span>
<span className="text-muted-foreground">
{originalData?.caption || <em>No caption</em>}
{(originalData?.caption as string) || <em>No caption</em>}
</span>
</div>
<div>
<span className="font-medium">New caption: </span>
<span className="text-muted-foreground">
{itemData?.new_caption || <em>No caption</em>}
{(itemData?.new_caption as string) || <em>No caption</em>}
</span>
</div>
</div>
)}
{!isEdit && itemData?.reason && (
{!isEdit && itemData?.reason && typeof itemData.reason === 'string' && (
<div className="text-sm">
<span className="font-medium">Reason: </span>
<span className="text-muted-foreground">{itemData.reason}</span>

View File

@@ -54,7 +54,7 @@ export function SubmissionReviewManager({
const [showRejectionDialog, setShowRejectionDialog] = useState(false);
const [showEditDialog, setShowEditDialog] = useState(false);
const [editingItem, setEditingItem] = useState<SubmissionItemWithDeps | null>(null);
const [activeTab, setActiveTab] = useState<'items' | 'dependencies'>('items');
const [activeTab, setActiveTab] = useState<'items' | 'dependencies'>('items' as const);
const [submissionType, setSubmissionType] = useState<string>('submission');
const [showValidationBlockerDialog, setShowValidationBlockerDialog] = useState(false);
const [showWarningConfirmDialog, setShowWarningConfirmDialog] = useState(false);