Files
thrilltrack-explorer/src-old/components/profile/AddRideCreditDialog.tsx

194 lines
6.1 KiB
TypeScript

import { useState } from 'react';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { AutocompleteSearch } from '@/components/search/AutocompleteSearch';
import { supabase } from '@/lib/supabaseClient';
import { toast } from 'sonner';
import { getErrorMessage } from '@/lib/errorHandler';
import { Calendar } from '@/components/ui/calendar';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Calendar as CalendarIcon } from 'lucide-react';
import { format } from 'date-fns';
import { cn } from '@/lib/utils';
interface AddRideCreditDialogProps {
userId: string;
open: boolean;
onOpenChange: (open: boolean) => void;
onSuccess: (newCreditId: string) => void;
}
export function AddRideCreditDialog({ userId, open, onOpenChange, onSuccess }: AddRideCreditDialogProps) {
const [selectedRideId, setSelectedRideId] = useState<string>('');
const [selectedRideName, setSelectedRideName] = useState<string>('');
const [firstRideDate, setFirstRideDate] = useState<Date | undefined>(undefined);
const [rideCount, setRideCount] = useState(1);
const [submitting, setSubmitting] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!selectedRideId) {
toast.error('Please select a ride');
return;
}
try {
setSubmitting(true);
// Check if credit already exists
const { data: existing } = await supabase
.from('user_ride_credits')
.select('id')
.eq('user_id', userId)
.eq('ride_id', selectedRideId)
.maybeSingle();
if (existing) {
toast.error('You already have a credit for this ride');
return;
}
const { data, error } = await supabase
.from('user_ride_credits')
.insert({
user_id: userId,
ride_id: selectedRideId,
first_ride_date: firstRideDate ? format(firstRideDate, 'yyyy-MM-dd') : null,
ride_count: rideCount
})
.select('id')
.single();
if (error) throw error;
toast.success('Ride credit added!');
handleReset();
onSuccess(data.id); // Pass the new ID
onOpenChange(false);
} catch (error: unknown) {
toast.error(getErrorMessage(error));
} finally {
setSubmitting(false);
}
};
const handleReset = () => {
setSelectedRideId('');
setSelectedRideName('');
setFirstRideDate(undefined);
setRideCount(1);
};
return (
<Dialog
open={open}
onOpenChange={(newOpen) => {
if (!newOpen) {
handleReset();
}
onOpenChange(newOpen);
}}
>
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle>Add Ride Credit</DialogTitle>
<DialogDescription>
Log a ride you've experienced
</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label>Search for a Ride</Label>
{!selectedRideId ? (
<AutocompleteSearch
onResultSelect={(result) => {
if (result.type === 'ride') {
setSelectedRideId(result.id);
setSelectedRideName(result.title);
}
}}
types={['ride']}
placeholder="Search rides..."
className="w-full"
/>
) : (
<div className="flex items-center justify-between p-3 border rounded-lg bg-muted/50">
<div>
<p className="font-medium">{selectedRideName}</p>
<p className="text-sm text-muted-foreground">Selected ride</p>
</div>
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => {
setSelectedRideId('');
setSelectedRideName('');
}}
>
Change
</Button>
</div>
)}
</div>
<div className="space-y-2">
<Label>First Ride Date (Optional)</Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
className={cn(
'w-full justify-start text-left font-normal',
!firstRideDate && 'text-muted-foreground'
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{firstRideDate ? format(firstRideDate, 'PPP') : 'Pick a date'}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={firstRideDate}
onSelect={setFirstRideDate}
initialFocus
disabled={(date) => date > new Date()}
/>
</PopoverContent>
</Popover>
</div>
<div className="space-y-2">
<Label htmlFor="ride-count">Number of Rides</Label>
<Input
id="ride-count"
type="number"
min="1"
value={rideCount}
onChange={(e) => setRideCount(parseInt(e.target.value) || 1)}
/>
</div>
<div className="flex gap-2 justify-end">
<Button
type="button"
variant="outline"
onClick={() => onOpenChange(false)}
>
Cancel
</Button>
<Button type="submit" loading={submitting} loadingText="Adding..." disabled={!selectedRideId}>
Add Credit
</Button>
</div>
</form>
</DialogContent>
</Dialog>
);
}