profit-planet-frontend/src/app/dashboard/page.tsx
seaznCode 25fff9b1c3 feat: Implement user status management with custom hook
- Added `useUserStatus` hook to manage user status fetching and state.
- Integrated user status in Quick Action Dashboard and related pages.
- Enhanced error handling and loading states for user status.
- Updated profile completion and document upload flows to refresh user status after actions.
- Created a centralized API utility for handling requests and responses.
- Refactored authentication token management to use session storage.
2025-10-11 19:47:07 +02:00

279 lines
11 KiB
TypeScript

'use client'
import { useEffect } from 'react'
import { useRouter } from 'next/navigation'
import useAuthStore from '../store/authStore'
import Header from '../components/nav/Header'
import Footer from '../components/Footer'
import {
ShoppingBagIcon,
UsersIcon,
UserCircleIcon,
StarIcon,
ChartBarIcon,
HeartIcon,
BuildingOffice2Icon // <-- added
} from '@heroicons/react/24/outline'
export default function DashboardPage() {
const router = useRouter()
const user = useAuthStore(state => state.user)
const isAuthReady = useAuthStore(state => state.isAuthReady)
// Redirect if not logged in (only after auth is ready)
useEffect(() => {
if (isAuthReady && !user) {
router.push('/login')
}
}, [isAuthReady, user, router])
// Show loading until auth is ready or user is confirmed
if (!isAuthReady || !user) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[#8D6B1D] mx-auto mb-4"></div>
<p className="text-[#4A4A4A]">Loading...</p>
</div>
</div>
)
}
// Get user name
const getUserName = () => {
if (user.firstName && user.lastName) {
return `${user.firstName} ${user.lastName}`
}
if (user.firstName) return user.firstName
if (user.email) return user.email.split('@')[0]
return 'User'
}
// Quick actions
const quickActions = [
{
title: 'Browse Shop',
description: 'Explore sustainable products',
icon: ShoppingBagIcon,
href: '/shop',
color: 'bg-blue-500'
},
{
title: 'Join Community',
description: 'Connect with like-minded people',
icon: UsersIcon,
href: '/community',
color: 'bg-green-500'
},
{
title: 'Edit Profile',
description: 'Update your information',
icon: UserCircleIcon,
href: '/profile',
color: 'bg-purple-500'
}
]
// Stats (mock data for now)
const stats = [
{ label: 'Orders', value: '12', icon: ShoppingBagIcon },
{ label: 'Favorites', value: '8', icon: HeartIcon },
{ label: 'Gold Points', value: '250', icon: StarIcon },
{ label: 'Activity', value: '15', icon: ChartBarIcon }
]
// Referral statistics (mock values)
const referralStats = [
{ label: 'Registered Users', value: '123', icon: UsersIcon, color: 'bg-indigo-600' },
{ label: 'Personal Users', value: '85', icon: UserCircleIcon, color: 'bg-teal-600' },
{ label: 'Company Users', value: '38', icon: BuildingOffice2Icon, color: 'bg-amber-600' },
]
return (
<div className="min-h-screen flex flex-col bg-gray-50">
<Header />
<main className="flex-1 py-8 px-4 sm:px-6 lg:px-8">
<div className="max-w-7xl mx-auto">
{/* Welcome Section */}
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900">
Welcome back, {getUserName()}! 👋
</h1>
<p className="text-gray-600 mt-2">
Here's what's happening with your Profit Planet account
</p>
</div>
{/* Account setup note */}
<div className="mb-8 bg-blue-50 border border-blue-200 rounded-lg p-4">
<div className="flex">
<div className="flex-shrink-0">
<UserCircleIcon className="h-5 w-5 text-blue-400" aria-hidden="true" />
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-blue-800">
Complete your account setup
</h3>
<div className="mt-2 text-sm text-blue-700">
<p>
Complete your verification process to unlock all features.{' '}
<button
onClick={() => router.push('/quickaction-dashboard')}
className="font-medium underline text-blue-800 hover:text-blue-900"
>
Start verification
</button>
</p>
</div>
</div>
</div>
</div>
{/* Stats Grid - Tailwind UI Plus "With brand icon" */}
<div className="mb-8">
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4">
{stats.map((stat, index) => {
// Define icon colors for each stat
const iconColors = [
'bg-blue-500', // Orders
'bg-red-500', // Favorites
'bg-yellow-500', // Gold Points
'bg-green-500' // Activity
];
return (
<div key={index} className="relative overflow-hidden rounded-lg bg-white px-4 pb-12 pt-5 shadow sm:px-6 sm:pt-6">
<dt>
<div className={`absolute rounded-md ${iconColors[index]} p-3`}>
<stat.icon aria-hidden="true" className="h-6 w-6 text-white" />
</div>
<p className="ml-16 truncate text-sm font-medium text-gray-500">{stat.label}</p>
</dt>
<dd className="ml-16 flex items-baseline pb-6 sm:pb-7">
<p className="text-2xl font-semibold text-gray-900">{stat.value}</p>
<div className="absolute inset-x-0 bottom-0 bg-gray-50 px-4 py-4 sm:px-6">
<div className="text-sm">
<a href="#" className="font-medium text-[#8D6B1D] hover:text-[#7A5E1A]">
View details
</a>
</div>
</div>
</dd>
</div>
);
})}
</div>
</div>
{/* Referral Statistics */}
<div className="mb-8">
<h2 className="text-xl font-semibold text-gray-900 mb-4">Referral Statistics</h2>
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
{referralStats.map((stat, i) => (
<div key={i} className="relative overflow-hidden rounded-lg bg-white px-4 pb-10 pt-5 shadow sm:px-6 sm:pt-6">
<dt>
<div className={`absolute rounded-md ${stat.color} p-3`}>
<stat.icon aria-hidden="true" className="h-6 w-6 text-white" />
</div>
<p className="ml-16 truncate text-sm font-medium text-gray-500">{stat.label}</p>
</dt>
<dd className="ml-16 flex items-baseline pb-2">
<p className="text-2xl font-semibold text-gray-900">{stat.value}</p>
</dd>
</div>
))}
</div>
</div>
{/* Quick Actions */}
<div className="mb-8">
<h2 className="text-xl font-semibold text-gray-900 mb-4">Quick Actions</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{quickActions.map((action, index) => (
<button
key={index}
onClick={() => router.push(action.href)}
className="bg-white rounded-lg p-6 shadow-sm border border-gray-200 hover:shadow-md transition-shadow text-left group"
>
<div className="flex items-start">
<div className={`${action.color} rounded-lg p-3 group-hover:scale-105 transition-transform`}>
<action.icon className="h-6 w-6 text-white" />
</div>
<div className="ml-4 flex-1">
<h3 className="text-lg font-medium text-gray-900 group-hover:text-[#8D6B1D] transition-colors">
{action.title}
</h3>
<p className="text-sm text-gray-600 mt-1">
{action.description}
</p>
</div>
</div>
</button>
))}
</div>
</div>
{/* Gold Member Status */}
<div className="bg-gradient-to-r from-[#8D6B1D] to-[#B8860B] rounded-lg p-6 text-white mb-8">
<div className="flex items-center">
<StarIcon className="h-12 w-12 text-yellow-300" />
<div className="ml-4">
<h2 className="text-2xl font-bold">Gold Member Status</h2>
<p className="text-yellow-100 mt-1">
Enjoy exclusive benefits and discounts
</p>
</div>
<div className="ml-auto">
<button className="bg-white/20 hover:bg-white/30 px-4 py-2 rounded-lg text-white font-medium transition-colors">
View Benefits
</button>
</div>
</div>
</div>
{/* Recent Activity */}
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<h2 className="text-xl font-semibold text-gray-900 mb-4">Recent Activity</h2>
<div className="space-y-4">
<div className="flex items-center py-3 border-b border-gray-100 last:border-b-0">
<div className="bg-green-100 rounded-full p-2">
<ShoppingBagIcon className="h-5 w-5 text-green-600" />
</div>
<div className="ml-4 flex-1">
<p className="text-sm font-medium text-gray-900">Order completed</p>
<p className="text-sm text-gray-600">Eco-friendly water bottle</p>
</div>
<span className="text-sm text-gray-500">2 days ago</span>
</div>
<div className="flex items-center py-3 border-b border-gray-100 last:border-b-0">
<div className="bg-blue-100 rounded-full p-2">
<HeartIcon className="h-5 w-5 text-blue-600" />
</div>
<div className="ml-4 flex-1">
<p className="text-sm font-medium text-gray-900">Added to favorites</p>
<p className="text-sm text-gray-600">Sustainable backpack</p>
</div>
<span className="text-sm text-gray-500">1 week ago</span>
</div>
<div className="flex items-center py-3">
<div className="bg-purple-100 rounded-full p-2">
<UsersIcon className="h-5 w-5 text-purple-600" />
</div>
<div className="ml-4 flex-1">
<p className="text-sm font-medium text-gray-900">Joined community</p>
<p className="text-sm text-gray-600">Eco Warriors Group</p>
</div>
<span className="text-sm text-gray-500">2 weeks ago</span>
</div>
</div>
</div>
</div>
</main>
<Footer />
</div>
)
}