Fix critical 'any' types in components

This commit is contained in:
gpt-engineer-app[bot]
2025-11-03 20:30:01 +00:00
parent 2cd6b2c6c3
commit 3d07198454
10 changed files with 403 additions and 28 deletions

View File

@@ -8,6 +8,20 @@ import { Alert, AlertDescription } from '@/components/ui/alert';
import { EditHistoryEntry } from './EditHistoryEntry';
import { History, Loader2, AlertCircle } from 'lucide-react';
interface EditHistoryRecord {
id: string;
item_id: string;
edited_at: string;
previous_data: Record<string, unknown>;
new_data: Record<string, unknown>;
edit_reason: string | null;
changed_fields: string[];
profiles?: {
username: string;
avatar_url?: string | null;
} | null;
}
interface EditHistoryAccordionProps {
submissionId: string;
}
@@ -30,7 +44,6 @@ export function EditHistoryAccordion({ submissionId }: EditHistoryAccordionProps
id,
item_id,
edited_at,
edited_by,
previous_data,
new_data,
edit_reason,
@@ -45,7 +58,7 @@ export function EditHistoryAccordion({ submissionId }: EditHistoryAccordionProps
.limit(limit);
if (error) throw error;
return data || [];
return (data || []) as unknown as EditHistoryRecord[];
},
staleTime: 5 * 60 * 1000, // 5 minutes
});
@@ -98,15 +111,15 @@ export function EditHistoryAccordion({ submissionId }: EditHistoryAccordionProps
<div className="space-y-4">
<ScrollArea className="h-[400px] pr-4">
<div className="space-y-3">
{editHistory.map((entry: any) => (
{editHistory.map((entry: EditHistoryRecord) => (
<EditHistoryEntry
key={entry.id}
editId={entry.id}
editorName={entry.profiles?.username || 'Unknown User'}
editorAvatar={entry.profiles?.avatar_url}
editorAvatar={entry.profiles?.avatar_url || undefined}
timestamp={entry.edited_at}
changedFields={entry.changed_fields || []}
editReason={entry.edit_reason}
editReason={entry.edit_reason || undefined}
beforeData={entry.previous_data}
afterData={entry.new_data}
/>

View File

@@ -414,8 +414,8 @@ export const ReportsQueue = forwardRef<ReportsQueueRef>((props, ref) => {
const sorted = [...reports];
sorted.sort((a, b) => {
let compareA: any;
let compareB: any;
let compareA: string | number;
let compareB: string | number;
switch (config.field) {
case 'created_at':

View File

@@ -27,20 +27,31 @@ export function ValidationSummary({ item, onValidationChange, compact = false, v
const [manualTriggerCount, setManualTriggerCount] = useState(0);
// Helper to extract the correct entity ID based on entity type
const getEntityId = (itemType: string, itemData: any, fallbackId?: string): string | undefined => {
const getEntityId = (
itemType: string,
itemData: SubmissionItemData,
fallbackId?: string
): string | undefined => {
// Try entity-specific ID fields first
const entityIdField = `${itemType}_id`;
if (itemData[entityIdField]) {
return itemData[entityIdField];
const typedData = itemData as unknown as Record<string, unknown>;
if (typeof typedData[entityIdField] === 'string') {
return typedData[entityIdField] as string;
}
// For companies, check company_id
if (['manufacturer', 'designer', 'operator', 'property_owner'].includes(itemType) && itemData.company_id) {
return itemData.company_id;
if (['manufacturer', 'designer', 'operator', 'property_owner'].includes(itemType) &&
typeof typedData.company_id === 'string') {
return typedData.company_id;
}
// Fall back to generic id field or provided fallback
return itemData.id || fallbackId;
if (typeof typedData.id === 'string') {
return typedData.id;
}
return fallbackId;
};
// Create stable reference for item_data to prevent unnecessary re-validations

View File

@@ -9,8 +9,17 @@ interface RideHighlight {
value: React.ReactNode;
}
interface RideWithStats {
id: string;
name: string;
max_speed_kmh?: number;
max_height_meters?: number;
inversions?: number;
average_rating?: number;
}
interface RideHighlightsProps {
ride: any;
ride: RideWithStats;
}
export function RideHighlights({ ride }: RideHighlightsProps) {
@@ -44,7 +53,7 @@ export function RideHighlights({ ride }: RideHighlightsProps) {
}
// Add rating highlight if high
if (ride.average_rating >= 4.0) {
if (ride.average_rating && ride.average_rating >= 4.0) {
highlights.push({
icon: <Award className="w-5 h-5 text-yellow-500" />,
label: 'Highly Rated',

View File

@@ -136,7 +136,9 @@ export function AdvancedRideFilters({
<Label>Filter Type</Label>
<Select
value={filter.operator}
onValueChange={(value: any) => updateTechnicalSpecFilter(index, { operator: value })}
onValueChange={(value: 'equals' | 'contains' | 'range' | 'has_spec') =>
updateTechnicalSpecFilter(index, { operator: value })
}
>
<SelectTrigger>
<SelectValue />

View File

@@ -108,7 +108,15 @@ export function AutocompleteSearch({
setIsOpen(true);
};
const handleResultClick = (result: SearchResult | { id: string; type: string; title: string; subtitle: string; data: any }) => {
type SearchResultOrSuggestion = SearchResult | {
id: string;
type: 'suggestion';
title: string;
subtitle: string;
data: Record<string, unknown> | null;
};
const handleResultClick = (result: SearchResultOrSuggestion) => {
if (result.type === 'suggestion') {
setQuery(result.title);
setIsOpen(false);

View File

@@ -100,6 +100,14 @@ export function EntityTimelineManager({
setIsDialogOpen(true);
};
// Convert TimelineEvent to the format expected by the dialog
const editingEventForDialog = editingEvent ? {
...editingEvent,
event_date: new Date(editingEvent.event_date),
id: editingEvent.id,
approved_by: editingEvent.approved_by || null,
} : undefined;
// Handle delete
const handleDelete = async (eventId: string) => {
if (!user) {
@@ -211,7 +219,7 @@ export function EntityTimelineManager({
entityType={entityType}
entityId={entityId}
entityName={entityName}
existingEvent={editingEvent}
existingEvent={editingEventForDialog}
onSuccess={handleSuccess}
/>
</div>

View File

@@ -93,7 +93,7 @@ interface TimelineEventEditorDialogProps {
entityType: EntityType;
entityId: string;
entityName: string;
existingEvent?: any;
existingEvent?: TimelineEventFormData & { id: string; approved_by?: string | null };
onSuccess?: () => void;
}