diff --git a/src/components/profile/RideCreditCard.tsx b/src/components/profile/RideCreditCard.tsx index f283f9f9..983d873d 100644 --- a/src/components/profile/RideCreditCard.tsx +++ b/src/components/profile/RideCreditCard.tsx @@ -24,14 +24,18 @@ import { interface RideCreditCardProps { credit: UserRideCredit; position: number; + maxPosition?: number; viewMode: 'grid' | 'list'; + isEditMode?: boolean; onUpdate: () => void; onDelete: () => void; + onReorder?: (creditId: string, newPosition: number) => Promise; } -export function RideCreditCard({ credit, position, viewMode, onUpdate, onDelete }: RideCreditCardProps) { +export function RideCreditCard({ credit, position, maxPosition, viewMode, isEditMode, onUpdate, onDelete, onReorder }: RideCreditCardProps) { const [isEditing, setIsEditing] = useState(false); const [editCount, setEditCount] = useState(credit.ride_count); + const [editPosition, setEditPosition] = useState(position); const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [updating, setUpdating] = useState(false); @@ -81,6 +85,25 @@ export function RideCreditCard({ credit, position, viewMode, onUpdate, onDelete } }; + const handlePositionChange = async () => { + if (editPosition === position || !onReorder || !maxPosition) return; + + if (editPosition < 1 || editPosition > maxPosition) { + toast.error(`Position must be between 1 and ${maxPosition}`); + setEditPosition(position); + return; + } + + try { + await onReorder(credit.id, editPosition); + toast.success('Position updated'); + } catch (error) { + console.error('Error changing position:', error); + toast.error(getErrorMessage(error)); + setEditPosition(position); + } + }; + const getCategoryBadge = (category: string) => { const categoryMap: Record = { roller_coaster: { label: 'Coaster', variant: 'default' }, @@ -117,9 +140,25 @@ export function RideCreditCard({ credit, position, viewMode, onUpdate, onDelete > {rideName} - - #{position} - + {isEditMode && maxPosition ? ( +
+ # + setEditPosition(parseInt(e.target.value) || 1)} + onBlur={handlePositionChange} + onKeyDown={(e) => e.key === 'Enter' && handlePositionChange()} + className="w-14 h-6 text-xs p-1" + min="1" + max={maxPosition} + /> +
+ ) : ( + + #{position} + + )} {getCategoryBadge(category)} @@ -245,9 +284,25 @@ export function RideCreditCard({ credit, position, viewMode, onUpdate, onDelete {rideName}
- - #{position} - + {isEditMode && maxPosition ? ( +
+ # + setEditPosition(parseInt(e.target.value) || 1)} + onBlur={handlePositionChange} + onKeyDown={(e) => e.key === 'Enter' && handlePositionChange()} + className="w-14 h-6 text-xs p-1" + min="1" + max={maxPosition} + /> +
+ ) : ( + + #{position} + + )} {getCategoryBadge(category)}
diff --git a/src/components/profile/RideCreditsManager.tsx b/src/components/profile/RideCreditsManager.tsx index 20c5a007..ba9708e4 100644 --- a/src/components/profile/RideCreditsManager.tsx +++ b/src/components/profile/RideCreditsManager.tsx @@ -158,6 +158,23 @@ export function RideCreditsManager({ userId }: RideCreditsManagerProps) { } }; + const handleReorder = async (creditId: string, newPosition: number) => { + try { + const { error } = await supabase.rpc('reorder_ride_credit', { + p_credit_id: creditId, + p_new_position: newPosition + }); + + if (error) throw error; + + // Refetch to get accurate sort_order values + await fetchCredits(); + } catch (error) { + console.error('Error reordering credit:', error); + throw error; + } + }; + const handleDragEnd = async (event: DragEndEvent) => { const { active, over } = event; @@ -173,19 +190,9 @@ export function RideCreditsManager({ userId }: RideCreditsManagerProps) { setCredits(newCredits); try { - // Call RPC to persist the change - const { error } = await supabase.rpc('reorder_ride_credit', { - p_credit_id: String(active.id), - p_new_position: newIndex + 1 - }); - - if (error) throw error; - - // Refetch to get accurate sort_order values - fetchCredits(); + await handleReorder(String(active.id), newIndex + 1); toast.success('Order updated'); } catch (error) { - console.error('Error reordering credit:', error); toast.error(getErrorMessage(error)); // Revert on error fetchCredits(); @@ -340,9 +347,11 @@ export function RideCreditsManager({ userId }: RideCreditsManagerProps) { key={credit.id} credit={credit} position={index + 1} + maxPosition={credits.length} viewMode={viewMode} onUpdate={handleCreditUpdated} onDelete={() => handleCreditDeleted(credit.id)} + onReorder={handleReorder} /> ))} diff --git a/src/components/profile/SortableRideCreditCard.tsx b/src/components/profile/SortableRideCreditCard.tsx index 9f500757..8a0e15be 100644 --- a/src/components/profile/SortableRideCreditCard.tsx +++ b/src/components/profile/SortableRideCreditCard.tsx @@ -7,17 +7,21 @@ import { UserRideCredit } from '@/types/database'; interface SortableRideCreditCardProps { credit: UserRideCredit; position: number; + maxPosition: number; viewMode: 'grid' | 'list'; onUpdate: () => void; onDelete: () => void; + onReorder: (creditId: string, newPosition: number) => Promise; } export function SortableRideCreditCard({ credit, position, + maxPosition, viewMode, onUpdate, onDelete, + onReorder, }: SortableRideCreditCardProps) { const { attributes, @@ -39,7 +43,11 @@ export function SortableRideCreditCard({
@@ -47,9 +55,12 @@ export function SortableRideCreditCard({ );