diff --git a/src/lib/submissionChangeDetection.ts b/src/lib/submissionChangeDetection.ts index 00ef3a25..0396a1f2 100644 --- a/src/lib/submissionChangeDetection.ts +++ b/src/lib/submissionChangeDetection.ts @@ -1,6 +1,18 @@ import type { SubmissionItemData } from '@/types/submissions'; +import type { + ParkSubmissionData, + RideSubmissionData, + CompanySubmissionData, + RideModelSubmissionData +} from '@/types/submission-data'; import { supabase } from '@/integrations/supabase/client'; +type SubmissionDataTypes = + | ParkSubmissionData + | RideSubmissionData + | CompanySubmissionData + | RideModelSubmissionData; + export interface FieldChange { field: string; oldValue: any; @@ -411,30 +423,70 @@ function shouldTrackField(key: string): boolean { 'review_count', 'coaster_count', 'average_rating', + + // Analytics fields (auto-updated by system) + 'view_count_7d', + 'view_count_30d', + 'view_count_all', ]; return !excludedFields.includes(key); } /** - * Deep equality check for values + * Normalizes values for consistent comparison + * Handles enum-like strings (snake_case) by ensuring lowercase + */ +function normalizeForComparison(value: any): any { + // Null/undefined pass through + if (value == null) return value; + + // Normalize enum-like strings to lowercase for comparison + // Matches patterns like: "operating", "Operating", "amusement_park", "Amusement_Park" + if (typeof value === 'string' && /^[a-zA-Z_]+$/.test(value)) { + return value.toLowerCase().trim(); + } + + // Recursively normalize arrays + if (Array.isArray(value)) { + return value.map(normalizeForComparison); + } + + // Recursively normalize objects (but not Date objects) + if (typeof value === 'object' && !(value instanceof Date)) { + const normalized: Record = {}; + for (const [key, val] of Object.entries(value)) { + normalized[key] = normalizeForComparison(val); + } + return normalized; + } + + return value; +} + +/** + * Deep equality check for values with normalization */ function isEqual(a: any, b: any): boolean { - if (a === b) return true; - if (a == null || b == null) return a === b; - if (typeof a !== typeof b) return false; + // Normalize both values before comparison + const normalizedA = normalizeForComparison(a); + const normalizedB = normalizeForComparison(b); - if (typeof a === 'object') { - if (Array.isArray(a) && Array.isArray(b)) { - if (a.length !== b.length) return false; - return a.every((item, i) => isEqual(item, b[i])); + if (normalizedA === normalizedB) return true; + if (normalizedA == null || normalizedB == null) return normalizedA === normalizedB; + if (typeof normalizedA !== typeof normalizedB) return false; + + if (typeof normalizedA === 'object') { + if (Array.isArray(normalizedA) && Array.isArray(normalizedB)) { + if (normalizedA.length !== normalizedB.length) return false; + return normalizedA.every((item, i) => isEqual(item, normalizedB[i])); } - const keysA = Object.keys(a); - const keysB = Object.keys(b); + const keysA = Object.keys(normalizedA); + const keysB = Object.keys(normalizedB); if (keysA.length !== keysB.length) return false; - return keysA.every(key => isEqual(a[key], b[key])); + return keysA.every(key => isEqual(normalizedA[key], normalizedB[key])); } return false;