mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
Calendar: manage rental/meeting calendars from the dashboard
Add a "Manage Calendars" action (rental/meeting modes) that opens the full AmenitiesManager for a chosen association in a dialog — so staff can create/ configure rental calendars, manage their bookings, and block/unblock availability without going to the association overview page. Adding bookings inline was already supported in these modes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { supabase } from "@/integrations/supabase/client";
|
|||||||
import { useAuth } from "@/contexts/AuthContext";
|
import { useAuth } from "@/contexts/AuthContext";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { useGoogleDrive } from "@/hooks/useGoogleDrive";
|
import { useGoogleDrive } from "@/hooks/useGoogleDrive";
|
||||||
import { Calendar as CalIcon, Plus, ChevronLeft, ChevronRight, Lock, Clock, MoreHorizontal, Edit, Trash2, Download, Loader2, Shield, Eye, EyeOff, Users, Building2, RefreshCw, HardDrive, ListChecks, Search } from "lucide-react";
|
import { Calendar as CalIcon, Plus, ChevronLeft, ChevronRight, Lock, Clock, MoreHorizontal, Edit, Trash2, Download, Loader2, Shield, Eye, EyeOff, Users, Building2, RefreshCw, HardDrive, ListChecks, Search, Settings2 } from "lucide-react";
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
@@ -14,6 +14,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogD
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
|
import AmenitiesManager from "@/components/association/AmenitiesManager";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { fetchAndParseCalendar, validateCalendarUrl } from "@/lib/calendarImportUtils";
|
import { fetchAndParseCalendar, validateCalendarUrl } from "@/lib/calendarImportUtils";
|
||||||
import {
|
import {
|
||||||
@@ -201,6 +202,10 @@ export default function CalendarPage({ boardAssociationIds }: { boardAssociation
|
|||||||
const [manageSelected, setManageSelected] = useState<Set<string>>(new Set());
|
const [manageSelected, setManageSelected] = useState<Set<string>>(new Set());
|
||||||
const [bulkDeleting, setBulkDeleting] = useState(false);
|
const [bulkDeleting, setBulkDeleting] = useState(false);
|
||||||
const [bookingAmenities, setBookingAmenities] = useState<any[]>([]);
|
const [bookingAmenities, setBookingAmenities] = useState<any[]>([]);
|
||||||
|
|
||||||
|
// Manage rental/meeting calendars (configure + bookings + block dates) from the dashboard
|
||||||
|
const [manageCalOpen, setManageCalOpen] = useState(false);
|
||||||
|
const [manageCalAssocId, setManageCalAssocId] = useState<string>("");
|
||||||
const [recurrence, setRecurrence] = useState<RecurrenceForm>(defaultRecurrence);
|
const [recurrence, setRecurrence] = useState<RecurrenceForm>(defaultRecurrence);
|
||||||
|
|
||||||
const isBoardView = !!boardAssociationIds?.length;
|
const isBoardView = !!boardAssociationIds?.length;
|
||||||
@@ -694,6 +699,11 @@ export default function CalendarPage({ boardAssociationIds }: { boardAssociation
|
|||||||
<Button variant="outline" className="gap-2" onClick={() => { setManageSelected(new Set()); setManageDialogOpen(true); }}>
|
<Button variant="outline" className="gap-2" onClick={() => { setManageSelected(new Set()); setManageDialogOpen(true); }}>
|
||||||
<ListChecks className="h-4 w-4" /> Manage Events
|
<ListChecks className="h-4 w-4" /> Manage Events
|
||||||
</Button>
|
</Button>
|
||||||
|
{calendarMode !== "events" && (
|
||||||
|
<Button variant="outline" className="gap-2" onClick={() => { setManageCalAssocId(associations[0]?.id || ""); setManageCalOpen(true); }}>
|
||||||
|
<Settings2 className="h-4 w-4" /> Manage Calendars
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button className="gap-2" onClick={() => calendarMode === "events" ? openNew() : openBookingNew()}><Plus className="h-4 w-4" /> {calendarMode === "events" ? "New Event" : "New Booking"}</Button>
|
<Button className="gap-2" onClick={() => calendarMode === "events" ? openNew() : openBookingNew()}><Plus className="h-4 w-4" /> {calendarMode === "events" ? "New Event" : "New Booking"}</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -1289,6 +1299,33 @@ export default function CalendarPage({ boardAssociationIds }: { boardAssociation
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
{/* Block Date Dialog */}
|
{/* Block Date Dialog */}
|
||||||
|
{/* Manage rental/meeting calendars: configure amenities, manage bookings, block availability */}
|
||||||
|
<Dialog open={manageCalOpen} onOpenChange={setManageCalOpen}>
|
||||||
|
<DialogContent className="sm:max-w-[760px] max-h-[90vh] overflow-y-auto">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Manage {calendarMode === "meetings" ? "Meeting" : "Rental"} Calendars</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Create or edit calendars, manage their bookings, and block availability — without leaving the calendar.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<Label>Association</Label>
|
||||||
|
<Select value={manageCalAssocId} onValueChange={setManageCalAssocId}>
|
||||||
|
<SelectTrigger><SelectValue placeholder="Select an association" /></SelectTrigger>
|
||||||
|
<SelectContent>{associations.map(a => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
{manageCalAssocId
|
||||||
|
? <AmenitiesManager associationId={manageCalAssocId} />
|
||||||
|
: <p className="text-sm text-muted-foreground py-6 text-center">Select an association to manage its calendars.</p>}
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={() => { setManageCalOpen(false); fetchData(); }}>Done</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
<Dialog open={blockDialogOpen} onOpenChange={setBlockDialogOpen}>
|
<Dialog open={blockDialogOpen} onOpenChange={setBlockDialogOpen}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader><DialogTitle>Block Date</DialogTitle></DialogHeader>
|
<DialogHeader><DialogTitle>Block Date</DialogTitle></DialogHeader>
|
||||||
|
|||||||
Reference in New Issue
Block a user