Add ACMCC app source, Supabase backend, and project config

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 20:19:26 -04:00
parent 313b51b412
commit 183fe0a93c
1422 changed files with 259271 additions and 0 deletions
@@ -0,0 +1,119 @@
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>
);
}