fix(dashboard): show full name on welcome, fix gender mismatch on trial-expired card

User reported single-letter welcome "Добро пожаловать, О!" (short first_name
"Олег"-style users) and a confused "Истекла" feminine label on the masculine
"Пробный период истёк" trial-expired card.

* Add `src/utils/displayName.ts` helper that composes `first_name + last_name`
  with `username` and `#telegram_id` fallbacks. Single source of truth for
  user-facing name rendering across the app.
* Apply `displayName(user)` in Dashboard welcome, AppHeader mobile drawer,
  and DesktopSidebar profile chip. Now a user with `first_name="О"` and
  `last_name="Иванов"` sees "О Иванов" instead of just "О".
* `SubscriptionCardExpired` — context-aware Russian label: for trial
  subscriptions render masculine "Истёк" (agrees with "пробный период"),
  for paid subscriptions keep feminine "Истекла" (agrees with "подписка").
  Uses i18next `context: subscription.is_trial ? 'trial' : ''` — falls back
  to base key for EN/ZH/FA which are grammatically neutral.
* Add `expiredDate_trial: "Истёк"` only to `ru.json` (no changes needed for
  other locales — i18next context falls back to `expiredDate`).
This commit is contained in:
Fringg
2026-05-13 09:02:10 +03:00
parent 7c10843d9c
commit 4de01ccd1d
6 changed files with 35 additions and 8 deletions

View File

@@ -5,6 +5,7 @@ import { useState, useEffect } from 'react';
import { initDataUser } from '@telegram-apps/sdk-react';
import { useAuthStore } from '@/store/auth';
import { displayName } from '@/utils/displayName';
import { useShallow } from 'zustand/shallow';
import { useTheme } from '@/hooks/useTheme';
import { usePlatform } from '@/platform';
@@ -340,9 +341,7 @@ export function AppHeader({
<UserIcon className="h-5 w-5" />
</div>
<div>
<div className="text-sm font-medium text-dark-100">
{user?.first_name || user?.username}
</div>
<div className="text-sm font-medium text-dark-100">{displayName(user)}</div>
<div className="text-xs text-dark-500">
@{user?.username || `ID: ${user?.telegram_id}`}
</div>

View File

@@ -4,6 +4,7 @@ import { motion } from 'framer-motion';
import { useQuery } from '@tanstack/react-query';
import { useAuthStore } from '@/store/auth';
import { displayName } from '@/utils/displayName';
import {
brandingApi,
getCachedBranding,
@@ -188,9 +189,7 @@ export function DesktopSidebar({
<UserIcon className="h-4 w-4 text-dark-400" />
</div>
<div className="min-w-0 flex-1">
<p className="truncate text-sm font-medium text-dark-100">
{user?.first_name || user?.username || `#${user?.telegram_id}`}
</p>
<p className="truncate text-sm font-medium text-dark-100">{displayName(user)}</p>
<p className="truncate text-xs text-dark-500">
@{user?.username || `ID: ${user?.telegram_id}`}
</p>