| 'use client' |
|
|
| interface LoadingSpinnerProps { |
| |
| size?: 'sm' | 'md' | 'lg' |
| |
| label?: string |
| |
| fullPage?: boolean |
| |
| className?: string |
| } |
|
|
| const sizeClasses = { |
| sm: 'w-5 h-5 border-2', |
| md: 'w-8 h-8 border-3', |
| lg: 'w-12 h-12 border-4', |
| } |
|
|
| export function LoadingSpinner({ |
| size = 'md', |
| label, |
| fullPage = false, |
| className = '', |
| }: LoadingSpinnerProps) { |
| const spinner = ( |
| <div className={`flex flex-col items-center justify-center gap-3 ${className}`}> |
| <div |
| className={`${sizeClasses[size]} border-gray-200 border-t-blue-600 rounded-full animate-spin`} |
| role="status" |
| aria-label={label || 'Yükleniyor'} |
| /> |
| {label && <p className="text-sm text-gray-500">{label}</p>} |
| </div> |
| ) |
|
|
| if (fullPage) { |
| return ( |
| <div className="min-h-[60vh] flex items-center justify-center"> |
| {spinner} |
| </div> |
| ) |
| } |
|
|
| return spinner |
| } |
|
|
| |
| export function Skeleton({ |
| className = '', |
| lines = 1, |
| }: { |
| className?: string |
| lines?: number |
| }) { |
| return ( |
| <div className={`animate-pulse space-y-2 ${className}`}> |
| {Array.from({ length: lines }).map((_, i) => ( |
| <div |
| key={i} |
| className="h-4 bg-gray-200 rounded" |
| style={{ width: i === lines - 1 && lines > 1 ? '75%' : '100%' }} |
| /> |
| ))} |
| </div> |
| ) |
| } |
|
|
| |
| export function CardSkeleton({ count = 3 }: { count?: number }) { |
| return ( |
| <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> |
| {Array.from({ length: count }).map((_, i) => ( |
| <div key={i} className="bg-white border border-gray-200 rounded-xl p-4 animate-pulse"> |
| <div className="h-4 bg-gray-200 rounded w-1/3 mb-3" /> |
| <div className="h-6 bg-gray-200 rounded w-2/3 mb-2" /> |
| <div className="h-4 bg-gray-200 rounded w-1/2" /> |
| </div> |
| ))} |
| </div> |
| ) |
| } |
|
|
| |
| export function TableSkeleton({ rows = 5, cols = 4 }: { rows?: number; cols?: number }) { |
| return ( |
| <div className="space-y-2"> |
| {Array.from({ length: rows }).map((_, r) => ( |
| <div key={r} className="flex gap-4 animate-pulse"> |
| {Array.from({ length: cols }).map((_, c) => ( |
| <div |
| key={c} |
| className="h-4 bg-gray-200 rounded flex-1" |
| style={{ maxWidth: c === 0 ? '120px' : undefined }} |
| /> |
| ))} |
| </div> |
| ))} |
| </div> |
| ) |
| } |
|
|