2026-05-13 14:25:47 +07:00
|
|
|
|
import { formatDate, formatDateTime } from '@/app/lib/formatDate';
|
|
|
|
|
|
import { useTranslations } from 'next-intl';
|
|
|
|
|
|
|
|
|
|
|
|
interface User {
|
|
|
|
|
|
fullName: string;
|
|
|
|
|
|
company: string | null;
|
|
|
|
|
|
email: string;
|
|
|
|
|
|
active: boolean;
|
|
|
|
|
|
phone: string;
|
|
|
|
|
|
genderType: 'MALE' | 'FEMALE';
|
|
|
|
|
|
birthday: string | null;
|
|
|
|
|
|
createdAt: string;
|
|
|
|
|
|
subscriptionType: 'DEMO' | string;
|
|
|
|
|
|
tariffs: null;
|
|
|
|
|
|
tariffInfo: TariffInfo;
|
|
|
|
|
|
permission: null;
|
|
|
|
|
|
verifiedStatus: 'VERIFIED' | 'PENDING' | 'UNVERIFIED';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface TariffInfo {
|
|
|
|
|
|
id: string;
|
|
|
|
|
|
status: 'EXPIRED' | 'ACTIVE' | 'PENDING';
|
|
|
|
|
|
startTariff: string;
|
|
|
|
|
|
endTariff: string;
|
|
|
|
|
|
tariffId: number;
|
|
|
|
|
|
tariffName: string;
|
|
|
|
|
|
tokens: number;
|
|
|
|
|
|
maxFileOnDisk: number;
|
|
|
|
|
|
currentFileOnDisk: number;
|
|
|
|
|
|
currentFileCounts: number;
|
|
|
|
|
|
maxFileCounts: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function UserInfoModalWindow({
|
|
|
|
|
|
userInfo,
|
|
|
|
|
|
setWindowClose,
|
|
|
|
|
|
setWindowChildren
|
|
|
|
|
|
}: {
|
|
|
|
|
|
userInfo: User, // Исправлено: ожидаем User, а не TariffInfo
|
|
|
|
|
|
setWindowClose: any,
|
|
|
|
|
|
setWindowChildren: any
|
|
|
|
|
|
}) {
|
|
|
|
|
|
const t = useTranslations('Global');
|
|
|
|
|
|
|
|
|
|
|
|
const formatBytes = (bytes: number) => {
|
|
|
|
|
|
if (bytes === 0) return '0 Bytes';
|
|
|
|
|
|
const k = 1024;
|
|
|
|
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
|
|
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const getStatusBadge = (status: string) => {
|
|
|
|
|
|
const statusConfig = {
|
|
|
|
|
|
'ACTIVE': { class: 'status-active', text: 'Active' },
|
|
|
|
|
|
'EXPIRED': { class: 'status-expired', text: 'Expired' },
|
|
|
|
|
|
'PENDING': { class: 'status-pending', text: 'Pending' },
|
|
|
|
|
|
'VERIFIED': { class: 'status-verified', text: 'Verified' },
|
|
|
|
|
|
'UNVERIFIED': { class: 'status-unverified', text: 'Unverified' }
|
|
|
|
|
|
};
|
|
|
|
|
|
const config = statusConfig[status as keyof typeof statusConfig];
|
|
|
|
|
|
return config ? <span className={`status-badge ${config.class}`}>{config.text}</span> : status;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const getGenderText = (gender: string) => {
|
2026-05-13 14:37:54 +07:00
|
|
|
|
return gender === 'MALE' ? t('male') : t('female');
|
2026-05-13 14:25:47 +07:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="modal-window-view-user">
|
|
|
|
|
|
<div className="modal-window-view-user-content">
|
|
|
|
|
|
<div className="user-info-wrapper">
|
|
|
|
|
|
{/* Карточка информации о пользователе */}
|
|
|
|
|
|
<div className="user-info-card">
|
|
|
|
|
|
<div className="info-header">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
<h4>{t('userInformation')}</h4>
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('fullName')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.fullName ? userInfo.fullName : '-'}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
|
|
|
|
|
{t('email')}:
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.email ? userInfo.email : '-'}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('phone')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.phone ? userInfo.phone : '-'}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
|
|
|
|
|
{t('company')}:
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.company ? userInfo.company : '-'}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('gender')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{getGenderText(userInfo?.genderType)}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('birthday')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.birthday ? formatDate(userInfo.birthday) : '-'}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('createdAt')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{formatDateTime(userInfo?.createdAt)}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('verifiedStatus')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{getStatusBadge(userInfo?.verifiedStatus)}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
|
|
|
|
|
{t('active')}:
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.active ? 'active' : 'not active'}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Карточка информации о тарифе */}
|
|
|
|
|
|
<div className="user-info-card">
|
|
|
|
|
|
<div className="info-header">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
<h4>{t('tariffInformation')}</h4>
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('tariffName')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.tariffInfo?.tariffName ? userInfo?.tariffInfo?.tariffName : '-'}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('tariffStatus')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{getStatusBadge(userInfo?.tariffInfo?.status)}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('tokens')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.tariffInfo?.tokens ? userInfo?.tariffInfo?.tokens : '-'}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('startDate')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{formatDate(userInfo?.tariffInfo?.startTariff)}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('endDate')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{formatDate(userInfo?.tariffInfo?.endTariff)}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Карточка использования диска */}
|
|
|
|
|
|
<div className="user-info-card">
|
|
|
|
|
|
<div className="info-header">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
<h4>{t('storageInformation')}</h4>
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('diskUsage')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{formatBytes(userInfo?.tariffInfo?.currentFileOnDisk)} / {formatBytes(userInfo?.tariffInfo?.maxFileOnDisk)}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-item">
|
|
|
|
|
|
<div className="info-label">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{t('fileCount')}:
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="info-value">
|
2026-05-13 14:37:54 +07:00
|
|
|
|
{userInfo?.tariffInfo?.currentFileCounts} / {userInfo?.tariffInfo?.maxFileCounts}
|
2026-05-13 14:25:47 +07:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|