- Add PWA configuration (manifest.json, service worker) - Implement light/dark theme system with purple accents - Replace desktop navbar with mobile-first bottom navigation - Redesign auth forms with mobile-optimized UI - Update Dashboard with gradient cards and touch-friendly actions - Add safe area support for iOS devices - Implement theme context with system preference detection - Optimize touch targets and mobile interactions - Add offline functionality through service worker
182 lines
No EOL
7.6 KiB
TypeScript
182 lines
No EOL
7.6 KiB
TypeScript
import React from 'react';
|
|
import { useAuth } from '../contexts/AuthContext';
|
|
import { Link } from 'react-router-dom';
|
|
|
|
const Dashboard: React.FC = () => {
|
|
const { user } = useAuth();
|
|
|
|
const statsCards = [
|
|
{
|
|
title: 'Collections',
|
|
value: '0',
|
|
icon: (
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
|
</svg>
|
|
),
|
|
color: 'primary'
|
|
},
|
|
{
|
|
title: 'Decks',
|
|
value: '0',
|
|
icon: (
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
|
</svg>
|
|
),
|
|
color: 'accent'
|
|
},
|
|
{
|
|
title: 'Total Cards',
|
|
value: '0',
|
|
icon: (
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 4V2a1 1 0 011-1h8a1 1 0 011 1v2M7 4H5a2 2 0 00-2 2v10a2 2 0 002 2h14a2 2 0 002-2V6a2 2 0 00-2-2h-2M7 4v6l2-2 2 2V4" />
|
|
</svg>
|
|
),
|
|
color: 'primary'
|
|
},
|
|
{
|
|
title: 'Total Value',
|
|
value: '$0',
|
|
icon: (
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1" />
|
|
</svg>
|
|
),
|
|
color: 'accent'
|
|
},
|
|
];
|
|
|
|
const quickActions = [
|
|
{
|
|
title: 'Scan Cards',
|
|
description: 'Use OCR to quickly add cards',
|
|
href: '/scanner',
|
|
icon: (
|
|
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" />
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 13a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
</svg>
|
|
),
|
|
gradient: 'from-primary-500 to-accent-500',
|
|
},
|
|
{
|
|
title: 'Browse Cards',
|
|
description: 'Explore your collection',
|
|
href: '/cards',
|
|
icon: (
|
|
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
|
</svg>
|
|
),
|
|
gradient: 'from-accent-500 to-primary-500',
|
|
},
|
|
{
|
|
title: 'Manage Collections',
|
|
description: 'Organize your cards',
|
|
href: '/collections',
|
|
icon: (
|
|
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
|
</svg>
|
|
),
|
|
gradient: 'from-primary-600 to-accent-400',
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Welcome Section */}
|
|
<div className="bg-gradient-to-br from-primary-500 via-primary-600 to-accent-500 p-6 rounded-2xl text-white shadow-lg">
|
|
<h1 className="text-2xl font-bold mb-2">
|
|
Welcome back, {user?.firstName || user?.username}! 👋
|
|
</h1>
|
|
<p className="text-primary-100">
|
|
Ready to manage your card collection?
|
|
</p>
|
|
</div>
|
|
|
|
{/* Quick Stats */}
|
|
<div className="grid grid-cols-2 gap-4">
|
|
{statsCards.map((stat, index) => (
|
|
<div
|
|
key={stat.title}
|
|
className="bg-white dark:bg-surface-800 p-4 rounded-xl shadow-sm border border-surface-200 dark:border-surface-700 transition-colors"
|
|
>
|
|
<div className={`inline-flex items-center justify-center w-10 h-10 rounded-lg mb-3 ${
|
|
stat.color === 'primary'
|
|
? 'bg-primary-100 text-primary-600 dark:bg-primary-900/30 dark:text-primary-400'
|
|
: 'bg-accent-100 text-accent-600 dark:bg-accent-900/30 dark:text-accent-400'
|
|
}`}>
|
|
{stat.icon}
|
|
</div>
|
|
<p className="text-2xl font-bold text-surface-900 dark:text-white">
|
|
{stat.value}
|
|
</p>
|
|
<p className="text-sm text-surface-600 dark:text-surface-400">
|
|
{stat.title}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Quick Actions */}
|
|
<div className="space-y-4">
|
|
<h2 className="text-lg font-semibold text-surface-900 dark:text-white">
|
|
Quick Actions
|
|
</h2>
|
|
|
|
{quickActions.map((action, index) => (
|
|
<Link
|
|
key={action.title}
|
|
to={action.href}
|
|
className="block bg-white dark:bg-surface-800 p-4 rounded-xl shadow-sm border border-surface-200 dark:border-surface-700 hover:shadow-md transition-all duration-200 active:scale-98"
|
|
>
|
|
<div className="flex items-center space-x-4">
|
|
<div className={`w-12 h-12 bg-gradient-to-r ${action.gradient} rounded-xl flex items-center justify-center text-white shadow-md`}>
|
|
{action.icon}
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className="font-semibold text-surface-900 dark:text-white">
|
|
{action.title}
|
|
</h3>
|
|
<p className="text-sm text-surface-600 dark:text-surface-400">
|
|
{action.description}
|
|
</p>
|
|
</div>
|
|
<svg className="w-5 h-5 text-surface-400 dark:text-surface-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
</svg>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
|
|
{/* Recent Activity */}
|
|
<div className="space-y-4">
|
|
<h2 className="text-lg font-semibold text-surface-900 dark:text-white">
|
|
Recent Activity
|
|
</h2>
|
|
|
|
<div className="bg-white dark:bg-surface-800 p-6 rounded-xl shadow-sm border border-surface-200 dark:border-surface-700 transition-colors">
|
|
<div className="text-center">
|
|
<div className="w-16 h-16 bg-surface-100 dark:bg-surface-700 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
|
<svg className="w-8 h-8 text-surface-400 dark:text-surface-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
|
</svg>
|
|
</div>
|
|
<p className="text-surface-600 dark:text-surface-400 mb-4">
|
|
No recent activity yet
|
|
</p>
|
|
<p className="text-sm text-surface-500 dark:text-surface-500">
|
|
Start by scanning some cards or creating a collection!
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Dashboard;
|