uchill/front_material/app/(protected)/request-mentor/page.tsx

904 lines
36 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { useState, useEffect, useCallback } from 'react';
import { useAuth } from '@/contexts/AuthContext';
import { useRouter } from 'next/navigation';
import { sendMentorshipRequest, getMyMentorshipRequests, getMyMentors, getMyInvitations, confirmInvitationAsStudent, rejectInvitationAsStudent, type MentorInvitation } from '@/api/students';
import { format } from 'date-fns';
import { ru } from 'date-fns/locale';
import { loadComponent } from '@/lib/material-components';
export default function RequestMentorPage() {
const { user, loading: authLoading } = useAuth();
const router = useRouter();
const [componentsLoaded, setComponentsLoaded] = useState(false);
const [mentorCode, setMentorCode] = useState('');
const [submitting, setSubmitting] = useState(false);
const [success, setSuccess] = useState(false);
const [addError, setAddError] = useState('');
const [showAddPanel, setShowAddPanel] = useState(false);
const [activeTab, setActiveTab] = useState<'connect' | 'awaiting' | 'invitations'>('connect');
const [myRequests, setMyRequests] = useState<Array<{
id: number;
status: string;
created_at: string | null;
updated_at: string | null;
mentor: { id: number; email: string; first_name: string; last_name: string; avatar_url?: string | null };
}>>([]);
const [loadingRequests, setLoadingRequests] = useState(false);
const [myMentors, setMyMentors] = useState<Array<{ id: number; email: string; first_name: string; last_name: string; avatar_url?: string | null }>>([]);
const [myInvitations, setMyInvitations] = useState<MentorInvitation[]>([]);
const [loadingInvitations, setLoadingInvitations] = useState(false);
const [confirmingId, setConfirmingId] = useState<number | null>(null);
const [rejectingId, setRejectingId] = useState<number | null>(null);
const [invitationError, setInvitationError] = useState<string | null>(null);
const loadData = useCallback(() => {
if (user?.role !== 'client') return;
setLoadingRequests(true);
setLoadingInvitations(true);
Promise.all([
getMyMentorshipRequests(),
getMyMentors(),
getMyInvitations(),
])
.then(([requests, mentors, invitations]) => {
setMyRequests(requests);
setMyMentors(mentors);
setMyInvitations(invitations);
setInvitationError(null);
})
.catch(() => {})
.finally(() => {
setLoadingRequests(false);
setLoadingInvitations(false);
});
}, [user?.role]);
useEffect(() => {
loadComponent('elevated-card').then(() => setComponentsLoaded(true)).catch(() => setComponentsLoaded(true));
}, []);
useEffect(() => {
if (user?.role !== 'client') {
router.replace('/dashboard');
return;
}
}, [user, router]);
useEffect(() => {
loadData();
}, [loadData]);
const handleSubmit = async () => {
setAddError('');
const code = mentorCode.trim().toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 8);
if (code.length !== 8) {
setAddError('Введите 8-символьный код (цифры и латинские буквы)');
return;
}
setSubmitting(true);
try {
await sendMentorshipRequest(code);
setSuccess(true);
setMentorCode('');
setActiveTab('awaiting'); // Показать вкладку с отправленным запросом
loadData();
} catch (err: any) {
setAddError(err?.response?.data?.error || 'Не удалось отправить запрос');
} finally {
setSubmitting(false);
}
};
if (authLoading || !user) {
return (
<div style={{ padding: 40, textAlign: 'center', minHeight: '50vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
Загрузка...
</div>
);
}
if (user?.role !== 'client') {
return null;
}
if (!componentsLoaded) {
return (
<div style={{ padding: 24, minHeight: '50vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
Загрузка...
</div>
);
}
const pendingRequests = myRequests.filter((r) => r.status === 'pending_mentor' || r.status === 'pending');
const pendingInvitationsFromMentors = myInvitations.filter((i) =>
['pending_student', 'pending_parent', 'pending'].includes(i.status)
);
const rejectedRequests = myRequests.filter((r) => r.status === 'rejected');
return (
<div
style={{
padding: '24px',
}}
data-tour="request-mentor-root"
>
{/* Табы всегда видны — Менторы | Ожидают ответа (ваши запросы) | Входящие приглашения (от менторов) */}
<div
data-tour="request-mentor-tabs"
style={{
display: 'flex',
gap: 4,
marginBottom: 24,
borderBottom: '1px solid var(--ios26-list-divider, rgba(0,0,0,0.12))',
paddingBottom: 0,
}}
>
<button
type="button"
onClick={() => setActiveTab('connect')}
style={{
padding: '12px 20px',
border: 'none',
borderBottom: activeTab === 'connect' ? '2px solid var(--md-sys-color-primary)' : '2px solid transparent',
background: 'transparent',
color: activeTab === 'connect' ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-on-surface-variant)',
fontSize: 16,
fontWeight: 600,
cursor: 'pointer',
}}
>
Менторы
</button>
<button
type="button"
onClick={() => setActiveTab('awaiting')}
style={{
padding: '12px 20px',
border: 'none',
borderBottom: activeTab === 'awaiting' ? '2px solid var(--md-sys-color-primary)' : '2px solid transparent',
background: 'transparent',
color: activeTab === 'awaiting' ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-on-surface-variant)',
fontSize: 16,
fontWeight: 600,
cursor: 'pointer',
}}
>
Ожидают ответа {pendingRequests.length > 0 && `(${pendingRequests.length})`}
</button>
<button
type="button"
onClick={() => setActiveTab('invitations')}
style={{
padding: '12px 20px',
border: 'none',
borderBottom: activeTab === 'invitations' ? '2px solid var(--md-sys-color-primary)' : '2px solid transparent',
background: 'transparent',
color: activeTab === 'invitations' ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-on-surface-variant)',
fontSize: 16,
fontWeight: 600,
cursor: 'pointer',
}}
>
Входящие приглашения {pendingInvitationsFromMentors.length > 0 && `(${pendingInvitationsFromMentors.length})`}
</button>
</div>
{loadingRequests || loadingInvitations ? (
<div style={{ display: 'flex', justifyContent: 'center', padding: 40 }}>
Загрузка...
</div>
) : activeTab === 'invitations' ? (
pendingInvitationsFromMentors.length === 0 ? (
<md-elevated-card style={{ padding: 40, borderRadius: 20, textAlign: 'center' }}>
<p style={{ fontSize: 16, color: 'var(--md-sys-color-on-surface-variant)' }}>
Нет входящих приглашений
</p>
</md-elevated-card>
) : (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
{invitationError && (
<div
style={{
padding: 12,
borderRadius: 12,
background: 'var(--md-sys-color-error-container)',
color: 'var(--md-sys-color-on-error-container)',
fontSize: 14,
}}
>
{invitationError}
</div>
)}
<div
className="students-cards-grid"
style={{
display: 'grid',
gridTemplateColumns: 'repeat(5, minmax(0, 1fr))',
gap: '16px',
alignItems: 'start',
}}
>
{pendingInvitationsFromMentors.map((inv) => {
const mentorName = [inv.mentor?.first_name, inv.mentor?.last_name].filter(Boolean).join(' ') || inv.mentor?.email || 'Ментор';
const initials = [inv.mentor?.first_name?.[0], inv.mentor?.last_name?.[0]].filter(Boolean).map((c) => c?.toUpperCase()).join('') || inv.mentor?.email?.[0]?.toUpperCase() || 'М';
return (
<md-elevated-card
key={inv.id}
style={{
borderRadius: 24,
overflow: 'hidden',
background: 'var(--md-sys-color-surface)',
boxShadow: '0 8px 24px rgba(0,0,0,0.08)',
}}
>
<div
style={{
height: '300px',
width: '100%',
background: 'linear-gradient(135deg, rgba(116,68,253,0.18), rgba(255,255,255,0.5))',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<div
style={{
width: 80,
height: 80,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'rgba(103, 80, 164, 0.18)',
color: 'var(--md-sys-color-primary)',
fontSize: 32,
fontWeight: 700,
}}
>
{initials}
</div>
</div>
<div style={{ padding: '14px 14px 16px' }}>
<div style={{ fontSize: 18, fontWeight: 700, marginBottom: 6 }}>{mentorName}</div>
<div style={{ fontSize: 15, color: 'var(--md-sys-color-on-surface-variant)', marginBottom: 12 }}>
{inv.mentor?.email}
</div>
{inv.created_at && (
<div style={{ fontSize: 12, color: 'var(--md-sys-color-outline)', marginBottom: 12 }}>
{format(new Date(inv.created_at), 'd MMM yyyy, HH:mm', { locale: ru })}
</div>
)}
{inv.status === 'pending_parent' ? (
<span
style={{
display: 'inline-block',
fontSize: 13,
fontWeight: 600,
padding: '6px 12px',
borderRadius: 8,
background: 'var(--md-sys-color-tertiary-container)',
color: 'var(--md-sys-color-on-tertiary-container)',
}}
>
Ожидаем подтверждения родителя
</span>
) : (
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
<button
type="button"
disabled={confirmingId === inv.id || rejectingId === inv.id}
onClick={async () => {
setConfirmingId(inv.id);
try {
await confirmInvitationAsStudent(inv.id);
loadData();
} catch (err: any) {
const msg = err?.response?.data?.error || 'Ошибка';
setInvitationError(msg);
setTimeout(() => setInvitationError(null), 5000);
} finally {
setConfirmingId(null);
}
}}
style={{
padding: '8px 14px',
borderRadius: 12,
border: 'none',
background: 'var(--md-sys-color-primary)',
color: 'var(--md-sys-color-on-primary)',
fontSize: 14,
fontWeight: 600,
cursor: confirmingId === inv.id || rejectingId === inv.id ? 'not-allowed' : 'pointer',
flex: 1,
minWidth: 0,
}}
>
{confirmingId === inv.id ? '…' : 'Принять'}
</button>
<button
type="button"
disabled={confirmingId === inv.id || rejectingId === inv.id}
onClick={async () => {
setRejectingId(inv.id);
try {
await rejectInvitationAsStudent(inv.id);
loadData();
} catch (err: any) {
const msg = err?.response?.data?.error || 'Ошибка';
setInvitationError(msg);
setTimeout(() => setInvitationError(null), 5000);
} finally {
setRejectingId(null);
}
}}
style={{
padding: '8px 14px',
borderRadius: 12,
border: '1px solid var(--md-sys-color-outline)',
background: 'transparent',
color: 'var(--md-sys-color-on-surface)',
fontSize: 14,
fontWeight: 600,
cursor: confirmingId === inv.id || rejectingId === inv.id ? 'not-allowed' : 'pointer',
flex: 1,
minWidth: 0,
}}
>
{rejectingId === inv.id ? '…' : 'Отклонить'}
</button>
</div>
)}
</div>
</md-elevated-card>
);
})}
</div>
</div>
)
) : activeTab === 'awaiting' ? (
pendingRequests.length === 0 ? (
<md-elevated-card style={{ padding: 40, borderRadius: 20, textAlign: 'center' }}>
<p style={{ fontSize: 16, color: 'var(--md-sys-color-on-surface-variant)' }}>
Нет запросов, ожидающих ответа
</p>
</md-elevated-card>
) : (
<div
className="students-cards-grid"
style={{
display: 'grid',
gridTemplateColumns: 'repeat(5, minmax(0, 1fr))',
gap: '16px',
alignItems: 'start',
}}
>
{pendingRequests.map((r) => {
const mentorName = [r.mentor?.first_name, r.mentor?.last_name].filter(Boolean).join(' ') || r.mentor?.email || 'Ментор';
const initials = [r.mentor?.first_name?.[0], r.mentor?.last_name?.[0]].filter(Boolean).map((c) => c?.toUpperCase()).join('') || r.mentor?.email?.[0]?.toUpperCase() || 'М';
return (
<md-elevated-card
key={r.id}
style={{
borderRadius: '24px',
overflow: 'hidden',
background: 'var(--md-sys-color-surface)',
boxShadow: '0 8px 24px rgba(0,0,0,0.08)',
}}
>
<div
style={{
height: '300px',
width: '100%',
background: 'linear-gradient(135deg, rgba(116,68,253,0.18), rgba(255,255,255,0.5))',
position: 'relative',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<div
style={{
width: 80,
height: 80,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'rgba(103, 80, 164, 0.18)',
color: 'var(--md-sys-color-primary)',
fontSize: 32,
fontWeight: 700,
}}
>
{initials}
</div>
</div>
<div style={{ padding: '14px 14px 16px' }}>
<div
style={{
fontSize: '18px',
fontWeight: 700,
color: 'var(--md-sys-color-on-surface)',
lineHeight: 1.2,
marginBottom: 6,
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical' as any,
overflow: 'hidden',
}}
>
{mentorName}
</div>
<div
style={{
fontSize: '15px',
color: 'var(--md-sys-color-on-surface-variant)',
lineHeight: 1.2,
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical' as any,
overflow: 'hidden',
}}
>
{r.mentor?.email || '—'}
</div>
{r.created_at && (
<div style={{ fontSize: 12, color: 'var(--md-sys-color-outline)', marginTop: 6 }}>
{format(new Date(r.created_at), 'd MMM yyyy, HH:mm', { locale: ru })}
</div>
)}
<span
style={{
display: 'inline-block',
marginTop: 8,
fontSize: 13,
fontWeight: 600,
padding: '4px 10px',
borderRadius: 8,
background: 'var(--md-sys-color-tertiary-container)',
color: 'var(--md-sys-color-on-tertiary-container)',
}}
>
Ожидает
</span>
</div>
</md-elevated-card>
);
})}
</div>
)
) : (
<div
className="students-cards-grid"
style={{
display: 'grid',
gridTemplateColumns: 'repeat(5, minmax(0, 1fr))',
gap: '16px',
alignItems: 'start',
}}
>
{/* Карточки подключённых менторов (из client.mentors — включая принятые приглашения) */}
{myMentors.map((m) => {
const mentorName = [m.first_name, m.last_name].filter(Boolean).join(' ') || m.email || 'Ментор';
const initials = [m.first_name?.[0], m.last_name?.[0]].filter(Boolean).map((c) => c?.toUpperCase()).join('') || m.email?.[0]?.toUpperCase() || 'М';
const avatarUrl = m.avatar_url || null;
const req = myRequests.find((r) => r.mentor?.id === m.id);
const statusLabel = 'Принято';
const statusBg = 'var(--md-sys-color-primary-container)';
const statusColor = 'var(--md-sys-color-on-primary-container)';
return (
<md-elevated-card
key={`mentor-${m.id}`}
style={{
borderRadius: '24px',
overflow: 'hidden',
background: 'var(--md-sys-color-surface)',
boxShadow: '0 8px 24px rgba(0,0,0,0.08)',
}}
>
<div
style={{
height: '300px',
width: '100%',
background: avatarUrl ? 'transparent' : 'linear-gradient(135deg, rgba(116,68,253,0.18), rgba(255,255,255,0.5))',
position: 'relative',
}}
>
{avatarUrl ? (
// eslint-disable-next-line @next/next/no-img-element
<img
src={avatarUrl}
alt={mentorName}
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
display: 'block',
}}
/>
) : (
<div
style={{
position: 'absolute',
inset: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'linear-gradient(135deg, rgba(116,68,253,0.18), rgba(255,255,255,0.5))',
}}
>
<div
style={{
width: 80,
height: 80,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'rgba(103, 80, 164, 0.18)',
color: 'var(--md-sys-color-primary)',
fontSize: 32,
fontWeight: 700,
}}
>
{initials}
</div>
</div>
)}
</div>
<div style={{ padding: '14px 14px 16px' }}>
<div
style={{
fontSize: '18px',
fontWeight: 700,
color: 'var(--md-sys-color-on-surface)',
lineHeight: 1.2,
marginBottom: 6,
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical' as any,
overflow: 'hidden',
}}
>
{mentorName}
</div>
<div
style={{
fontSize: '15px',
color: 'var(--md-sys-color-on-surface-variant)',
lineHeight: 1.2,
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical' as any,
overflow: 'hidden',
}}
>
{m.email || '—'}
</div>
{req?.created_at && (
<div style={{ fontSize: 12, color: 'var(--md-sys-color-outline)', marginTop: 6 }}>
{format(new Date(req.created_at), 'd MMM yyyy, HH:mm', { locale: ru })}
</div>
)}
<span
style={{
display: 'inline-block',
marginTop: 8,
fontSize: 13,
fontWeight: 600,
padding: '4px 10px',
borderRadius: 8,
background: statusBg,
color: statusColor,
}}
>
{statusLabel}
</span>
</div>
</md-elevated-card>
);
})}
{/* Карточки отклонённых запросов */}
{rejectedRequests.map((r) => {
const mentorName = [r.mentor?.first_name, r.mentor?.last_name].filter(Boolean).join(' ') || r.mentor?.email || 'Ментор';
const initials = [r.mentor?.first_name?.[0], r.mentor?.last_name?.[0]].filter(Boolean).map((c) => c?.toUpperCase()).join('') || r.mentor?.email?.[0]?.toUpperCase() || 'М';
return (
<md-elevated-card
key={`rejected-${r.id}`}
style={{
borderRadius: '24px',
overflow: 'hidden',
background: 'var(--md-sys-color-surface)',
boxShadow: '0 8px 24px rgba(0,0,0,0.08)',
}}
>
<div
style={{
height: '300px',
width: '100%',
background: 'linear-gradient(135deg, rgba(116,68,253,0.18), rgba(255,255,255,0.5))',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<div
style={{
width: 80,
height: 80,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'rgba(103, 80, 164, 0.18)',
color: 'var(--md-sys-color-primary)',
fontSize: 32,
fontWeight: 700,
}}
>
{initials}
</div>
</div>
<div style={{ padding: '14px 14px 16px' }}>
<div style={{ fontSize: 18, fontWeight: 700, marginBottom: 6 }}>{mentorName}</div>
<div style={{ fontSize: 15, color: 'var(--md-sys-color-on-surface-variant)', marginBottom: 6 }}>{r.mentor?.email || '—'}</div>
{r.created_at && (
<div style={{ fontSize: 12, color: 'var(--md-sys-color-outline)', marginBottom: 8 }}>
{format(new Date(r.created_at), 'd MMM yyyy, HH:mm', { locale: ru })}
</div>
)}
<span
style={{
display: 'inline-block',
fontSize: 13,
fontWeight: 600,
padding: '4px 10px',
borderRadius: 8,
background: 'var(--md-sys-color-error-container)',
color: 'var(--md-sys-color-on-error-container)',
}}
>
Отклонено
</span>
</div>
</md-elevated-card>
);
})}
{/* Карточка «Подключиться к ментору» */}
<md-elevated-card
style={{
borderRadius: '24px',
overflow: 'hidden',
cursor: 'pointer',
background: 'var(--md-sys-color-surface-container-low)',
boxShadow: '0 8px 24px rgba(0,0,0,0.06)',
}}
onClick={() => {
setShowAddPanel(true);
setAddError('');
setSuccess(false);
setMentorCode('');
}}
>
<div
style={{
height: '300px',
width: '100%',
background: 'linear-gradient(135deg, rgba(116,68,253,0.18), rgba(255,255,255,0.5))',
position: 'relative',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<div
style={{
width: 80,
height: 80,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'rgba(103, 80, 164, 0.18)',
color: 'var(--md-sys-color-primary)',
fontSize: 40,
fontWeight: 600,
}}
>
+
</div>
</div>
<div style={{ padding: '14px 14px 16px', textAlign: 'center' }}>
<div
style={{
fontSize: 18,
fontWeight: 700,
color: 'var(--md-sys-color-on-surface)',
marginBottom: 6,
}}
>
Подключиться к ментору
</div>
<div
style={{
fontSize: 15,
color: 'var(--md-sys-color-on-surface-variant)',
lineHeight: 1.2,
}}
>
Введите код ментора
</div>
</div>
</md-elevated-card>
</div>
)}
{/* Боковая панель с формой (как на странице студентов) */}
{showAddPanel && (
<div
className="students-side-panel"
style={{
position: 'fixed',
top: 0,
right: 0,
height: '100vh',
width: 'min(420px, 100vw)',
padding: '20px 20px 24px',
background: 'var(--md-sys-color-surface)',
boxShadow: '0 0 24px rgba(0,0,0,0.18)',
borderTopLeftRadius: 24,
borderBottomLeftRadius: 24,
display: 'flex',
flexDirection: 'column',
gap: 16,
zIndex: 40,
}}
>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<div style={{ fontSize: 20, fontWeight: 700, color: 'var(--md-sys-color-on-surface)', marginBottom: 4 }}>
Подключиться к ментору
</div>
<div style={{ fontSize: 16, color: 'var(--md-sys-color-on-surface-variant)' }}>
Введите 8-символьный код ментора
</div>
</div>
<button
type="button"
onClick={() => {
setShowAddPanel(false);
setAddError('');
setSuccess(false);
}}
style={{
border: 'none',
background: 'transparent',
cursor: 'pointer',
fontSize: 18,
color: 'var(--md-sys-color-on-surface-variant)',
}}
>
</button>
</div>
<div style={{ flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 16 }}>
{success ? (
<div
style={{
padding: 20,
borderRadius: 12,
background: 'var(--md-sys-color-primary-container)',
color: 'var(--md-sys-color-on-primary-container)',
fontSize: 16,
}}
>
Запрос отправлен. Ожидайте ответа ментора.
</div>
) : (
<>
<label style={{ fontSize: 14, fontWeight: 600, color: 'var(--md-sys-color-on-surface)' }}>
Код ментора
</label>
<input
type="text"
inputMode="text"
maxLength={8}
value={mentorCode}
onChange={(e) => {
const v = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 8);
setMentorCode(v);
setAddError('');
}}
placeholder="A1B2C3D4"
disabled={submitting}
style={{
width: '100%',
padding: '14px 16px',
borderRadius: 12,
border: `1px solid ${addError ? 'var(--md-sys-color-error)' : 'var(--md-sys-color-outline)'}`,
background: 'var(--md-sys-color-surface-container-low)',
color: 'var(--md-sys-color-on-surface)',
fontSize: 18,
letterSpacing: 4,
boxSizing: 'border-box',
}}
/>
{addError && (
<p style={{ fontSize: 14, color: 'var(--md-sys-color-error)' }}>{addError}</p>
)}
<p style={{ fontSize: 13, color: 'var(--md-sys-color-on-surface-variant)' }}>
Ментор получит уведомление и сможет принять или отклонить запрос.
</p>
<button
type="button"
disabled={submitting || mentorCode.length !== 8}
onClick={() => handleSubmit()}
style={{
padding: '12px 24px',
borderRadius: 12,
border: 'none',
background:
submitting || mentorCode.length !== 8
? 'var(--md-sys-color-surface-container-high)'
: 'var(--md-sys-color-primary)',
color:
submitting || mentorCode.length !== 8
? 'var(--md-sys-color-on-surface-variant)'
: 'var(--md-sys-color-on-primary)',
fontSize: 16,
fontWeight: 600,
cursor: submitting || mentorCode.length !== 8 ? 'not-allowed' : 'pointer',
opacity: submitting || mentorCode.length !== 8 ? 0.7 : 1,
}}
>
{submitting ? 'Отправка…' : 'Отправить запрос'}
</button>
</>
)}
{user?.universal_code && (
<div
style={{
marginTop: 24,
padding: 16,
borderRadius: 12,
background: 'var(--md-sys-color-primary)',
}}
>
<div style={{ fontSize: 13, color: '#fff', marginBottom: 8 }}>
Ваш 8-символьный код
</div>
<div style={{ display: 'flex', gap: 4, flexWrap: 'wrap', marginBottom: 8 }}>
{(user.universal_code || '').split('').map((char, i) => (
<span
key={i}
style={{
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
padding: '8px 10px',
border: '1px solid #fff',
borderRadius: 6,
fontSize: 18,
fontWeight: 700,
color: '#fff',
}}
>
{char}
</span>
))}
</div>
<div style={{ fontSize: 12, color: '#fff', opacity: 0.9 }}>
Поделитесь кодом с ментором он сможет добавить вас по приглашению
</div>
</div>
)}
</div>
</div>
)}
</div>
);
}