Calender & Linked Added

This commit is contained in:
JCBSComputer
2026-06-26 16:38:18 +02:00
parent ffa595451e
commit 68483e9b60
35 changed files with 5042 additions and 118 deletions
+112 -1
View File
@@ -17,7 +17,7 @@ import {
import {
Search, Send, Phone, Video, MoreHorizontal, Paperclip,
Smile, Flag, Ban, Trash2, Image, FileIcon, X, Mic, Square, Play, Pause, Check, CheckCheck,
CornerDownRight, Forward, Pencil, Download, Undo2,
CornerDownRight, Forward, Pencil, Download, Undo2, CalendarDays, Loader2,
} from "lucide-react"
import {
Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription,
@@ -25,6 +25,9 @@ import {
} from "@/components/ui/dialog"
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
import {
Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
} from "@/components/ui/select"
import { useTheme } from "next-themes"
import { useUser } from "@/providers/user-provider"
import { toast } from "sonner"
@@ -157,6 +160,13 @@ export default function ChatsPage() {
const [searchingUsers, setSearchingUsers] = useState(false)
const [unreadMap, setUnreadMap] = useState<Map<string, number>>(new Map())
const [previewAvatarUrl, setPreviewAvatarUrl] = useState<string | null>(null)
const [scheduleDialogOpen, setScheduleDialogOpen] = useState(false)
const [scheduleTitle, setScheduleTitle] = useState("")
const [scheduleDate, setScheduleDate] = useState("")
const [scheduleTime, setScheduleTime] = useState("")
const [scheduleDuration, setScheduleDuration] = useState("30")
const [scheduleType, setScheduleType] = useState<string>("meeting")
const [scheduleSaving, setScheduleSaving] = useState(false)
const fileInputRef = useRef<HTMLInputElement>(null)
const textareaRef = useRef<HTMLTextAreaElement>(null)
const emojiPickerRef = useRef<HTMLDivElement>(null)
@@ -846,6 +856,9 @@ const formatPreviewContent = (content: string) => {
<Button variant="ghost" size="icon" className="h-8 w-8" onClick={() => toast.info("Video calling coming soon")}>
<Video className="h-4 w-4" />
</Button>
<Button variant="ghost" size="icon" className="h-8 w-8" onClick={() => setScheduleDialogOpen(true)}>
<CalendarDays className="h-4 w-4" />
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon" className="h-8 w-8">
@@ -1228,6 +1241,104 @@ const formatPreviewContent = (content: string) => {
</ScrollArea>
</DialogContent>
</Dialog>
<<<<<<< Updated upstream
=======
<VoiceCallModal open={isCallModalOpen} onClose={() => setIsCallModalOpen(false)} />
{/* Schedule from Chat Dialog */}
<Dialog open={scheduleDialogOpen} onOpenChange={setScheduleDialogOpen}>
<DialogContent className="sm:max-w-[440px]">
<DialogHeader>
<DialogTitle>Schedule with {conversation ? otherParticipant(conversation).name : "..."}</DialogTitle>
<DialogDescription>Create an event and notify the participant</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<div>
<Label htmlFor="sched-title">Title</Label>
<Input id="sched-title" value={scheduleTitle} onChange={(e) => setScheduleTitle(e.target.value)} placeholder="e.g. Follow-up call" />
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label htmlFor="sched-date">Date</Label>
<Input id="sched-date" type="date" value={scheduleDate} onChange={(e) => setScheduleDate(e.target.value)} />
</div>
<div>
<Label htmlFor="sched-time">Time</Label>
<Input id="sched-time" type="time" value={scheduleTime} onChange={(e) => setScheduleTime(e.target.value)} />
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label htmlFor="sched-type">Type</Label>
<Select value={scheduleType} onValueChange={setScheduleType}>
<SelectTrigger id="sched-type">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="meeting">Meeting</SelectItem>
<SelectItem value="call">Call</SelectItem>
<SelectItem value="follow_up">Follow Up</SelectItem>
<SelectItem value="demo">Demo</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="sched-duration">Duration</Label>
<Select value={scheduleDuration} onValueChange={setScheduleDuration}>
<SelectTrigger id="sched-duration">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="15">15 min</SelectItem>
<SelectItem value="30">30 min</SelectItem>
<SelectItem value="60">1 hour</SelectItem>
<SelectItem value="90">1.5 hours</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setScheduleDialogOpen(false)}>Cancel</Button>
<Button disabled={scheduleSaving || !scheduleTitle || !scheduleDate || !scheduleTime} onClick={async () => {
if (!conversation || !user) return
setScheduleSaving(true)
try {
const startTime = new Date(`${scheduleDate}T${scheduleTime}:00`).toISOString()
const end = new Date(startTime)
end.setMinutes(end.getMinutes() + parseInt(scheduleDuration))
const res = await fetch("/api/events", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: scheduleTitle,
eventType: scheduleType,
startTime,
endTime: end.toISOString(),
durationMinutes: parseInt(scheduleDuration),
participantId: otherParticipant(conversation).id,
conversationId: conversation.id,
}),
})
if (!res.ok) throw new Error("Failed")
toast.success("Event scheduled! Notification sent.")
setScheduleDialogOpen(false)
setScheduleTitle("")
setScheduleDate("")
setScheduleTime("")
} catch {
toast.error("Failed to schedule event")
} finally {
setScheduleSaving(false)
}
}}>
{scheduleSaving && <Loader2 className="h-4 w-4 animate-spin mr-2" />}
Schedule
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
>>>>>>> Stashed changes
</div>
)
}