UI: даты игр в едином формате ДД.ММ.ГГГГ вместо сырых ISO-строк
Новый formatDate в domain/format.ts для date-only строк (played_at, last_match_at). Применён: список партий, заголовок страницы партии (раньше там было «2026-07-13»), записи в админке, «последняя партия» на странице группы. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { formatDuration } from "../domain/format";
|
import { formatDate, formatDuration } from "../domain/format";
|
||||||
import { winReasonLabel } from "../domain/winReasons";
|
import { winReasonLabel } from "../domain/winReasons";
|
||||||
import type { MatchListItem } from "../domain/types";
|
import type { MatchListItem } from "../domain/types";
|
||||||
import { PlayerLink } from "./PlayerLink";
|
import { PlayerLink } from "./PlayerLink";
|
||||||
@@ -24,7 +24,7 @@ export function MatchListView({ items }: { items: MatchListItem[] }) {
|
|||||||
onClick={() => navigate(`/match/${m.id}`)}
|
onClick={() => navigate(`/match/${m.id}`)}
|
||||||
>
|
>
|
||||||
<div className="row-between">
|
<div className="row-between">
|
||||||
<span className="muted small">{m.played_at}</span>
|
<span className="muted small">{formatDate(m.played_at)}</span>
|
||||||
{inProgress ? (
|
{inProgress ? (
|
||||||
<span className="badge" style={{ color: "var(--accent-2)" }}>идёт</span>
|
<span className="badge" style={{ color: "var(--accent-2)" }}>идёт</span>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ export function formatTime(iso: string | null | undefined): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// «Дата игры» приходит date-only строкой (YYYY-MM-DD) — просто переставляем части,
|
||||||
|
// без сдвига пояса (бэкенд уже посчитал дату в поясе приложения).
|
||||||
|
export function formatDate(iso: string | null | undefined): string {
|
||||||
|
if (!iso) return "—";
|
||||||
|
const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(iso);
|
||||||
|
return m ? `${m[3]}.${m[2]}.${m[1]}` : iso;
|
||||||
|
}
|
||||||
|
|
||||||
export function formatDateTime(iso: string | null | undefined): string {
|
export function formatDateTime(iso: string | null | undefined): string {
|
||||||
if (!iso) return "—";
|
if (!iso) return "—";
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { GroupSwitcher } from "../components/GroupSwitcher";
|
|||||||
import { Leaderboard } from "../components/Leaderboard";
|
import { Leaderboard } from "../components/Leaderboard";
|
||||||
import { MatchListView } from "../components/MatchList";
|
import { MatchListView } from "../components/MatchList";
|
||||||
import { Spinner } from "../components/Spinner";
|
import { Spinner } from "../components/Spinner";
|
||||||
|
import { formatDate } from "../domain/format";
|
||||||
import { useMe } from "../hooks/auth";
|
import { useMe } from "../hooks/auth";
|
||||||
import { useGroup, useGroupMatches, useGroupStats } from "../hooks/groups";
|
import { useGroup, useGroupMatches, useGroupStats } from "../hooks/groups";
|
||||||
|
|
||||||
@@ -49,7 +50,7 @@ export function GroupPage() {
|
|||||||
</div>
|
</div>
|
||||||
<p className="muted small">
|
<p className="muted small">
|
||||||
Партий: {stats?.total_matches ?? 0}
|
Партий: {stats?.total_matches ?? 0}
|
||||||
{stats?.last_match_at ? ` · последняя: ${stats.last_match_at}` : ""}
|
{stats?.last_match_at ? ` · последняя: ${formatDate(stats.last_match_at)}` : ""}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { ConfirmDialog } from "../components/ConfirmDialog";
|
|||||||
import { MatchMedia } from "../components/MatchMedia";
|
import { MatchMedia } from "../components/MatchMedia";
|
||||||
import { PlayerLink } from "../components/PlayerLink";
|
import { PlayerLink } from "../components/PlayerLink";
|
||||||
import { Spinner } from "../components/Spinner";
|
import { Spinner } from "../components/Spinner";
|
||||||
import { formatDuration, formatTime } from "../domain/format";
|
import { formatDate, formatDuration, formatTime } from "../domain/format";
|
||||||
import { WIN_REASONS, type WinReason, winReasonLabel } from "../domain/winReasons";
|
import { WIN_REASONS, type WinReason, winReasonLabel } from "../domain/winReasons";
|
||||||
import { useToast } from "../context/ToastContext";
|
import { useToast } from "../context/ToastContext";
|
||||||
import {
|
import {
|
||||||
@@ -120,7 +120,7 @@ export function MatchDetailPage() {
|
|||||||
<div>
|
<div>
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="row-between">
|
<div className="row-between">
|
||||||
<h2 style={{ margin: 0 }}>{match.played_at}</h2>
|
<h2 style={{ margin: 0 }}>{formatDate(match.played_at)}</h2>
|
||||||
{inProgress ? (
|
{inProgress ? (
|
||||||
<span className="badge" style={{ color: "var(--accent-2)" }}>идёт</span>
|
<span className="badge" style={{ color: "var(--accent-2)" }}>идёт</span>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useMemo, useState } from "react";
|
|||||||
|
|
||||||
import { ApiError } from "../../api/client";
|
import { ApiError } from "../../api/client";
|
||||||
import { ConfirmDialog } from "../../components/ConfirmDialog";
|
import { ConfirmDialog } from "../../components/ConfirmDialog";
|
||||||
|
import { formatDate } from "../../domain/format";
|
||||||
import { Spinner } from "../../components/Spinner";
|
import { Spinner } from "../../components/Spinner";
|
||||||
import { Switch } from "../../components/Switch";
|
import { Switch } from "../../components/Switch";
|
||||||
import { useToast } from "../../context/ToastContext";
|
import { useToast } from "../../context/ToastContext";
|
||||||
@@ -54,7 +55,7 @@ export function AdminRecordsPage() {
|
|||||||
<div key={m.id} className="card" style={{ margin: 0 }}>
|
<div key={m.id} className="card" style={{ margin: 0 }}>
|
||||||
<div className="row-between">
|
<div className="row-between">
|
||||||
<div>
|
<div>
|
||||||
<b>#{m.id}</b> · {m.played_at}
|
<b>#{m.id}</b> · {formatDate(m.played_at)}
|
||||||
{!grouped && <span className="muted small"> · {m.group_name}</span>}
|
{!grouped && <span className="muted small"> · {m.group_name}</span>}
|
||||||
<div className="muted small">
|
<div className="muted small">
|
||||||
{m.player_count} игр. · автор {m.created_by}
|
{m.player_count} игр. · автор {m.created_by}
|
||||||
|
|||||||
Reference in New Issue
Block a user