fix: Select defaults + confirm responsive pattern + convert to AlertDialog
1. Fixed Select Field Default Value ✅ Problem: Select shows empty even with default/saved value Solution: Ensure select always has value const selectValue = (value || field.value || field.default) as string; <Select value={selectValue}> Priority: current > saved > default Result: ✅ Select always shows correct value 2. Confirmed Responsive Pattern ✅ ResponsiveDialog already working correctly: - Desktop (≥768px): Dialog component - Mobile (<768px): Drawer component - useMediaQuery hook detects screen size ✅ No changes needed - already correct! 3. Converted to AlertDialog ✅ A. Orders/Detail.tsx - Retry Payment - Was: Dialog (can dismiss by clicking outside) - Now: AlertDialog (must choose action) - Better for critical payment retry action B. Orders/index.tsx - Delete Orders - Was: Dialog (can dismiss by clicking outside) - Now: AlertDialog (must choose action) - Better for destructive delete action Benefits: - ❌ No close button (forces decision) - ❌ Can't dismiss by clicking outside - ✅ User must explicitly choose Cancel or Confirm - ✅ Better UX for critical/destructive actions Component Usage Summary: - Dialog: Forms, settings, content display - Drawer: Mobile bottom sheet (auto via ResponsiveDialog) - AlertDialog: Confirmations, destructive actions Files Modified: - GenericGatewayForm.tsx: Select default value fix - Orders/Detail.tsx: Dialog → AlertDialog - Orders/index.tsx: Dialog → AlertDialog
This commit is contained in:
@@ -160,6 +160,8 @@ export function GenericGatewayForm({ gateway, onSave, onCancel, hideFooter = fal
|
||||
);
|
||||
|
||||
case 'select':
|
||||
// Ensure select has a value - use current value, saved value, or default
|
||||
const selectValue = (value || field.value || field.default) as string;
|
||||
return (
|
||||
<div key={field.id} className="space-y-2">
|
||||
<Label htmlFor={field.id}>
|
||||
@@ -173,7 +175,7 @@ export function GenericGatewayForm({ gateway, onSave, onCancel, hideFooter = fal
|
||||
/>
|
||||
)}
|
||||
<Select
|
||||
value={value as string}
|
||||
value={selectValue}
|
||||
onValueChange={(val) => handleFieldChange(field.id, val)}
|
||||
>
|
||||
<SelectTrigger id={field.id}>
|
||||
|
||||
@@ -6,7 +6,16 @@ import { formatRelativeOrDate } from '@/lib/dates';
|
||||
import { formatMoney } from '@/lib/currency';
|
||||
import { ArrowLeft, Printer, ExternalLink, Loader2, Ticket, FileText, Pencil, RefreshCw } from 'lucide-react';
|
||||
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from '@/components/ui/select';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { showErrorToast, showSuccessToast, getPageLoadErrorMessage } from '@/lib/errorHandling';
|
||||
import { ErrorCard } from '@/components/ErrorCard';
|
||||
@@ -254,33 +263,33 @@ export default function OrderShow() {
|
||||
{__('Retry Payment')}
|
||||
</button>
|
||||
|
||||
<Dialog open={showRetryDialog} onOpenChange={setShowRetryDialog}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{__('Retry Payment')}</DialogTitle>
|
||||
<DialogDescription>
|
||||
<AlertDialog open={showRetryDialog} onOpenChange={setShowRetryDialog}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>{__('Retry Payment')}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
{__('Are you sure you want to retry payment processing for this order?')}
|
||||
<br />
|
||||
<span className="text-amber-600 font-medium">
|
||||
{__('This will create a new payment transaction.')}
|
||||
</span>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setShowRetryDialog(false)}>
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel onClick={() => setShowRetryDialog(false)}>
|
||||
{__('Cancel')}
|
||||
</Button>
|
||||
<Button onClick={confirmRetryPayment} disabled={retryPaymentMutation.isPending}>
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={confirmRetryPayment} disabled={retryPaymentMutation.isPending}>
|
||||
{retryPaymentMutation.isPending ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin mr-2" />
|
||||
) : (
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
)}
|
||||
{__('Retry Payment')}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,16 @@ import { ErrorCard } from '@/components/ErrorCard';
|
||||
import { getPageLoadErrorMessage } from '@/lib/errorHandling';
|
||||
import { __ } from '@/lib/i18n';
|
||||
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { toast } from 'sonner';
|
||||
@@ -435,34 +444,33 @@ export default function Orders() {
|
||||
</div>
|
||||
|
||||
{/* Delete Confirmation Dialog */}
|
||||
<Dialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{__('Delete Orders')}</DialogTitle>
|
||||
<DialogDescription>
|
||||
<AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>{__('Delete Orders')}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
{__('Are you sure you want to delete')} {selectedIds.length} {selectedIds.length === 1 ? __('order') : __('orders')}?
|
||||
<br />
|
||||
<span className="text-red-600 font-medium">{__('This action cannot be undone.')}</span>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel
|
||||
onClick={() => setShowDeleteDialog(false)}
|
||||
disabled={deleteMutation.isPending}
|
||||
>
|
||||
{__('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={confirmDelete}
|
||||
disabled={deleteMutation.isPending}
|
||||
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
||||
>
|
||||
{deleteMutation.isPending ? __('Deleting...') : __('Delete')}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user