Merge PR #506: приветствие без пустого имени для email-пользователей

displayName() получил фолбэк на локальную часть email; без имени вовсе —
dashboard.welcomeNoName без запятой (4 локали). Закрывает #423.
Спасибо @kewldan.
This commit is contained in:
Fringg
2026-07-24 14:50:21 +03:00
7 changed files with 96 additions and 35 deletions

View File

@@ -0,0 +1,51 @@
import { describe, expect, it } from 'vitest';
import { displayName } from './displayName';
describe('displayName', () => {
it('returns empty string for missing user', () => {
expect(displayName(undefined)).toBe('');
expect(displayName(null)).toBe('');
});
it('combines first_name and last_name', () => {
expect(displayName({ first_name: 'Иван', last_name: 'Петров' })).toBe('Иван Петров');
expect(displayName({ first_name: 'Иван', last_name: null })).toBe('Иван');
expect(displayName({ first_name: null, last_name: 'Петров' })).toBe('Петров');
});
it('falls back to username when there is no name', () => {
expect(displayName({ first_name: null, last_name: null, username: 'ivan' })).toBe('ivan');
});
it('falls back to telegram_id when there is no name and no username', () => {
expect(displayName({ first_name: null, username: null, telegram_id: 123456 })).toBe('#123456');
});
it('falls back to the email local part for email-only users', () => {
expect(
displayName({
first_name: null,
last_name: null,
username: null,
telegram_id: null,
email: 'vasya@gmail.com',
}),
).toBe('vasya');
});
it('prefers telegram_id over email', () => {
expect(displayName({ telegram_id: 123456, email: 'vasya@gmail.com' })).toBe('#123456');
});
it('returns empty string when every source is empty', () => {
expect(
displayName({
first_name: ' ',
last_name: null,
username: null,
telegram_id: null,
email: null,
}),
).toBe('');
});
});

View File

@@ -3,21 +3,28 @@
*
* Why: single-letter first_name (e.g., "О") looked confusing alone ("Добро пожаловать, О!").
* Combining with last_name makes truncated/short first names readable.
*
* Email/OAuth registration does not collect a name, so for such users every
* Telegram-derived field is null — fall back to the email local part
* ("vasya@gmail.com" → "vasya") to avoid an empty name in greetings.
*/
export interface NameSource {
first_name?: string | null;
last_name?: string | null;
username?: string | null;
telegram_id?: number | null;
email?: string | null;
}
export function displayName(user?: NameSource | null): string {
if (!user) return '';
const fullName = [user.first_name, user.last_name]
.filter((part): part is string => Boolean(part && part.trim()))
.filter((part): part is string => Boolean(part?.trim()))
.join(' ');
if (fullName) return fullName;
if (user.username) return user.username;
if (user.telegram_id) return `#${user.telegram_id}`;
const emailLocalPart = user.email?.trim().split('@')[0];
if (emailLocalPart) return emailLocalPart;
return '';
}