Files
thrilltrack-explorer/src/components/admin/ParkLocationBackfill.tsx
2025-11-11 15:40:48 +00:00

101 lines
3.4 KiB
TypeScript

import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { supabase } from '@/lib/supabaseClient';
import { MapPin, AlertCircle, CheckCircle2 } from 'lucide-react';
import { useToast } from '@/hooks/use-toast';
export function ParkLocationBackfill() {
const [isRunning, setIsRunning] = useState(false);
const [result, setResult] = useState<{
success: boolean;
parks_updated: number;
locations_created: number;
} | null>(null);
const [error, setError] = useState<string | null>(null);
const { toast } = useToast();
const handleBackfill = async () => {
setIsRunning(true);
setError(null);
setResult(null);
try {
const { data, error: invokeError } = await supabase.functions.invoke(
'backfill-park-locations'
);
if (invokeError) throw invokeError;
setResult(data);
toast({
title: 'Backfill Complete',
description: `Updated ${data.parks_updated} parks with ${data.locations_created} new locations`,
});
} catch (err: any) {
const errorMessage = err.message || 'Failed to run backfill';
setError(errorMessage);
toast({
title: 'Backfill Failed',
description: errorMessage,
variant: 'destructive',
});
} finally {
setIsRunning(false);
}
};
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<MapPin className="w-5 h-5" />
Park Location Backfill
</CardTitle>
<CardDescription>
Backfill missing location data for approved parks from their submission data
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<Alert>
<AlertCircle className="h-4 w-4" />
<AlertDescription>
This tool will find parks without location data and populate them using the location information from their approved submissions. This is useful for fixing parks that were approved before the location creation fix was implemented.
</AlertDescription>
</Alert>
{result && (
<Alert className="border-green-200 bg-green-50 dark:bg-green-950 dark:border-green-800">
<CheckCircle2 className="h-4 w-4 text-green-600 dark:text-green-400" />
<AlertDescription className="text-green-900 dark:text-green-100">
<div className="font-medium">Backfill completed successfully!</div>
<div className="mt-2 space-y-1">
<div>Parks updated: {result.parks_updated}</div>
<div>Locations created: {result.locations_created}</div>
</div>
</AlertDescription>
</Alert>
)}
{error && (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
<Button
onClick={handleBackfill}
disabled={isRunning}
className="w-full"
trackingLabel="run-park-location-backfill"
>
<MapPin className="w-4 h-4 mr-2" />
{isRunning ? 'Running Backfill...' : 'Run Location Backfill'}
</Button>
</CardContent>
</Card>
);
}