diff --git a/app/chat/page.tsx b/app/chat/page.tsx index b1a227a..6d36d2e 100644 --- a/app/chat/page.tsx +++ b/app/chat/page.tsx @@ -19,6 +19,7 @@ import { RoomMembersDialog } from "@/components/room-members-dialog"; import ConnectWallet from "@/components/wallet-connector"; import { RoomActivityPanel } from "@/components/room-activity-panel"; import { MessageSearchBar } from "@/components/message-search-bar"; +import { InviteMembersModal } from "@/components/invite-members-modal"; import { cn } from "@/lib/utils"; import { highlightText } from "@/lib/highlight-text"; import { handleAppError } from "@/lib/error-handler"; // Integrated Error Handler @@ -653,6 +654,10 @@ export default function ChatPage() { Members + diff --git a/components/invite-members-modal.tsx b/components/invite-members-modal.tsx new file mode 100644 index 0000000..43eeef7 --- /dev/null +++ b/components/invite-members-modal.tsx @@ -0,0 +1,167 @@ +"use client"; + +import * as Dialog from "@radix-ui/react-dialog"; +import { Check, Copy, Loader2, RefreshCw, UserPlus, X } from "lucide-react"; +import { useState } from "react"; +import toast from "react-hot-toast"; +import { cn } from "@/lib/utils"; + +type InviteMembersModalProps = { + roomId: string; + roomName: string; +}; + +export function InviteMembersModal({ roomId, roomName }: InviteMembersModalProps) { + const [isOpen, setIsOpen] = useState(false); + const [inviteCode, setInviteCode] = useState(null); + const [isGenerating, setIsGenerating] = useState(false); + const [copied, setCopied] = useState(false); + + const generateCode = async () => { + setIsGenerating(true); + try { + const res = await fetch(`/api/groups/${encodeURIComponent(roomId)}/invite`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({}), + }); + const data = await res.json(); + if (!res.ok) { + toast.error(data.error ?? "Failed to generate invite code"); + setInviteCode(null); + return; + } + setInviteCode(data.invite.code); + setCopied(false); + } catch { + toast.error("Failed to generate invite code"); + setInviteCode(null); + } finally { + setIsGenerating(false); + } + }; + + const handleOpenChange = (open: boolean) => { + setIsOpen(open); + if (open) { + setInviteCode(null); + setCopied(false); + generateCode(); + } + }; + + const handleCopy = async () => { + if (!inviteCode) return; + try { + await navigator.clipboard.writeText(inviteCode); + setCopied(true); + toast.success("Invite code copied to clipboard!"); + setTimeout(() => setCopied(false), 2500); + } catch { + toast.error("Failed to copy — please copy the code manually"); + } + }; + + return ( + + + + + Invite + + + + + + + + + Invite Members + + Share this code so others can join{" "} + {roomName}. + + + + + Close + + + + + {isGenerating && ( + + + Generating code… + + )} + + {!isGenerating && inviteCode && ( + <> + + + Invite Code + + + {inviteCode} + + + + + {copied ? ( + <> + + Copied! + > + ) : ( + <> + + Copy Invite Code + > + )} + + + + + Generate a new code + + > + )} + + {!isGenerating && !inviteCode && ( + + + Could not generate an invite code. + + + + Try again + + + )} + + + + + ); +}
+ Invite Code +
+ {inviteCode} +
+ Could not generate an invite code. +