Corp/frontend/src/components/messages/MessageActionsMenu.tsx
2026-07-06 13:47:03 +03:00

143 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { CheckCheck, Link2, Pencil, Reply, Smile, Trash2 } from "lucide-react";
import type { Message } from "@/types/api";
type MessageActionsMenuProps = {
currentUserId?: number;
message: Message;
canReply: boolean;
canManage: boolean;
isMine?: boolean;
recentReactions: string[];
onQuickReact: (emoji: string) => void;
onOpenReactionPicker: () => void;
onShowAllReaders?: () => void;
onLinkToTask?: () => void;
onReply: () => void;
onEdit: () => void;
onDelete: () => void;
};
export default function MessageActionsMenu({
currentUserId,
message,
canReply,
canManage,
isMine,
recentReactions,
onQuickReact,
onOpenReactionPicker,
onShowAllReaders,
onLinkToTask,
onReply,
onEdit,
onDelete,
}: MessageActionsMenuProps) {
const resolvedIsMine = Boolean(
isMine ?? (
currentUserId &&
(message.author_id === currentUserId || message.author?.id === currentUserId || message.sender?.id === currentUserId)
)
);
const readers = message.read_by || [];
return (
<div
data-actions-menu="true"
className={`app-menu absolute top-8 z-[30] min-w-[208px] max-w-[232px] rounded-xl py-1.5 ${resolvedIsMine ? "right-0" : "left-0"}`}
>
{canReply ? (
<div className="app-divider border-b px-2.5 pb-2 pt-1">
<div className="app-text-muted mb-1.5 px-0.5 text-[10px] font-semibold uppercase tracking-[0.08em]">Реакции</div>
<div className="flex items-center gap-1">
{recentReactions.map((emoji) => (
<button
key={`recent-${message.id}-${emoji}`}
type="button"
onClick={() => onQuickReact(emoji)}
className="inline-flex h-8 w-8 items-center justify-center rounded-md text-base transition hover:bg-[var(--surface-secondary)]"
title="Быстрая реакция"
>
{emoji}
</button>
))}
<button
type="button"
onClick={onOpenReactionPicker}
className="app-text-muted ml-auto inline-flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-[var(--surface-secondary)] hover:text-[var(--accent-primary-strong)]"
title="Все смайлы"
>
<Smile size={14} />
</button>
</div>
</div>
) : null}
<div className="py-1">
{isMine && onShowAllReaders ? (
<>
<button
type="button"
onClick={onShowAllReaders}
className="flex w-full items-center justify-between gap-2 px-3 py-2 text-left text-sm text-[var(--foreground)] transition hover:bg-[var(--surface-secondary)]"
>
<span className="flex items-center gap-2">
<CheckCheck size={13} className="app-text-muted" />
Кто прочитал
</span>
<span className="app-text-muted text-xs">{readers.length}</span>
</button>
<div className="app-divider my-1 border-t" />
</>
) : null}
{canReply ? (
<button
type="button"
onClick={onReply}
className="flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-[var(--foreground)] transition hover:bg-[var(--surface-secondary)]"
>
<Reply size={13} className="app-text-muted" />
Ответить
</button>
) : null}
{canReply && onLinkToTask ? (
<button
type="button"
onClick={onLinkToTask}
className="flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-[var(--foreground)] transition hover:bg-[var(--surface-secondary)]"
>
<Link2 size={13} className="app-text-muted" />
Связать с задачей
</button>
) : null}
{canManage ? (
<button
type="button"
onClick={onEdit}
className="flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-[var(--foreground)] transition hover:bg-[var(--surface-secondary)]"
>
<Pencil size={13} className="app-text-muted" />
Редактировать
</button>
) : null}
{canManage ? (
<button
type="button"
onClick={onDelete}
className="flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-[var(--danger-foreground)] transition hover:bg-[var(--danger-soft)]"
>
<Trash2 size={13} className="text-[var(--danger-foreground)]" />
Удалить
</button>
) : null}
</div>
</div>
);
}