Files
ForbiddenStarsApp/frontend/src/components/NotificationPanel.tsx
T
NotBigGhostandClaude Fable 5 e38555b74d UI: согласованные тексты и терминология
- «Winrate» -> «Винрейт» в карточке статистики; в справке добавлена
  расшифровка «Винрейт (WR)» — WR остаётся в компактных таблицах;
- кнопки сохранения: «ОК» -> «Сохранить» (аккаунт, фракции, аккаунты
  в админке); отмена в модалках/формах — везде «Отмена», не «Назад»;
- пустые состояния приведены к шаблону «X пока нет.»;
- роли участников группы переведены: owner/member -> владелец/участник,
  бейдж admin -> «админ»; «Имя обновлено» -> «Ник обновлён»;
- «N игр.» в значении числа игроков -> «N игроков» со склонением
  (новый хелпер plural в domain/format.ts);
- «минимум 2 участника» -> «минимум 2 игрока» (в партии — игроки,
  в группе — участники).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 17:44:08 +03:00

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>
);
}