init
This commit is contained in:
113
frontend/src/App.jsx
Normal file
113
frontend/src/App.jsx
Normal file
@@ -0,0 +1,113 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import './App.css'
|
||||
|
||||
function App() {
|
||||
const [userInfo, setUserInfo] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
// Получаем информацию о пользователе от бэкенда
|
||||
fetch('/api/user-info')
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
return response.json()
|
||||
})
|
||||
.then(data => {
|
||||
setUserInfo(data)
|
||||
setLoading(false)
|
||||
})
|
||||
.catch(err => {
|
||||
setError(err.message)
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="loading">Загрузка...</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="error">
|
||||
<h2>Ошибка</h2>
|
||||
<p>{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<header className="header">
|
||||
<h1>Dex Authentication Demo</h1>
|
||||
<p className="subtitle">Демонстрация аутентификации через DexAuthenticator</p>
|
||||
</header>
|
||||
|
||||
<div className="user-card">
|
||||
<h2>Информация о пользователе</h2>
|
||||
<div className="info-grid">
|
||||
<div className="info-item">
|
||||
<span className="label">Email:</span>
|
||||
<span className="value">{userInfo.email}</span>
|
||||
</div>
|
||||
<div className="info-item">
|
||||
<span className="label">Полное имя:</span>
|
||||
<span className="value">{userInfo.full_name}</span>
|
||||
</div>
|
||||
{userInfo.organization && (
|
||||
<div className="info-item">
|
||||
<span className="label">Организация:</span>
|
||||
<span className="value">{userInfo.organization.name}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="roles-section">
|
||||
<h3>Роли</h3>
|
||||
<div className="roles-list">
|
||||
{userInfo.roles.map(role => (
|
||||
<div key={role.id} className="role-badge">
|
||||
<span className="role-name">{role.name}</span>
|
||||
{role.description && (
|
||||
<span className="role-description">{role.description}</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="links-section">
|
||||
<h3>Доступные ресурсы</h3>
|
||||
{userInfo.available_links.length > 0 ? (
|
||||
<div className="links-grid">
|
||||
{userInfo.available_links.map(link => (
|
||||
<a
|
||||
key={link.id}
|
||||
href={link.url}
|
||||
className="link-card"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h4>{link.title}</h4>
|
||||
{link.description && <p>{link.description}</p>}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="no-links">У вас нет доступных ресурсов</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
Reference in New Issue
Block a user