mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 01:40:01 +00:00
Messaging: add explicit Delete button to the conversation header
The list-row trash is always-visible now, but add an unmissable "Delete" button in the open-conversation header (ChatView) too. Deletes the whole 1:1 conversation for everyone and clears the selection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useRef, useEffect } from "react";
|
import { useState, useRef, useEffect } from "react";
|
||||||
import { useAuth } from "@/contexts/AuthContext";
|
import { useAuth } from "@/contexts/AuthContext";
|
||||||
import { useChatMessages, usePartnerInfo } from "@/hooks/useDirectMessages";
|
import { useChatMessages, usePartnerInfo, STAFF_GROUP_ID } from "@/hooks/useDirectMessages";
|
||||||
import { supabase } from "@/integrations/supabase/client";
|
import { supabase } from "@/integrations/supabase/client";
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
interface Props {
|
interface Props {
|
||||||
partnerId: string | null;
|
partnerId: string | null;
|
||||||
partnerName: string;
|
partnerName: string;
|
||||||
|
onDeleted?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitials(name: string) {
|
function getInitials(name: string) {
|
||||||
@@ -32,12 +33,26 @@ function formatMessageDate(dateStr: string) {
|
|||||||
return format(d, "MMM d, h:mm a");
|
return format(d, "MMM d, h:mm a");
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ChatView({ partnerId, partnerName }: Props) {
|
export default function ChatView({ partnerId, partnerName, onDeleted }: Props) {
|
||||||
const { user, isAdmin, isStaff } = useAuth();
|
const { user, isAdmin, isStaff } = useAuth();
|
||||||
const { messages, loading, sendMessage, deleteMessage } = useChatMessages(partnerId);
|
const { messages, loading, sendMessage, deleteMessage } = useChatMessages(partnerId);
|
||||||
const partnerInfo = usePartnerInfo(partnerId);
|
const partnerInfo = usePartnerInfo(partnerId);
|
||||||
const [draft, setDraft] = useState("");
|
const [draft, setDraft] = useState("");
|
||||||
const [sending, setSending] = useState(false);
|
const [sending, setSending] = useState(false);
|
||||||
|
const [deleteConvOpen, setDeleteConvOpen] = useState(false);
|
||||||
|
|
||||||
|
const canDeleteConversation = !!partnerId && partnerId !== STAFF_GROUP_ID;
|
||||||
|
const deleteConversation = async () => {
|
||||||
|
if (!user || !partnerId) return;
|
||||||
|
const { error } = await supabase
|
||||||
|
.from("direct_messages")
|
||||||
|
.delete()
|
||||||
|
.or(`and(sender_id.eq.${user.id},recipient_id.eq.${partnerId}),and(sender_id.eq.${partnerId},recipient_id.eq.${user.id})`);
|
||||||
|
setDeleteConvOpen(false);
|
||||||
|
if (error) { toast({ title: "Couldn't delete conversation", description: error.message, variant: "destructive" }); return; }
|
||||||
|
toast({ title: "Conversation deleted" });
|
||||||
|
onDeleted?.();
|
||||||
|
};
|
||||||
const [creatingRequestId, setCreatingRequestId] = useState<string | null>(null);
|
const [creatingRequestId, setCreatingRequestId] = useState<string | null>(null);
|
||||||
const [deletingId, setDeletingId] = useState<string | null>(null);
|
const [deletingId, setDeletingId] = useState<string | null>(null);
|
||||||
const scrollRef = useRef<HTMLDivElement>(null);
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -133,7 +148,7 @@ export default function ChatView({ partnerId, partnerName }: Props) {
|
|||||||
{getInitials(partnerName)}
|
{getInitials(partnerName)}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div className="min-w-0">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="font-semibold text-sm truncate">{partnerName}</div>
|
<div className="font-semibold text-sm truncate">{partnerName}</div>
|
||||||
{partnerInfo && (partnerInfo.ownerName || partnerInfo.unit || partnerInfo.associationName) && (
|
{partnerInfo && (partnerInfo.ownerName || partnerInfo.unit || partnerInfo.associationName) && (
|
||||||
<div className="text-[11px] text-muted-foreground truncate">
|
<div className="text-[11px] text-muted-foreground truncate">
|
||||||
@@ -141,8 +156,35 @@ export default function ChatView({ partnerId, partnerName }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{canDeleteConversation && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="shrink-0 gap-1 text-muted-foreground hover:text-destructive"
|
||||||
|
onClick={() => setDeleteConvOpen(true)}
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4" /> Delete
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<AlertDialog open={deleteConvOpen} onOpenChange={setDeleteConvOpen}>
|
||||||
|
<AlertDialogContent>
|
||||||
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle>Delete this conversation?</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription>
|
||||||
|
This permanently deletes the conversation with {partnerName} for everyone. This can't be undone.
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||||
|
<AlertDialogAction className="bg-destructive text-destructive-foreground hover:bg-destructive/90" onClick={deleteConversation}>
|
||||||
|
Delete
|
||||||
|
</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialog>
|
||||||
|
|
||||||
{/* Messages */}
|
{/* Messages */}
|
||||||
<div ref={scrollRef} className="flex-1 overflow-y-auto px-4 py-4 space-y-3">
|
<div ref={scrollRef} className="flex-1 overflow-y-auto px-4 py-4 space-y-3">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
|
|||||||
@@ -62,7 +62,11 @@ export default function MessagesPage() {
|
|||||||
onMessageWholeBoard={handleMessageWholeBoard}
|
onMessageWholeBoard={handleMessageWholeBoard}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ChatView partnerId={selectedPartnerId} partnerName={partnerName} />
|
<ChatView
|
||||||
|
partnerId={selectedPartnerId}
|
||||||
|
partnerName={partnerName}
|
||||||
|
onDeleted={() => { setSelectedPartnerId(null); setPartnerName(""); }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user