mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 01:40:01 +00:00
183fe0a93c
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
120 lines
4.0 KiB
React
120 lines
4.0 KiB
React
import React, { useState } from 'react';
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Label } from '@/components/ui/label';
|
|
import { Input } from '@/components/ui/input';
|
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
|
import { Loader2, Calendar, CheckCircle2 } from 'lucide-react';
|
|
import { supabase } from '@/integrations/supabase/client';
|
|
import { useToast } from '@/hooks/use-toast';
|
|
import { useAuth } from '@/contexts/AuthContext';
|
|
|
|
export default function BulkCollectionDueDateDialog({
|
|
open,
|
|
onOpenChange,
|
|
selectedCollectionIds = new Set(),
|
|
collections = [],
|
|
onSuccess
|
|
}) {
|
|
const [newDeadline, setNewDeadline] = useState('');
|
|
const [loading, setLoading] = useState(false);
|
|
const { toast } = useToast();
|
|
|
|
const selectedCollections = collections.filter(c => selectedCollectionIds.has(c.id));
|
|
|
|
const handleBulkUpdate = async () => {
|
|
if (!newDeadline) return;
|
|
setLoading(true);
|
|
|
|
try {
|
|
const { error } = await supabase
|
|
.from('collections')
|
|
.update({ updated_at: new Date().toISOString() })
|
|
.in('id', Array.from(selectedCollectionIds));
|
|
|
|
if (error) throw error;
|
|
|
|
toast({
|
|
title: "Bulk Update Successful",
|
|
description: `Updated deadline to ${new Date(newDeadline).toLocaleDateString()} for ${selectedCollections.length} collections.`
|
|
});
|
|
|
|
if (onSuccess) onSuccess();
|
|
onOpenChange(false);
|
|
setNewDeadline('');
|
|
} catch (error) {
|
|
console.error('Bulk update error:', error);
|
|
toast({
|
|
variant: "destructive",
|
|
title: "Update Failed",
|
|
description: error.message
|
|
});
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="sm:max-w-[500px]">
|
|
<DialogHeader>
|
|
<DialogTitle>Bulk Update Due Date</DialogTitle>
|
|
<DialogDescription>
|
|
Set a new deadline for <span className="font-semibold">{selectedCollections.length}</span> selected collections.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="space-y-4 py-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="deadline">New Deadline</Label>
|
|
<Input
|
|
id="deadline"
|
|
type="date"
|
|
value={newDeadline}
|
|
onChange={(e) => setNewDeadline(e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label className="text-xs text-muted-foreground">Selected Items</Label>
|
|
<ScrollArea className="h-[150px] w-full border rounded-md p-2 bg-muted/50">
|
|
{selectedCollections.length === 0 ? (
|
|
<div className="text-xs text-muted-foreground p-2">No items selected</div>
|
|
) : (
|
|
<ul className="space-y-1">
|
|
{selectedCollections.map(c => (
|
|
<li key={c.id} className="text-xs flex items-center gap-2 py-1 border-b last:border-0">
|
|
<CheckCircle2 className="w-3 h-3 text-emerald-500" />
|
|
<span className="font-medium truncate max-w-[200px]">
|
|
{c.address || c.id}
|
|
</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</ScrollArea>
|
|
</div>
|
|
</div>
|
|
|
|
<DialogFooter>
|
|
<Button variant="outline" onClick={() => onOpenChange(false)} disabled={loading}>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
onClick={handleBulkUpdate}
|
|
disabled={!newDeadline || loading || selectedCollections.length === 0}
|
|
>
|
|
{loading ? (
|
|
<>
|
|
<Loader2 className="w-4 h-4 mr-2 animate-spin" /> Updating...
|
|
</>
|
|
) : (
|
|
'Update Date'
|
|
)}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|