- «Winrate» -> «Винрейт» в карточке статистики; в справке добавлена расшифровка «Винрейт (WR)» — WR остаётся в компактных таблицах; - кнопки сохранения: «ОК» -> «Сохранить» (аккаунт, фракции, аккаунты в админке); отмена в модалках/формах — везде «Отмена», не «Назад»; - пустые состояния приведены к шаблону «X пока нет.»; - роли участников группы переведены: owner/member -> владелец/участник, бейдж admin -> «админ»; «Имя обновлено» -> «Ник обновлён»; - «N игр.» в значении числа игроков -> «N игроков» со склонением (новый хелпер plural в domain/format.ts); - «минимум 2 участника» -> «минимум 2 игрока» (в партии — игроки, в группе — участники). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
import { useNavigate } from "react-router-dom";
|
|
|
|
import { formatTime } from "../domain/format";
|
|
import type { Notification } from "../hooks/notifications";
|
|
|
|
/** Выпадающий список уведомлений под колокольчиком. Клик по строке ведёт по ссылке. */
|
|
export function NotificationPanel({
|
|
items,
|
|
onClose,
|
|
}: {
|
|
items: Notification[];
|
|
onClose: () => void;
|
|
}) {
|
|
const navigate = useNavigate();
|
|
|
|
const go = (n: Notification) => {
|
|
onClose();
|
|
if (n.link) navigate(n.link);
|
|
};
|
|
|
|
return (
|
|
<div className="notif-panel">
|
|
<div className="notif-panel-head">Уведомления</div>
|
|
{items.length === 0 ? (
|
|
<div className="notif-empty muted small">Уведомлений пока нет.</div>
|
|
) : (
|
|
<div className="notif-list">
|
|
{items.map((n) => (
|
|
<button
|
|
key={n.id}
|
|
className={`notif-item${n.read_at ? "" : " unread"}`}
|
|
onClick={() => go(n)}
|
|
>
|
|
<div className="notif-item-title">{n.title}</div>
|
|
{n.body && <div className="notif-item-body muted small">{n.body}</div>}
|
|
<div className="notif-item-time muted small">{formatTime(n.created_at)}</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|