mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:51:13 -05:00
Fix: Resolve internal server error
This commit is contained in:
@@ -62,7 +62,7 @@ export function ParkCard({ park }: ParkCardProps) {
|
||||
<div className="aspect-[3/2] bg-gradient-to-br from-primary/20 via-secondary/20 to-accent/20 flex items-center justify-center relative">
|
||||
{(park.card_image_url || park.card_image_id) ? (
|
||||
<img
|
||||
src={park.card_image_url || getCloudflareImageUrl(park.card_image_id, 'card')}
|
||||
src={park.card_image_url || getCloudflareImageUrl(park.card_image_id || '', 'card')}
|
||||
srcSet={park.card_image_id ? `
|
||||
${getCloudflareImageUrl(park.card_image_id, 'cardthumb')} 600w,
|
||||
${getCloudflareImageUrl(park.card_image_id, 'card')} 1200w
|
||||
@@ -111,7 +111,7 @@ export function ParkCard({ park }: ParkCardProps) {
|
||||
{/* Stats & Rating */}
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
<div className="flex items-center gap-3">
|
||||
{park.ride_count > 0 && (
|
||||
{(park.ride_count != null && park.ride_count > 0) && (
|
||||
<div className="flex items-center gap-1">
|
||||
<FerrisWheel className="w-4 h-4 text-primary/70 flex-shrink-0" />
|
||||
<span className="font-medium">{park.ride_count}</span>
|
||||
@@ -120,11 +120,11 @@ export function ParkCard({ park }: ParkCardProps) {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{park.average_rating > 0 && (
|
||||
{(park.average_rating != null && park.average_rating > 0) && (
|
||||
<div className="inline-flex items-center gap-1">
|
||||
<Star className="w-4 h-4 fill-yellow-500 text-yellow-500" />
|
||||
<span className="font-semibold">{park.average_rating.toFixed(1)}</span>
|
||||
{park.review_count > 0 && (
|
||||
{(park.review_count != null && park.review_count > 0) && (
|
||||
<span className="text-muted-foreground">({park.review_count})</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -65,12 +65,12 @@ export function ParkFilters({ filters, onFiltersChange, parks }: ParkFiltersProp
|
||||
}, [locations]);
|
||||
|
||||
const stateOptions: MultiSelectOption[] = useMemo(() => {
|
||||
const states = new Set(locations?.map(l => l.state_province).filter(Boolean) || []);
|
||||
const states = new Set(locations?.map(l => l.state_province).filter((s): s is string => s != null) || []);
|
||||
return Array.from(states).sort().map(s => ({ label: s, value: s }));
|
||||
}, [locations]);
|
||||
|
||||
const cityOptions: MultiSelectOption[] = useMemo(() => {
|
||||
const cities = new Set(locations?.map(l => l.city).filter(Boolean) || []);
|
||||
const cities = new Set(locations?.map(l => l.city).filter((c): c is string => c != null) || []);
|
||||
return Array.from(cities).sort().map(c => ({ label: c, value: c }));
|
||||
}, [locations]);
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ export function ParkListView({ parks, onParkClick }: ParkListViewProps) {
|
||||
</div>
|
||||
|
||||
{/* Rating */}
|
||||
{park.average_rating > 0 && (
|
||||
{(park.average_rating != null && park.average_rating > 0) && (
|
||||
<div className="flex items-center gap-1.5 ml-4 flex-shrink-0 bg-yellow-400/10 px-3 py-1.5 rounded-full group-hover:bg-yellow-400/20 transition-colors duration-300">
|
||||
<Star className="w-4 h-4 fill-yellow-400 text-yellow-400" />
|
||||
<span className="font-semibold text-foreground">{park.average_rating.toFixed(1)}</span>
|
||||
@@ -149,7 +149,7 @@ export function ParkListView({ parks, onParkClick }: ParkListViewProps) {
|
||||
<span className="text-accent font-semibold">{park.coaster_count || 0}</span>
|
||||
<span className="text-muted-foreground text-xs">coasters</span>
|
||||
</div>
|
||||
{park.review_count > 0 && (
|
||||
{(park.review_count != null && park.review_count > 0) && (
|
||||
<div className="flex items-center gap-1.5 group/stat">
|
||||
<Users className="w-3.5 h-3.5 text-muted-foreground group-hover/stat:text-foreground transition-colors duration-300" />
|
||||
<span className="text-muted-foreground text-xs">{park.review_count} reviews</span>
|
||||
|
||||
@@ -67,10 +67,11 @@ export function BlockedUsers() {
|
||||
const blockedUsersWithProfiles = blocks.map(block => ({
|
||||
...block,
|
||||
blocker_id: user.id,
|
||||
blocked_profile: profiles?.find(p => p.user_id === block.blocked_id)
|
||||
blocked_profile: profiles?.find(p => p.user_id === block.blocked_id),
|
||||
reason: block.reason || undefined
|
||||
}));
|
||||
|
||||
setBlockedUsers(blockedUsersWithProfiles);
|
||||
setBlockedUsers(blockedUsersWithProfiles as UserBlock[]);
|
||||
|
||||
logger.info('Blocked users fetched successfully', {
|
||||
userId: user.id,
|
||||
|
||||
@@ -134,7 +134,7 @@ export function RideCreditsManager({ userId }: RideCreditsManagerProps) {
|
||||
});
|
||||
}
|
||||
|
||||
setCredits(processedData);
|
||||
setCredits(processedData as UserRideCredit[]);
|
||||
} catch (error: unknown) {
|
||||
handleError(error, {
|
||||
action: 'Fetch Ride Credits',
|
||||
|
||||
@@ -176,8 +176,8 @@ export function ReviewForm({
|
||||
<div className="space-y-2">
|
||||
<Label>Visit Date</Label>
|
||||
<DatePicker
|
||||
date={watch('visit_date') ? parseDateOnly(watch('visit_date')) : undefined}
|
||||
onSelect={(date) => setValue('visit_date', date ? toDateOnly(date) : undefined)}
|
||||
date={watch('visit_date') ? parseDateOnly(watch('visit_date') || '') : undefined}
|
||||
onSelect={(date) => setValue('visit_date', date ? toDateOnly(date) : '')}
|
||||
placeholder="When did you visit?"
|
||||
disableFuture={true}
|
||||
fromYear={1950}
|
||||
|
||||
@@ -67,7 +67,7 @@ export function RideCard({ ride, showParkName = true, className, parkSlug }: Rid
|
||||
<div className="aspect-[3/2] bg-gradient-to-br from-primary/20 via-secondary/20 to-accent/20 flex items-center justify-center relative">
|
||||
{(ride.card_image_url || ride.card_image_id || ride.image_url) ? (
|
||||
<img
|
||||
src={ride.card_image_url || getCloudflareImageUrl(ride.card_image_id, 'card') || ride.image_url}
|
||||
src={ride.card_image_url || getCloudflareImageUrl(ride.card_image_id || '', 'card') || ride.image_url || ''}
|
||||
srcSet={ride.card_image_id ? `
|
||||
${getCloudflareImageUrl(ride.card_image_id, 'cardthumb')} 600w,
|
||||
${getCloudflareImageUrl(ride.card_image_id, 'card')} 1200w
|
||||
@@ -122,29 +122,29 @@ export function RideCard({ ride, showParkName = true, className, parkSlug }: Rid
|
||||
{/* Stats & Rating */}
|
||||
<div className="flex flex-col gap-1.5">
|
||||
{/* Stats Row */}
|
||||
{(Number(ride.max_speed_kmh) > 0 || Number(ride.max_height_meters) > 0 || Number(ride.duration_seconds) > 0) && (
|
||||
{(Number(ride.max_speed_kmh || 0) > 0 || Number(ride.max_height_meters || 0) > 0 || Number(ride.duration_seconds || 0) > 0) && (
|
||||
<div className="flex items-center gap-3 flex-wrap text-sm">
|
||||
{Number(ride.max_speed_kmh) > 0 && (
|
||||
{Number(ride.max_speed_kmh || 0) > 0 && (
|
||||
<div className="flex items-center gap-1 min-w-0">
|
||||
<Zap className="w-4 h-4 text-primary/70 flex-shrink-0" />
|
||||
<span className="font-medium whitespace-nowrap">
|
||||
<MeasurementDisplay value={ride.max_speed_kmh} type="speed" />
|
||||
<MeasurementDisplay value={ride.max_speed_kmh || 0} type="speed" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{Number(ride.max_height_meters) > 0 && (
|
||||
{Number(ride.max_height_meters || 0) > 0 && (
|
||||
<div className="flex items-center gap-1 min-w-0">
|
||||
<ArrowUp className="w-4 h-4 text-accent/70 flex-shrink-0" />
|
||||
<span className="font-medium whitespace-nowrap">
|
||||
<MeasurementDisplay value={ride.max_height_meters} type="distance" />
|
||||
<MeasurementDisplay value={ride.max_height_meters || 0} type="distance" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{Number(ride.duration_seconds) > 0 && (
|
||||
{Number(ride.duration_seconds || 0) > 0 && (
|
||||
<div className="flex items-center gap-1 min-w-0">
|
||||
<Clock className="w-4 h-4 text-secondary/70 flex-shrink-0" />
|
||||
<span className="font-medium whitespace-nowrap">
|
||||
{Math.floor(ride.duration_seconds / 60)}<span className="text-muted-foreground text-xs ml-0.5">min</span>
|
||||
{Math.floor((ride.duration_seconds || 0) / 60)}<span className="text-muted-foreground text-xs ml-0.5">min</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -152,11 +152,11 @@ export function RideCard({ ride, showParkName = true, className, parkSlug }: Rid
|
||||
)}
|
||||
|
||||
{/* Rating */}
|
||||
{ride.average_rating > 0 && (
|
||||
{(ride.average_rating != null && ride.average_rating > 0) && (
|
||||
<div className="inline-flex items-center gap-1 text-sm">
|
||||
<Star className="w-4 h-4 fill-yellow-500 text-yellow-500" />
|
||||
<span className="font-semibold text-foreground">{ride.average_rating.toFixed(1)}</span>
|
||||
{ride.review_count > 0 && (
|
||||
{(ride.review_count != null && ride.review_count > 0) && (
|
||||
<span className="text-muted-foreground">({ride.review_count})</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -145,12 +145,12 @@ export function RideFilters({ filters, onFiltersChange, rides }: RideFiltersProp
|
||||
}, [locations]);
|
||||
|
||||
const stateOptions: MultiSelectOption[] = useMemo(() => {
|
||||
const states = new Set(locations?.map(l => l.state_province).filter(Boolean) || []);
|
||||
const states = new Set(locations?.map(l => l.state_province).filter((s): s is string => s != null) || []);
|
||||
return Array.from(states).sort().map(s => ({ label: s, value: s }));
|
||||
}, [locations]);
|
||||
|
||||
const cityOptions: MultiSelectOption[] = useMemo(() => {
|
||||
const cities = new Set(locations?.map(l => l.city).filter(Boolean) || []);
|
||||
const cities = new Set(locations?.map(l => l.city).filter((c): c is string => c != null) || []);
|
||||
return Array.from(cities).sort().map(c => ({ label: c, value: c }));
|
||||
}, [locations]);
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ export function RideListView({ rides, onRideClick }: RideListViewProps) {
|
||||
</div>
|
||||
|
||||
{/* Rating */}
|
||||
{ride.average_rating > 0 && (
|
||||
{(ride.average_rating != null && ride.average_rating > 0) && (
|
||||
<div className="flex items-center gap-1.5 ml-4 flex-shrink-0 bg-yellow-400/10 px-3 py-1.5 rounded-full group-hover:bg-yellow-400/20 transition-colors duration-300">
|
||||
<Star className="w-4 h-4 fill-yellow-400 text-yellow-400" />
|
||||
<span className="font-semibold text-foreground">{ride.average_rating.toFixed(1)}</span>
|
||||
|
||||
@@ -17,14 +17,14 @@ interface SimilarRide {
|
||||
name: string;
|
||||
slug: string;
|
||||
image_url: string | null;
|
||||
average_rating: number;
|
||||
average_rating: number | null;
|
||||
status: string;
|
||||
category: string;
|
||||
description: string | null;
|
||||
max_speed_kmh: number | null;
|
||||
max_height_meters: number | null;
|
||||
duration_seconds: number | null;
|
||||
review_count: number;
|
||||
review_count: number | null;
|
||||
park: {
|
||||
name: string;
|
||||
slug: string;
|
||||
@@ -61,7 +61,7 @@ export function SimilarRides({ currentRideId, parkId, parkSlug, category }: Simi
|
||||
.limit(4);
|
||||
|
||||
if (!error && data) {
|
||||
setRides(data);
|
||||
setRides(data as SimilarRide[]);
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ export function SearchResults({ query, onClose }: SearchResultsProps) {
|
||||
const getResultRating = (result: SearchResult) => {
|
||||
if (result.type === 'park' || result.type === 'ride') {
|
||||
const data = result.data as Park | Ride;
|
||||
return data.average_rating > 0 ? data.average_rating : null;
|
||||
return (data.average_rating != null && data.average_rating > 0) ? data.average_rating : null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -97,7 +97,7 @@ export function AccountProfileTab() {
|
||||
.maybeSingle();
|
||||
|
||||
if (!error && data) {
|
||||
setDeletionRequest(data);
|
||||
setDeletionRequest(data as AccountDeletionRequest);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,8 +112,8 @@ export function AccountProfileTab() {
|
||||
// Use the update_profile RPC function with server-side validation
|
||||
const { data: result, error } = await supabase.rpc('update_profile', {
|
||||
p_username: data.username,
|
||||
p_display_name: data.display_name || null,
|
||||
p_bio: data.bio || null
|
||||
p_display_name: data.display_name || '',
|
||||
p_bio: data.bio || ''
|
||||
});
|
||||
|
||||
if (error) {
|
||||
@@ -219,7 +219,7 @@ export function AccountProfileTab() {
|
||||
.maybeSingle();
|
||||
|
||||
if (!error && data) {
|
||||
setDeletionRequest(data);
|
||||
setDeletionRequest(data as AccountDeletionRequest);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user