Add CigaretteLoader component for improved loading experience in Dashboard
- Introduced a new CigaretteLoader component to replace the default loading indicator in the Dashboard. - Enhanced the loading experience with a custom animated SVG representation of a cigarette.
This commit is contained in:
parent
56b475ef55
commit
0187796388
162
src/components/CigaretteLoader.tsx
Normal file
162
src/components/CigaretteLoader.tsx
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export const CigaretteLoader = () => (
|
||||||
|
<div style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
height: '100vh',
|
||||||
|
backgroundColor: '#1a1a1a'
|
||||||
|
}}>
|
||||||
|
<svg width="200" height="60" viewBox="0 0 200 60" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
{/* Градиент для сигареты */}
|
||||||
|
<linearGradient id="cigaretteGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||||
|
<stop offset="0%" style={{ stopColor: '#f5f5f5', stopOpacity: 1 }} />
|
||||||
|
<stop offset="95%" style={{ stopColor: '#e0e0e0', stopOpacity: 1 }} />
|
||||||
|
<stop offset="100%" style={{ stopColor: '#d4a574', stopOpacity: 1 }} />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
{/* Градиент для тлеющей части */}
|
||||||
|
<linearGradient id="burningGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||||
|
<stop offset="0%" style={{ stopColor: '#ff6b35', stopOpacity: 1 }} />
|
||||||
|
<stop offset="50%" style={{ stopColor: '#ff8c42', stopOpacity: 1 }} />
|
||||||
|
<stop offset="100%" style={{ stopColor: '#ffa600', stopOpacity: 1 }} />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
{/* Маска для эффекта сгорания */}
|
||||||
|
<mask id="burnMask">
|
||||||
|
<rect x="0" y="0" width="200" height="60" fill="white">
|
||||||
|
<animate
|
||||||
|
attributeName="width"
|
||||||
|
from="0"
|
||||||
|
to="200"
|
||||||
|
dur="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</mask>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
{/* Тело сигареты (не сгоревшая часть) */}
|
||||||
|
<rect x="0" y="22" width="180" height="16" rx="2" fill="url(#cigaretteGradient)" />
|
||||||
|
|
||||||
|
{/* Фильтр */}
|
||||||
|
<rect x="175" y="20" width="20" height="20" rx="2" fill="#d4a574" />
|
||||||
|
<line x1="180" y1="20" x2="180" y2="40" stroke="#b8956a" strokeWidth="1" />
|
||||||
|
<line x1="185" y1="20" x2="185" y2="40" stroke="#b8956a" strokeWidth="1" />
|
||||||
|
<line x1="190" y1="20" x2="190" y2="40" stroke="#b8956a" strokeWidth="1" />
|
||||||
|
|
||||||
|
{/* Сгоревшая часть с маской */}
|
||||||
|
<g mask="url(#burnMask)">
|
||||||
|
<rect x="0" y="22" width="180" height="16" fill="#333" opacity="0.8" />
|
||||||
|
|
||||||
|
{/* Тлеющий край */}
|
||||||
|
<rect x="0" y="24" width="5" height="12" fill="url(#burningGradient)">
|
||||||
|
<animate
|
||||||
|
attributeName="x"
|
||||||
|
from="0"
|
||||||
|
to="180"
|
||||||
|
dur="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
|
||||||
|
{/* Искры */}
|
||||||
|
<circle r="2" fill="#ff6b35">
|
||||||
|
<animate
|
||||||
|
attributeName="cx"
|
||||||
|
from="5"
|
||||||
|
to="185"
|
||||||
|
dur="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="cy"
|
||||||
|
values="20;18;20"
|
||||||
|
dur="0.3s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
values="1;0.5;1"
|
||||||
|
dur="0.3s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
<circle r="1.5" fill="#ffa600">
|
||||||
|
<animate
|
||||||
|
attributeName="cx"
|
||||||
|
from="8"
|
||||||
|
to="188"
|
||||||
|
dur="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="cy"
|
||||||
|
values="40;42;40"
|
||||||
|
dur="0.4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
values="0.8;0.3;0.8"
|
||||||
|
dur="0.4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
{/* Дым */}
|
||||||
|
<g opacity="0.6">
|
||||||
|
<ellipse rx="3" ry="3" fill="#888">
|
||||||
|
<animate
|
||||||
|
attributeName="cx"
|
||||||
|
from="5"
|
||||||
|
to="185"
|
||||||
|
dur="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="cy"
|
||||||
|
from="18"
|
||||||
|
to="8"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
from="0.6"
|
||||||
|
to="0"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</ellipse>
|
||||||
|
<ellipse rx="4" ry="4" fill="#999">
|
||||||
|
<animate
|
||||||
|
attributeName="cx"
|
||||||
|
from="3"
|
||||||
|
to="183"
|
||||||
|
dur="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="cy"
|
||||||
|
from="18"
|
||||||
|
to="5"
|
||||||
|
dur="1.2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
from="0.5"
|
||||||
|
to="0"
|
||||||
|
dur="1.2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</ellipse>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
@ -7,9 +7,12 @@ import { SignInPage, SignUpPage } from './pages/auth'
|
|||||||
import { TrackerPage } from './pages/tracker'
|
import { TrackerPage } from './pages/tracker'
|
||||||
import { StatsPage } from './pages/stats'
|
import { StatsPage } from './pages/stats'
|
||||||
import { ProtectedRoute } from './components/ProtectedRoute'
|
import { ProtectedRoute } from './components/ProtectedRoute'
|
||||||
|
import { CigaretteLoader } from './components/CigaretteLoader'
|
||||||
|
|
||||||
const PageWrapper = ({ children }: React.PropsWithChildren) => (
|
const PageWrapper = ({ children }: React.PropsWithChildren) => (
|
||||||
<Suspense fallback={<div>Loading...</div>}>{children}</Suspense>
|
<Suspense fallback={<CigaretteLoader />}>
|
||||||
|
{children}
|
||||||
|
</Suspense>
|
||||||
)
|
)
|
||||||
|
|
||||||
export const Dashboard = () => {
|
export const Dashboard = () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user