feat: implement authentication flow with login page, middleware protection, and session-based role management
This commit is contained in:
240
src/app/page.tsx
240
src/app/page.tsx
@@ -1,80 +1,182 @@
|
||||
import Image from 'next/image';
|
||||
import StatCard from '@/components/StatCard';
|
||||
import BikeCard from '@/components/BikeCard';
|
||||
import TransactionList from '@/components/TransactionList';
|
||||
import { bikes, rentals, transactions, stats, users } from '@/data/mockData';
|
||||
import { Bike, Wallet, Footprints, Clock, Zap, RotateCcw, CreditCard, FileText, Share2 } from 'lucide-react';
|
||||
'use client';
|
||||
|
||||
export default function Home() {
|
||||
const activeRental = rentals.find(r => r.status === 'active');
|
||||
const currentBike = bikes.find(b => b.id === activeRental?.bikeId);
|
||||
const currentUser = users[0];
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { users } from '@/data/mockData';
|
||||
import { Zap, ArrowRight, Bike, Wallet } from 'lucide-react';
|
||||
|
||||
export default function LandingPage() {
|
||||
const router = useRouter();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleLogin = async (email: string) => {
|
||||
setLoading(true);
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
const user = users.find(u => u.email === email);
|
||||
if (user) {
|
||||
sessionStorage.setItem('authToken', 'demo-token');
|
||||
sessionStorage.setItem('userRole', user.role);
|
||||
sessionStorage.setItem('userName', user.name);
|
||||
|
||||
switch (user.role) {
|
||||
case 'admin':
|
||||
case 'manager':
|
||||
case 'staff':
|
||||
router.push('/admin');
|
||||
break;
|
||||
case 'accountant':
|
||||
router.push('/admin');
|
||||
break;
|
||||
case 'investor':
|
||||
router.push('/investor');
|
||||
break;
|
||||
case 'biker':
|
||||
router.push('/biker');
|
||||
break;
|
||||
case 'swap-station':
|
||||
router.push('/swapstation');
|
||||
break;
|
||||
case 'merchant':
|
||||
router.push('/merchant');
|
||||
break;
|
||||
default:
|
||||
router.push('/login');
|
||||
}
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-4 lg:p-6">
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-14 h-14 rounded-full bg-biker-light flex items-center justify-center text-2xl font-bold text-biker">
|
||||
{currentUser.name.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-xl lg:text-2xl font-extrabold text-slate-800">Welcome back, {currentUser.name.split(' ')[0]}!</h1>
|
||||
<p className="text-sm text-slate-500">Here's your rental status</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
||||
<StatCard label="Active Rental" value={stats.biker.activeRental} icon={Bike} color="text-biker" />
|
||||
<StatCard label="Wallet Balance" value={`৳${stats.biker.walletBalance}`} icon={Wallet} color="text-green-600" />
|
||||
<StatCard label="Total Rides" value={stats.biker.totalRides} icon={Footprints} color="text-purple-600" />
|
||||
<StatCard label="Days Remaining" value={stats.biker.daysRemaining} icon={Clock} color="text-amber-600" />
|
||||
</div>
|
||||
|
||||
{currentBike && (
|
||||
<div className="mb-6">
|
||||
<h2 className="text-lg font-bold text-slate-800 mb-3">Current Bike</h2>
|
||||
<BikeCard bike={currentBike} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid lg:grid-cols-2 gap-6 mb-6">
|
||||
<div>
|
||||
<h2 className="text-lg font-bold text-slate-800 mb-3">Quick Actions</h2>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button className="py-3 bg-accent text-white rounded-lg font-semibold hover:bg-accent-dark transition-colors flex items-center justify-center gap-2">
|
||||
<Zap className="w-4 h-4" /> Rent Bike
|
||||
</button>
|
||||
<button className="py-3 bg-biker text-white rounded-lg font-semibold hover:bg-biker-dark transition-colors flex items-center justify-center gap-2">
|
||||
<RotateCcw className="w-4 h-4" /> Extend Rental
|
||||
</button>
|
||||
<button className="py-3 bg-green-600 text-white rounded-lg font-semibold hover:bg-green-700 transition-colors flex items-center justify-center gap-2">
|
||||
<CreditCard className="w-4 h-4" /> Top Up
|
||||
</button>
|
||||
<button className="py-3 border-2 border-slate-200 text-slate-600 rounded-lg font-semibold hover:bg-slate-50 transition-colors flex items-center justify-center gap-2">
|
||||
<FileText className="w-4 h-4" /> End Rental
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-lg font-bold text-slate-800 mb-3">Recent Transactions</h2>
|
||||
<TransactionList transactions={transactions.filter(t => t.userId === 'u1')} compact />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-gradient-to-r from-accent to-accent-dark rounded-xl p-6 text-white">
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900">
|
||||
<header className="p-4 lg:p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm opacity-80">Refer a friend</p>
|
||||
<h3 className="text-xl font-bold mt-1">Earn ৳500 Credit</h3>
|
||||
<p className="text-xs opacity-80 mt-2">Share your referral link and earn free rides</p>
|
||||
<h1 className="text-2xl lg:text-3xl font-extrabold text-white">JAIBEN</h1>
|
||||
<p className="text-xs text-slate-400">Mobility Ltd</p>
|
||||
</div>
|
||||
<button className="px-4 py-2 bg-white text-accent rounded-lg font-semibold text-sm flex items-center gap-2">
|
||||
<Share2 className="w-4 h-4" /> Share Link
|
||||
<button
|
||||
onClick={() => router.push('/login')}
|
||||
className="px-4 py-2 bg-accent text-white rounded-lg font-semibold hover:bg-accent-dark transition-colors flex items-center gap-2"
|
||||
>
|
||||
Sign In <ArrowRight className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="p-4 lg:p-6">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="text-center mb-8 lg:mb-12">
|
||||
<div className="inline-flex items-center gap-2 px-4 py-1.5 bg-accent/20 rounded-full text-accent text-sm font-medium mb-4">
|
||||
<Zap className="w-4 h-4" /> Bangladesh's Leading EV Platform
|
||||
</div>
|
||||
<h2 className="text-3xl lg:text-5xl font-extrabold text-white mb-4 leading-tight">
|
||||
Electric Vehicle
|
||||
<br className="lg:hidden" /> Rental
|
||||
<span className="text-accent"> Made Simple</span>
|
||||
</h2>
|
||||
<p className="text-slate-400 text-lg lg:text-xl max-w-2xl mx-auto">
|
||||
Rent, Rent-to-Own, or Invest in EVs. Join Bangladesh's fastest growing
|
||||
electric mobility ecosystem with FOCO model for investors.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 mb-8">
|
||||
<button
|
||||
onClick={() => handleLogin('rahim@email.com')}
|
||||
disabled={loading}
|
||||
className="p-6 bg-slate-800/50 border border-slate-700 rounded-2xl hover:border-biker hover:bg-biker/10 transition-all group text-left"
|
||||
>
|
||||
<div className="w-12 h-12 bg-biker/20 rounded-xl flex items-center justify-center mb-4">
|
||||
<Bike className="w-6 h-6 text-biker" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-white mb-1">Biker</h3>
|
||||
<p className="text-slate-400 text-sm mb-3">Rent electric bikes for daily commute</p>
|
||||
<span className="text-biker text-sm font-medium flex items-center gap-1">
|
||||
Login as Biker <ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handleLogin('investor@email.com')}
|
||||
disabled={loading}
|
||||
className="p-6 bg-slate-800/50 border border-slate-700 rounded-2xl hover:border-green-500 hover:bg-green-500/10 transition-all group text-left"
|
||||
>
|
||||
<div className="w-12 h-12 bg-green-500/20 rounded-xl flex items-center justify-center mb-4">
|
||||
<Wallet className="w-6 h-6 text-green-500" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-white mb-1">Investor</h3>
|
||||
<p className="text-slate-400 text-sm mb-3">FOCO model with guaranteed returns</p>
|
||||
<span className="text-green-500 text-sm font-medium flex items-center gap-1">
|
||||
Login as Investor <ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handleLogin('swap@jaiben.com')}
|
||||
disabled={loading}
|
||||
className="p-6 bg-slate-800/50 border border-slate-700 rounded-2xl hover:border-purple-500 hover:bg-purple-500/10 transition-all group text-left"
|
||||
>
|
||||
<div className="w-12 h-12 bg-purple-500/20 rounded-xl flex items-center justify-center mb-4">
|
||||
<Zap className="w-6 h-6 text-purple-500" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-white mb-1">Swap Station</h3>
|
||||
<p className="text-slate-400 text-sm mb-3">Battery swap and charging services</p>
|
||||
<span className="text-purple-500 text-sm font-medium flex items-center gap-1">
|
||||
Login as Swap Station <ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
||||
<div className="text-center p-4">
|
||||
<div className="text-2xl lg:text-3xl font-bold text-accent mb-1">500+</div>
|
||||
<div className="text-slate-400 text-sm">Active Bikers</div>
|
||||
</div>
|
||||
<div className="text-center p-4">
|
||||
<div className="text-2xl lg:text-3xl font-bold text-accent mb-1">200+</div>
|
||||
<div className="text-slate-400 text-sm">EV Fleet</div>
|
||||
</div>
|
||||
<div className="text-center p-4">
|
||||
<div className="text-2xl lg:text-3xl font-bold text-accent mb-1">50+</div>
|
||||
<div className="text-slate-400 text-sm">Investors</div>
|
||||
</div>
|
||||
<div className="text-center p-4">
|
||||
<div className="text-2xl lg:text-3xl font-bold text-accent mb-1">18%</div>
|
||||
<div className="text-slate-400 text-sm">Avg. ROI</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-gradient-to-r from-accent to-accent-dark rounded-2xl p-6 lg:p-8 text-white">
|
||||
<div className="grid lg:grid-cols-2 gap-6 items-center">
|
||||
<div>
|
||||
<h3 className="text-xl lg:text-2xl font-bold mb-2">Ready to join the EV revolution?</h3>
|
||||
<p className="text-white/80 mb-4">Start renting or investing today and be part of Bangladesh's sustainable future.</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<button
|
||||
onClick={() => router.push('/login')}
|
||||
className="w-full py-3 bg-white text-accent rounded-lg font-semibold hover:bg-slate-100 transition-colors"
|
||||
>
|
||||
Get Started
|
||||
</button>
|
||||
<button
|
||||
onClick={() => router.push('/login')}
|
||||
className="w-full py-3 border-2 border-white text-white rounded-lg font-semibold hover:bg-white/10 transition-colors"
|
||||
>
|
||||
Learn More
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer className="p-4 lg:p-6 text-center">
|
||||
<p className="text-slate-500 text-sm">
|
||||
© 2024 JAIBEN Mobility Ltd. All rights reserved.
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user