profile refactor
This commit is contained in:
@@ -1 +1,5 @@
|
||||
export { ProfilePage } from './ui/ProfilePage'
|
||||
export { ProfileDetailsItem } from './ui/items/ProfileDetailsItem'
|
||||
export { SecurityItem } from './ui/items/SecurityItem'
|
||||
export { MnemonicItem } from './ui/items/MnemonicItem'
|
||||
export { TransactionsItem } from './ui/items/TransactionsItem'
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-deep);
|
||||
}
|
||||
|
||||
.main {
|
||||
max-width: 1024px;
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 40px 32px 60px;
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-columns: 25% 1fr;
|
||||
gap: 32px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.sections {
|
||||
flex: 1;
|
||||
.menu {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
/* < 1024px: avatar + sections stack into a single column */
|
||||
/* < 1024px: menu and content stack into a single column */
|
||||
@media (max-width: 1023px) {
|
||||
.main {
|
||||
flex-direction: column;
|
||||
.page {
|
||||
grid-template-columns: 1fr;
|
||||
padding: 24px 20px 40px;
|
||||
gap: 24px;
|
||||
}
|
||||
@@ -32,7 +31,7 @@
|
||||
|
||||
/* < 640px: tighter page padding */
|
||||
@media (max-width: 639px) {
|
||||
.main {
|
||||
.page {
|
||||
padding: 16px 16px 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { WalletHeader } from '@widgets/wallet-header'
|
||||
import { KycBanner, ProfileSummary, ProfileDetails, SecuritySection, MnemonicSection } from '@widgets/profile'
|
||||
import { Outlet } from 'react-router-dom'
|
||||
import { KycBanner, ProfileMenu } from '@widgets/profile'
|
||||
import styles from './ProfilePage.module.css'
|
||||
|
||||
// Profile dashboard layout. The outer WalletLayout (see RouterProvider) renders
|
||||
// the header/footer; here we split into a ~25% menu column and a ~75% content
|
||||
// column. The active item is rendered into the inner <Outlet/>.
|
||||
export function ProfilePage() {
|
||||
return (
|
||||
<div className={styles.page}>
|
||||
<WalletHeader />
|
||||
<KycBanner />
|
||||
<main className={styles.main}>
|
||||
<ProfileSummary />
|
||||
<div className={styles.sections}>
|
||||
<ProfileDetails />
|
||||
<SecuritySection />
|
||||
<MnemonicSection />
|
||||
</div>
|
||||
<div className={styles.menu}>
|
||||
<ProfileMenu />
|
||||
</div>
|
||||
<main className={styles.content}>
|
||||
<KycBanner />
|
||||
<Outlet />
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
|
||||
10
src/pages/profile/ui/items/MnemonicItem.tsx
Normal file
10
src/pages/profile/ui/items/MnemonicItem.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { useMe } from '@features/auth'
|
||||
import { MnemonicSection } from '@widgets/profile'
|
||||
import { Spinner } from '@shared/ui'
|
||||
|
||||
// «Мнемоническая фраза» dashboard item.
|
||||
export function MnemonicItem() {
|
||||
const { isLoading } = useMe()
|
||||
if (isLoading) return <Spinner fullscreen label="Загрузка" />
|
||||
return <MnemonicSection />
|
||||
}
|
||||
11
src/pages/profile/ui/items/ProfileDetailsItem.tsx
Normal file
11
src/pages/profile/ui/items/ProfileDetailsItem.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { useMe } from '@features/auth'
|
||||
import { ProfileDetails } from '@widgets/profile'
|
||||
import { Spinner } from '@shared/ui'
|
||||
|
||||
// «Данные профиля» — default dashboard item. Shows a spinner while the profile
|
||||
// data is still loading, then the details form.
|
||||
export function ProfileDetailsItem() {
|
||||
const { isLoading } = useMe()
|
||||
if (isLoading) return <Spinner fullscreen label="Загрузка" />
|
||||
return <ProfileDetails />
|
||||
}
|
||||
10
src/pages/profile/ui/items/SecurityItem.tsx
Normal file
10
src/pages/profile/ui/items/SecurityItem.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { useMe } from '@features/auth'
|
||||
import { SecuritySection } from '@widgets/profile'
|
||||
import { Spinner } from '@shared/ui'
|
||||
|
||||
// «Безопасность» dashboard item.
|
||||
export function SecurityItem() {
|
||||
const { isLoading } = useMe()
|
||||
if (isLoading) return <Spinner fullscreen label="Загрузка" />
|
||||
return <SecuritySection />
|
||||
}
|
||||
7
src/pages/profile/ui/items/TransactionsItem.tsx
Normal file
7
src/pages/profile/ui/items/TransactionsItem.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import { TransactionsPanel } from '@widgets/transactions-panel'
|
||||
|
||||
// «Транзакции» dashboard item — the shared transactions panel (list + tabs).
|
||||
// The panel handles its own loading state.
|
||||
export function TransactionsItem() {
|
||||
return <TransactionsPanel />
|
||||
}
|
||||
@@ -1,45 +1,15 @@
|
||||
import { useState } from 'react'
|
||||
import { useMe } from '@features/auth'
|
||||
import { TransactionsList } from '@widgets/transactions-list'
|
||||
import { PurchaseRequestsList } from '@widgets/purchase-requests-list'
|
||||
import { TransactionsPanel } from '@widgets/transactions-panel'
|
||||
import styles from './TransactionsPage.module.css'
|
||||
|
||||
type Tab = 'transactions' | 'requests'
|
||||
|
||||
// The standalone /transactions route now redirects to /profile/transactions
|
||||
// (see RouterProvider). This page is kept as a thin wrapper around the shared
|
||||
// TransactionsPanel for any direct/legacy usage.
|
||||
export function TransactionsPage() {
|
||||
const { data } = useMe()
|
||||
const [tab, setTab] = useState<Tab>('transactions')
|
||||
|
||||
const isLegal = !!data && data.account_type !== 'individual'
|
||||
const activeTab: Tab = isLegal ? tab : 'transactions'
|
||||
|
||||
return (
|
||||
<div className={styles.inner}>
|
||||
<div className={styles.glow} />
|
||||
<h1 className={styles.title}>Транзакции</h1>
|
||||
|
||||
{isLegal && (
|
||||
<div className={styles.tabs}>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.tab}
|
||||
data-active={activeTab === 'transactions' || undefined}
|
||||
onClick={() => setTab('transactions')}
|
||||
>
|
||||
Транзакции
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.tab}
|
||||
data-active={activeTab === 'requests' || undefined}
|
||||
onClick={() => setTab('requests')}
|
||||
>
|
||||
Заявки
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'transactions' ? <TransactionsList /> : <PurchaseRequestsList />}
|
||||
<TransactionsPanel />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user