I-1: обёртка со stopPropagation вокруг всего Popover (CommentsPopover и FileWarningsPopover);
I-2, M-2: key={doc.id} на боковой панели комментариев; решения R-5…R-12 в design.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
1.9 KiB
TypeScript
43 lines
1.9 KiB
TypeScript
import { CommentOutlined } from '@ant-design/icons';
|
||
import { Button, Popover } from 'antd';
|
||
import { useState } from 'react';
|
||
import { CommentsList } from './CommentsList';
|
||
import { useDocumentComments } from './useDocumentComments';
|
||
|
||
/** Кнопка с числом комментариев в строке панели документов [39-01]; по клику — список только для чтения. */
|
||
export function CommentsPopover({ documentId, fileName, count }: { documentId: string; fileName: string; count: number }) {
|
||
const [open, setOpen] = useState(false);
|
||
const { state, load, reset } = useDocumentComments(documentId);
|
||
|
||
const onOpenChange = (next: boolean) => {
|
||
setOpen(next);
|
||
if (next) load();
|
||
else reset();
|
||
};
|
||
|
||
const content = (
|
||
<div style={{ width: 360, maxWidth: 420 }}>
|
||
<div style={{ maxHeight: 320, overflowY: 'auto', marginBottom: 8 }}>
|
||
<CommentsList state={state} emptyText='Комментарий отсутствует' />
|
||
</div>
|
||
<div style={{ textAlign: 'right' }}>
|
||
<Button size='small' onClick={() => onOpenChange(false)}>
|
||
Закрыть
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
);
|
||
|
||
return (
|
||
// Поповер рисуется в портале, но события React всплывают по дереву компонентов до onClick строки таблицы и открывали
|
||
// бы документ. Обёртка вокруг всего Popover ловит клики по кнопке, заголовку, отступам и содержимому разом.
|
||
<span onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()}>
|
||
<Popover trigger='click' title={`Комментарии к документу ${fileName}`} content={content} open={open} onOpenChange={onOpenChange}>
|
||
<Button icon={<CommentOutlined />} aria-label={`Комментарии: ${count}`}>
|
||
{count > 0 ? count : null}
|
||
</Button>
|
||
</Popover>
|
||
</span>
|
||
);
|
||
}
|