pmtool / src /pages /calendar.tsx
devarshia5's picture
Upload 487 files
d97b8f9 verified
Raw
History Blame Contribute Delete
14.1 kB
import { useState } from "react";
import { addDays, format, startOfMonth } from "date-fns";
import { Calendar as CalendarUI } from "@/components/ui/calendar";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Dropdown } from "@/components/ui/dropdown";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import Layout from "@/components/layout/layout";
import { CalendarClock, CalendarPlus, CalendarRange, Check, Filter, Users } from "lucide-react";
type EventType = "meeting" | "deadline" | "reminder" | "task";
type EventPriority = "low" | "medium" | "high";
interface CalendarEvent {
id: string;
title: string;
date: Date;
type: EventType;
priority: EventPriority;
assignees?: string[];
description?: string;
}
const CalendarPage = () => {
const [date, setDate] = useState<Date>(new Date());
const [events, setEvents] = useState<CalendarEvent[]>([
{
id: "1",
title: "Team Standup",
date: new Date(),
type: "meeting",
priority: "medium",
assignees: ["Team Alpha"],
description: "Daily team standup meeting"
},
{
id: "2",
title: "Project Deadline",
date: addDays(new Date(), 7),
type: "deadline",
priority: "high",
description: "Final delivery of the UI components"
},
{
id: "3",
title: "Review Backlog",
date: addDays(new Date(), 2),
type: "task",
priority: "low",
description: "Go through backlog and prioritize tasks"
}
]);
const [showAddEvent, setShowAddEvent] = useState(false);
const [newEvent, setNewEvent] = useState<Partial<CalendarEvent>>({
title: "",
date: new Date(),
type: "meeting",
priority: "medium",
description: ""
});
const [selectedView, setSelectedView] = useState<"month" | "week" | "day">("month");
const [filter, setFilter] = useState<EventType | "all">("all");
const handleAddEvent = () => {
if (newEvent.title && newEvent.date) {
const event: CalendarEvent = {
id: Math.random().toString(36).substring(2, 9),
title: newEvent.title,
date: newEvent.date,
type: newEvent.type as EventType,
priority: newEvent.priority as EventPriority,
description: newEvent.description
};
setEvents([...events, event]);
setNewEvent({
title: "",
date: new Date(),
type: "meeting",
priority: "medium",
description: ""
});
setShowAddEvent(false);
}
};
const filteredEvents = events.filter(event => {
if (filter === "all") return true;
return event.type === filter;
});
const getEventsForDate = (date: Date) => {
return filteredEvents.filter(event =>
event.date.getDate() === date.getDate() &&
event.date.getMonth() === date.getMonth() &&
event.date.getFullYear() === date.getFullYear()
);
};
const eventsForSelectedDate = getEventsForDate(date);
const getPriorityColor = (priority: EventPriority) => {
switch (priority) {
case "high": return "text-red-500";
case "medium": return "text-amber-500";
case "low": return "text-green-500";
default: return "";
}
};
const getEventTypeIcon = (type: EventType) => {
switch (type) {
case "meeting": return <Users className="h-4 w-4" />;
case "deadline": return <CalendarRange className="h-4 w-4" />;
case "reminder": return <CalendarClock className="h-4 w-4" />;
case "task": return <Check className="h-4 w-4" />;
default: return null;
}
};
return (
<Layout>
<div className="container mx-auto py-6">
<div className="flex flex-col lg:flex-row gap-8">
<div className="w-full lg:w-3/5">
<Card>
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<CardTitle>Calendar</CardTitle>
<div className="flex items-center gap-2">
<Dropdown
options={[
{ label: "Month", value: "month" },
{ label: "Week", value: "week" },
{ label: "Day", value: "day" }
]}
value={selectedView}
onValueChange={(value) => setSelectedView(value as "month" | "week" | "day")}
placeholder="View"
className="w-[120px]"
/>
<Dialog>
<DialogTrigger asChild>
<Button size="sm" variant="outline">
<Filter className="h-4 w-4 mr-2" />
Filter
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Filter Events</DialogTitle>
<DialogDescription>
Show events by type
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<Dropdown
options={[
{ label: "All Events", value: "all" },
{ label: "Meetings", value: "meeting" },
{ label: "Deadlines", value: "deadline" },
{ label: "Reminders", value: "reminder" },
{ label: "Tasks", value: "task" }
]}
value={filter}
onValueChange={(value) => setFilter(value as EventType | "all")}
placeholder="Filter by type"
/>
</div>
<DialogFooter>
<Button onClick={() => setFilter("all")}>Reset Filters</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<Dialog open={showAddEvent} onOpenChange={setShowAddEvent}>
<DialogTrigger asChild>
<Button size="sm">
<CalendarPlus className="h-4 w-4 mr-2" />
Add Event
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Add New Event</DialogTitle>
<DialogDescription>
Create a new event for your calendar
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid gap-2">
<Label htmlFor="title">Title</Label>
<Input
id="title"
value={newEvent.title}
onChange={(e) => setNewEvent({...newEvent, title: e.target.value})}
placeholder="Event title"
/>
</div>
<div className="grid gap-2">
<Label>Date</Label>
<CalendarUI
selected={newEvent.date}
onSelect={(date) => date && setNewEvent({...newEvent, date})}
className="p-3 pointer-events-auto"
/>
</div>
<div className="grid gap-2">
<Label htmlFor="type">Event Type</Label>
<Dropdown
options={[
{ label: "Meeting", value: "meeting" },
{ label: "Deadline", value: "deadline" },
{ label: "Reminder", value: "reminder" },
{ label: "Task", value: "task" }
]}
value={newEvent.type}
onValueChange={(value) => setNewEvent({...newEvent, type: value as EventType})}
placeholder="Select type"
/>
</div>
<div className="grid gap-2">
<Label htmlFor="priority">Priority</Label>
<Dropdown
options={[
{ label: "Low", value: "low" },
{ label: "Medium", value: "medium" },
{ label: "High", value: "high" }
]}
value={newEvent.priority}
onValueChange={(value) => setNewEvent({...newEvent, priority: value as "low" | "medium" | "high"})}
placeholder="Select priority"
/>
</div>
<div className="grid gap-2">
<Label htmlFor="description">Description</Label>
<Input
id="description"
value={newEvent.description}
onChange={(e) => setNewEvent({...newEvent, description: e.target.value})}
placeholder="Event description"
/>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setShowAddEvent(false)}>Cancel</Button>
<Button onClick={handleAddEvent}>Add Event</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</div>
<CardDescription>
{format(date, "MMMM yyyy")}
</CardDescription>
</CardHeader>
<CardContent>
<CalendarUI
selected={date}
onSelect={(newDate) => newDate && setDate(newDate)}
className="p-3 pointer-events-auto"
month={startOfMonth(date)}
/>
</CardContent>
</Card>
</div>
<div className="w-full lg:w-2/5">
<Card>
<CardHeader>
<CardTitle>
Events for {format(date, "MMMM d, yyyy")}
</CardTitle>
<CardDescription>
{eventsForSelectedDate.length} {eventsForSelectedDate.length === 1 ? "event" : "events"} scheduled
</CardDescription>
</CardHeader>
<CardContent>
{eventsForSelectedDate.length > 0 ? (
<div className="space-y-4">
{eventsForSelectedDate.map((event) => (
<div
key={event.id}
className="flex items-start p-3 rounded-lg border border-border"
>
<div className="flex-1">
<div className="flex items-center gap-2">
<span className={getPriorityColor(event.priority)}>
{getEventTypeIcon(event.type)}
</span>
<h3 className="font-medium">{event.title}</h3>
</div>
<div className="text-sm text-muted-foreground mt-1">
{event.description}
</div>
{event.assignees && (
<div className="text-xs text-muted-foreground mt-2 flex items-center gap-1">
<Users className="h-3 w-3" />
{event.assignees.join(", ")}
</div>
)}
</div>
<div className={`text-xs font-medium ${getPriorityColor(event.priority)}`}>
{event.priority}
</div>
</div>
))}
</div>
) : (
<div className="flex flex-col items-center justify-center py-8 text-center">
<CalendarRange className="h-10 w-10 text-muted-foreground mb-2" />
<p className="text-muted-foreground">No events scheduled for this day</p>
<Button
variant="link"
className="mt-2"
onClick={() => setShowAddEvent(true)}
>
Add an event
</Button>
</div>
)}
</CardContent>
</Card>
</div>
</div>
</div>
</Layout>
);
};
export default CalendarPage;