170 lines
5.2 KiB
TypeScript
170 lines
5.2 KiB
TypeScript
'use client';
|
||
|
||
import { useEffect, useState } from 'react';
|
||
import { loadComponent } from '@/lib/material-components';
|
||
import { useOptimizedFetch } from '@/hooks/useOptimizedFetch';
|
||
import { useRouter } from 'next/navigation';
|
||
|
||
export default function ChildrenPage() {
|
||
const router = useRouter();
|
||
const [componentsLoaded, setComponentsLoaded] = useState(false);
|
||
const [selectedChild, setSelectedChild] = useState<number | null>(null);
|
||
|
||
useEffect(() => {
|
||
Promise.all([
|
||
loadComponent('elevated-card'),
|
||
loadComponent('filled-button'),
|
||
loadComponent('icon'),
|
||
loadComponent('list'),
|
||
loadComponent('list-item'),
|
||
]).then(() => {
|
||
setComponentsLoaded(true);
|
||
}).catch((err) => {
|
||
console.error('Error loading components:', err);
|
||
setComponentsLoaded(true);
|
||
});
|
||
}, []);
|
||
|
||
const { data: childrenData, loading } = useOptimizedFetch({
|
||
url: '/users/parents/children/',
|
||
cacheKey: 'children_list',
|
||
cacheTTL: 5 * 60 * 1000, // 5 минут
|
||
});
|
||
|
||
if (!componentsLoaded) {
|
||
return (
|
||
<div style={{
|
||
display: 'flex',
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
height: '50vh'
|
||
}}>
|
||
<div>Загрузка...</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
const children = childrenData?.results || childrenData || [];
|
||
|
||
return (
|
||
<div>
|
||
<h1 style={{
|
||
fontSize: '28px',
|
||
fontWeight: '400',
|
||
marginBottom: '24px',
|
||
color: 'var(--md-sys-color-on-surface)'
|
||
}}>
|
||
Мои дети
|
||
</h1>
|
||
|
||
{loading ? (
|
||
<div style={{
|
||
display: 'flex',
|
||
justifyContent: 'center',
|
||
padding: '40px'
|
||
}}>
|
||
<div>Загрузка...</div>
|
||
</div>
|
||
) : children.length === 0 ? (
|
||
<md-elevated-card style={{
|
||
padding: '40px',
|
||
borderRadius: '20px',
|
||
textAlign: 'center'
|
||
}}>
|
||
<md-icon style={{
|
||
fontSize: '64px',
|
||
color: 'var(--md-sys-color-on-surface-variant)',
|
||
marginBottom: '16px'
|
||
}}>
|
||
family_restroom
|
||
</md-icon>
|
||
<p style={{
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface-variant)',
|
||
marginBottom: '16px'
|
||
}}>
|
||
Нет привязанных детей
|
||
</p>
|
||
</md-elevated-card>
|
||
) : (
|
||
<div style={{
|
||
display: 'grid',
|
||
gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
|
||
gap: '16px'
|
||
}}>
|
||
{children.map((child: any) => (
|
||
<md-elevated-card
|
||
key={child.id}
|
||
style={{
|
||
padding: '24px',
|
||
borderRadius: '20px',
|
||
cursor: 'pointer',
|
||
transition: 'transform 0.2s',
|
||
border: selectedChild === child.id
|
||
? '2px solid var(--md-sys-color-primary)'
|
||
: 'none'
|
||
}}
|
||
onClick={() => {
|
||
setSelectedChild(child.id);
|
||
localStorage.setItem('selected_child_id', child.id.toString());
|
||
}}
|
||
onMouseEnter={(e: any) => {
|
||
e.currentTarget.style.transform = 'translateY(-4px)';
|
||
}}
|
||
onMouseLeave={(e: any) => {
|
||
e.currentTarget.style.transform = 'translateY(0)';
|
||
}}
|
||
>
|
||
<div style={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: '16px',
|
||
marginBottom: '12px'
|
||
}}>
|
||
<div style={{
|
||
width: '48px',
|
||
height: '48px',
|
||
borderRadius: '50%',
|
||
background: 'var(--md-sys-color-primary-container)',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
color: 'var(--md-sys-color-primary)'
|
||
}}>
|
||
<md-icon>person</md-icon>
|
||
</div>
|
||
<div style={{ flex: 1 }}>
|
||
<h3 style={{
|
||
fontSize: '18px',
|
||
fontWeight: '500',
|
||
margin: 0,
|
||
color: 'var(--md-sys-color-on-surface)'
|
||
}}>
|
||
{child.first_name || ''} {child.last_name || ''}
|
||
</h3>
|
||
<p style={{
|
||
fontSize: '14px',
|
||
color: 'var(--md-sys-color-on-surface-variant)',
|
||
margin: 0
|
||
}}>
|
||
{child.email}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<md-filled-button
|
||
style={{ width: '100%' }}
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
router.push(`/children-progress?child=${child.id}`);
|
||
}}
|
||
>
|
||
Посмотреть прогресс
|
||
</md-filled-button>
|
||
</md-elevated-card>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|