mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 18:11:12 -05:00
Fix critical 'any' types in components
This commit is contained in:
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -93,7 +93,7 @@ interface TimelineEventEditorDialogProps {
|
||||
entityType: EntityType;
|
||||
entityId: string;
|
||||
entityName: string;
|
||||
existingEvent?: any;
|
||||
existingEvent?: TimelineEventFormData & { id: string; approved_by?: string | null };
|
||||
onSuccess?: () => void;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user