default layuout

This commit is contained in:
pradeepkumar
2026-01-11 21:30:57 +05:30
parent c8d414ccd6
commit 500c8b6e5d
6 changed files with 581 additions and 80 deletions

View File

@@ -0,0 +1,147 @@
'use client';
import { useSession } from 'next-auth/react';
export default function AgentDashboard() {
const { data: session } = useSession();
return (
<div className="space-y-6">
{/* Welcome Section */}
<div className="bg-white rounded-[20px] shadow-lg p-8">
<h1 className="text-3xl font-bold text-[#00293d] mb-2">
Welcome back, {session?.user?.name?.split(' ')[0] || 'Agent'}!
</h1>
<p className="text-[#00293d]/70">
Here's an overview of your real estate business today.
</p>
</div>
{/* Stats Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div className="bg-white rounded-[20px] shadow-lg p-6">
<div className="flex items-center justify-between mb-4">
<div className="w-12 h-12 bg-[#00293d] rounded-full flex items-center justify-center">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
</div>
</div>
<p className="text-2xl font-bold text-[#00293d]">12</p>
<p className="text-sm text-[#00293d]/70">Active Listings</p>
</div>
<div className="bg-white rounded-[20px] shadow-lg p-6">
<div className="flex items-center justify-between mb-4">
<div className="w-12 h-12 bg-[#e58625] rounded-full flex items-center justify-center">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
</div>
</div>
<p className="text-2xl font-bold text-[#00293d]">48</p>
<p className="text-sm text-[#00293d]/70">Total Clients</p>
</div>
<div className="bg-white rounded-[20px] shadow-lg p-6">
<div className="flex items-center justify-between mb-4">
<div className="w-12 h-12 bg-[#5ba4a4] rounded-full flex items-center justify-center">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</div>
</div>
<p className="text-2xl font-bold text-[#00293d]">5</p>
<p className="text-sm text-[#00293d]/70">Upcoming Appointments</p>
</div>
<div className="bg-white rounded-[20px] shadow-lg p-6">
<div className="flex items-center justify-between mb-4">
<div className="w-12 h-12 bg-[#00293d] rounded-full flex items-center justify-center">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
</div>
</div>
<p className="text-2xl font-bold text-[#00293d]">8</p>
<p className="text-sm text-[#00293d]/70">Unread Messages</p>
</div>
</div>
{/* Quick Actions */}
<div className="bg-white rounded-[20px] shadow-lg p-8">
<h2 className="text-xl font-bold text-[#00293d] mb-6">Quick Actions</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<button className="flex items-center gap-3 p-4 bg-[#f0f5fc] rounded-lg hover:bg-[#e0e8f5] transition-colors">
<div className="w-10 h-10 bg-[#00293d] rounded-full flex items-center justify-center">
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
</svg>
</div>
<span className="font-medium text-[#00293d]">Add New Property</span>
</button>
<button className="flex items-center gap-3 p-4 bg-[#f0f5fc] rounded-lg hover:bg-[#e0e8f5] transition-colors">
<div className="w-10 h-10 bg-[#e58625] rounded-full flex items-center justify-center">
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z" />
</svg>
</div>
<span className="font-medium text-[#00293d]">Add New Client</span>
</button>
<button className="flex items-center gap-3 p-4 bg-[#f0f5fc] rounded-lg hover:bg-[#e0e8f5] transition-colors">
<div className="w-10 h-10 bg-[#5ba4a4] rounded-full flex items-center justify-center">
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<span className="font-medium text-[#00293d]">Schedule Appointment</span>
</button>
</div>
</div>
{/* Recent Activity */}
<div className="bg-white rounded-[20px] shadow-lg p-8">
<h2 className="text-xl font-bold text-[#00293d] mb-6">Recent Activity</h2>
<div className="space-y-4">
<div className="flex items-center gap-4 p-4 bg-[#f0f5fc] rounded-lg">
<div className="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center">
<svg className="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div className="flex-1">
<p className="font-medium text-[#00293d]">New inquiry for 123 Main Street</p>
<p className="text-sm text-[#00293d]/70">2 hours ago</p>
</div>
</div>
<div className="flex items-center gap-4 p-4 bg-[#f0f5fc] rounded-lg">
<div className="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center">
<svg className="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</div>
<div className="flex-1">
<p className="font-medium text-[#00293d]">Appointment scheduled with John Doe</p>
<p className="text-sm text-[#00293d]/70">5 hours ago</p>
</div>
</div>
<div className="flex items-center gap-4 p-4 bg-[#f0f5fc] rounded-lg">
<div className="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
<svg className="w-5 h-5 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</div>
<div className="flex-1">
<p className="font-medium text-[#00293d]">Property price updated: 456 Oak Avenue</p>
<p className="text-sm text-[#00293d]/70">Yesterday</p>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,7 +1,139 @@
'use client';
import { useSession, signOut } from 'next-auth/react';
import { useRouter, usePathname } from 'next/navigation';
import { useEffect } from 'react';
import Link from 'next/link';
const agentNavItems = [
{ href: '/agent/dashboard', label: 'Dashboard', icon: 'home' },
{ href: '/agent/properties', label: 'My Properties', icon: 'building' },
{ href: '/agent/clients', label: 'Clients', icon: 'users' },
{ href: '/agent/appointments', label: 'Appointments', icon: 'calendar' },
{ href: '/agent/messages', label: 'Messages', icon: 'message' },
{ href: '/agent/settings', label: 'Settings', icon: 'settings' },
];
const icons: Record<string, JSX.Element> = {
home: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
),
building: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
),
users: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
),
calendar: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
),
message: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
),
settings: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
),
};
export default function AgentLayout({ export default function AgentLayout({
children, children,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return <>{children}</>; const { data: session, status } = useSession();
const router = useRouter();
const pathname = usePathname();
useEffect(() => {
if (status === 'loading') return;
if (!session) {
router.replace('/login');
return;
}
// Redirect non-agents to user dashboard
const userRole = (session.user as any)?.role;
if (userRole !== 'AGENT') {
router.replace('/user/dashboard');
}
}, [session, status, router]);
if (status === 'loading' || !session) {
return (
<div className="min-h-screen bg-gradient-to-b from-[#c4d9d4] to-[#f0f5fc] flex items-center justify-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#00293d]"></div>
</div>
);
}
return (
<div className="min-h-screen bg-gradient-to-b from-[#c4d9d4] to-[#f0f5fc]">
{/* Header */}
<header className="bg-white/80 backdrop-blur-sm shadow-sm fixed top-0 left-0 right-0 z-50">
<div className="px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<Link href="/agent/dashboard">
<img src="/assets/logo.svg" alt="RE-QuestN" className="h-8" />
</Link>
<div className="flex items-center gap-4">
<span className="text-sm text-[#00293d]">
{session?.user?.name || session?.user?.email}
</span>
<span className="px-2 py-1 bg-[#e58625]/10 text-[#e58625] text-xs font-medium rounded">
Agent
</span>
<button
onClick={() => signOut({ callbackUrl: '/login' })}
className="px-4 py-2 bg-[#e58625] hover:bg-[#d47a1f] text-white text-sm font-medium rounded-lg transition-colors"
>
Sign Out
</button>
</div>
</div>
</div>
</header>
<div className="flex pt-16">
{/* Sidebar */}
<aside className="w-64 bg-white/80 backdrop-blur-sm shadow-sm min-h-[calc(100vh-4rem)] fixed left-0 top-16">
<nav className="p-4 space-y-1">
{agentNavItems.map((item) => {
const isActive = pathname === item.href;
return (
<Link
key={item.href}
href={item.href}
className={`flex items-center gap-3 px-4 py-3 rounded-lg transition-colors ${
isActive
? 'bg-[#00293d] text-white'
: 'text-[#00293d] hover:bg-[#f0f5fc]'
}`}
>
{icons[item.icon]}
<span className="font-medium">{item.label}</span>
</Link>
);
})}
</nav>
</aside>
{/* Main Content */}
<main className="flex-1 ml-64 p-6">{children}</main>
</div>
</div>
);
} }

View File

@@ -1,7 +1,136 @@
'use client';
import { useSession, signOut } from 'next-auth/react';
import { useRouter, usePathname } from 'next/navigation';
import { useEffect } from 'react';
import Link from 'next/link';
const userNavItems = [
{ href: '/user/dashboard', label: 'Dashboard', icon: 'home' },
{ href: '/user/properties', label: 'Browse Properties', icon: 'building' },
{ href: '/user/favorites', label: 'Favorites', icon: 'heart' },
{ href: '/user/inquiries', label: 'My Inquiries', icon: 'message' },
{ href: '/user/appointments', label: 'Appointments', icon: 'calendar' },
{ href: '/user/settings', label: 'Settings', icon: 'settings' },
];
const icons: Record<string, JSX.Element> = {
home: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
),
building: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
),
heart: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
</svg>
),
message: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
),
calendar: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
),
settings: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
),
};
export default function UserLayout({ export default function UserLayout({
children, children,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return <>{children}</>; const { data: session, status } = useSession();
const router = useRouter();
const pathname = usePathname();
useEffect(() => {
if (status === 'loading') return;
if (!session) {
router.replace('/login');
return;
}
// Redirect agents to agent dashboard
const userRole = (session.user as any)?.role;
if (userRole === 'AGENT') {
router.replace('/agent/dashboard');
}
}, [session, status, router]);
if (status === 'loading' || !session) {
return (
<div className="min-h-screen bg-gradient-to-b from-[#c4d9d4] to-[#f0f5fc] flex items-center justify-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#00293d]"></div>
</div>
);
}
return (
<div className="min-h-screen bg-gradient-to-b from-[#c4d9d4] to-[#f0f5fc]">
{/* Header */}
<header className="bg-white/80 backdrop-blur-sm shadow-sm fixed top-0 left-0 right-0 z-50">
<div className="px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<Link href="/user/dashboard">
<img src="/assets/logo.svg" alt="RE-QuestN" className="h-8" />
</Link>
<div className="flex items-center gap-4">
<span className="text-sm text-[#00293d]">
{session?.user?.name || session?.user?.email}
</span>
<button
onClick={() => signOut({ callbackUrl: '/login' })}
className="px-4 py-2 bg-[#e58625] hover:bg-[#d47a1f] text-white text-sm font-medium rounded-lg transition-colors"
>
Sign Out
</button>
</div>
</div>
</div>
</header>
<div className="flex pt-16">
{/* Sidebar */}
<aside className="w-64 bg-white/80 backdrop-blur-sm shadow-sm min-h-[calc(100vh-4rem)] fixed left-0 top-16">
<nav className="p-4 space-y-1">
{userNavItems.map((item) => {
const isActive = pathname === item.href;
return (
<Link
key={item.href}
href={item.href}
className={`flex items-center gap-3 px-4 py-3 rounded-lg transition-colors ${
isActive
? 'bg-[#00293d] text-white'
: 'text-[#00293d] hover:bg-[#f0f5fc]'
}`}
>
{icons[item.icon]}
<span className="font-medium">{item.label}</span>
</Link>
);
})}
</nav>
</aside>
{/* Main Content */}
<main className="flex-1 ml-64 p-6">{children}</main>
</div>
</div>
);
} }

View File

@@ -0,0 +1,115 @@
'use client';
import { useSession } from 'next-auth/react';
export default function UserDashboard() {
const { data: session } = useSession();
return (
<div className="space-y-6">
{/* Welcome Section */}
<div className="bg-white rounded-[20px] shadow-lg p-8">
<h1 className="text-3xl font-bold text-[#00293d] mb-2">
Welcome, {session?.user?.name?.split(' ')[0] || 'User'}!
</h1>
<p className="text-[#00293d]/70">
Your real estate journey starts here. Explore properties, connect with agents, and find your dream home.
</p>
</div>
{/* Quick Actions */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="bg-white rounded-[20px] shadow-lg p-6 hover:shadow-xl transition-shadow cursor-pointer">
<div className="w-12 h-12 bg-[#00293d] rounded-full flex items-center justify-center mb-4">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</div>
<h3 className="text-lg font-semibold text-[#00293d] mb-2">Search Properties</h3>
<p className="text-sm text-[#00293d]/70">Find your perfect home from thousands of listings</p>
</div>
<div className="bg-white rounded-[20px] shadow-lg p-6 hover:shadow-xl transition-shadow cursor-pointer">
<div className="w-12 h-12 bg-[#e58625] rounded-full flex items-center justify-center mb-4">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
</div>
<h3 className="text-lg font-semibold text-[#00293d] mb-2">Find Agents</h3>
<p className="text-sm text-[#00293d]/70">Connect with top real estate professionals</p>
</div>
<div className="bg-white rounded-[20px] shadow-lg p-6 hover:shadow-xl transition-shadow cursor-pointer">
<div className="w-12 h-12 bg-[#5ba4a4] rounded-full flex items-center justify-center mb-4">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
</svg>
</div>
<h3 className="text-lg font-semibold text-[#00293d] mb-2">Saved Favorites</h3>
<p className="text-sm text-[#00293d]/70">View your saved properties and searches</p>
</div>
</div>
{/* Stats */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<div className="bg-white rounded-[20px] shadow-lg p-6">
<p className="text-3xl font-bold text-[#00293d]">0</p>
<p className="text-sm text-[#00293d]/70">Saved Properties</p>
</div>
<div className="bg-white rounded-[20px] shadow-lg p-6">
<p className="text-3xl font-bold text-[#00293d]">0</p>
<p className="text-sm text-[#00293d]/70">Active Inquiries</p>
</div>
<div className="bg-white rounded-[20px] shadow-lg p-6">
<p className="text-3xl font-bold text-[#00293d]">0</p>
<p className="text-sm text-[#00293d]/70">Scheduled Tours</p>
</div>
<div className="bg-white rounded-[20px] shadow-lg p-6">
<p className="text-3xl font-bold text-[#00293d]">0</p>
<p className="text-sm text-[#00293d]/70">Messages</p>
</div>
</div>
{/* Featured Properties */}
<div className="bg-white rounded-[20px] shadow-lg p-8">
<div className="flex items-center justify-between mb-6">
<h2 className="text-xl font-bold text-[#00293d]">Featured Properties</h2>
<button className="text-[#e58625] hover:text-[#d47a1f] font-medium text-sm">
View All
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{/* Property Card Placeholder */}
<div className="bg-[#f0f5fc] rounded-[20px] p-6 text-center">
<div className="w-16 h-16 bg-[#00293d]/10 rounded-full flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-[#00293d]/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
</div>
<p className="text-[#00293d]/70 text-sm">No featured properties yet</p>
<button className="mt-4 text-[#e58625] hover:text-[#d47a1f] font-medium text-sm">
Browse Properties
</button>
</div>
</div>
</div>
{/* Recent Activity */}
<div className="bg-white rounded-[20px] shadow-lg p-8">
<h2 className="text-xl font-bold text-[#00293d] mb-6">Recent Activity</h2>
<div className="text-center py-8">
<div className="w-16 h-16 bg-[#f0f5fc] rounded-full flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-[#00293d]/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<p className="text-[#00293d]/70">No recent activity</p>
<p className="text-sm text-[#00293d]/50 mt-2">
Start exploring properties to see your activity here
</p>
</div>
</div>
</div>
);
}

View File

@@ -1,86 +1,43 @@
'use client'; 'use client';
import { useSession, signOut } from 'next-auth/react'; import { useSession } from 'next-auth/react';
import Link from 'next/link'; import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
export default function Home() { export default function Home() {
const { data: session } = useSession(); const { data: session, status } = useSession();
const router = useRouter();
useEffect(() => {
if (status === 'loading') return;
if (!session) {
router.replace('/login');
return;
}
// Redirect based on user role
const userRole = (session.user as any)?.role;
if (userRole === 'AGENT') {
router.replace('/agent/dashboard');
} else {
router.replace('/user/dashboard');
}
}, [session, status, router]);
// Loading state while determining redirect
return ( return (
<div className="min-h-screen bg-gradient-to-b from-[#c4d9d4] to-[#f0f5fc]"> <div className="min-h-screen bg-gradient-to-b from-[#c4d9d4] to-[#f0f5fc] flex items-center justify-center">
{/* Header */} <div className="text-center">
<header className="bg-white/80 backdrop-blur-sm shadow-sm"> <img
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> src="/assets/logo.svg"
<div className="flex justify-between items-center h-16"> alt="RE-QuestN"
{/* Logo */} className="h-10 mx-auto mb-4"
<Link href="/"> />
<img <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#00293d] mx-auto"></div>
src="/assets/logo.svg" <p className="mt-4 text-[#00293d]/70">Loading...</p>
alt="RE-QuestN" </div>
className="h-8"
/>
</Link>
{/* User Menu */}
<div className="flex items-center gap-4">
<span className="text-sm text-[#00293d]">
Welcome, {session?.user?.name || session?.user?.email || 'User'}
</span>
<button
onClick={() => signOut({ callbackUrl: '/login' })}
className="px-4 py-2 bg-[#e58625] hover:bg-[#d47a1f] text-white text-sm font-medium rounded-lg transition-colors"
>
Sign Out
</button>
</div>
</div>
</div>
</header>
{/* Main Content */}
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="bg-white rounded-[20px] shadow-lg p-8">
<h1 className="text-3xl font-bold text-[#00293d] mb-4">
Welcome to RE-QuestN
</h1>
<p className="text-[#00293d]/70 mb-8">
Your real estate journey starts here. Explore properties, connect with agents, and find your dream home.
</p>
{/* Quick Actions */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="bg-[#f0f5fc] rounded-[20px] p-6 hover:shadow-md transition-shadow">
<div className="w-12 h-12 bg-[#00293d] rounded-full flex items-center justify-center mb-4">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
</div>
<h3 className="text-lg font-semibold text-[#00293d] mb-2">Browse Properties</h3>
<p className="text-sm text-[#00293d]/70">Explore thousands of listings in your area</p>
</div>
<div className="bg-[#f0f5fc] rounded-[20px] p-6 hover:shadow-md transition-shadow">
<div className="w-12 h-12 bg-[#e58625] rounded-full flex items-center justify-center mb-4">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
</div>
<h3 className="text-lg font-semibold text-[#00293d] mb-2">Find Agents</h3>
<p className="text-sm text-[#00293d]/70">Connect with top real estate professionals</p>
</div>
<div className="bg-[#f0f5fc] rounded-[20px] p-6 hover:shadow-md transition-shadow">
<div className="w-12 h-12 bg-[#5ba4a4] rounded-full flex items-center justify-center mb-4">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
</svg>
</div>
<h3 className="text-lg font-semibold text-[#00293d] mb-2">Saved Favorites</h3>
<p className="text-sm text-[#00293d]/70">View your saved properties and searches</p>
</div>
</div>
</div>
</main>
</div> </div>
); );
} }

View File

@@ -7,11 +7,15 @@ const publicRoutes = ["/login", "/signup", "/forgot-password", "/reset-password"
export default auth((req) => { export default auth((req) => {
const { nextUrl } = req; const { nextUrl } = req;
const isLoggedIn = !!req.auth; const isLoggedIn = !!req.auth;
const userRole = (req.auth?.user as any)?.role;
const isPublicRoute = publicRoutes.some( const isPublicRoute = publicRoutes.some(
(route) => nextUrl.pathname === route || nextUrl.pathname.startsWith(route + "/") (route) => nextUrl.pathname === route || nextUrl.pathname.startsWith(route + "/")
); );
const isAgentRoute = nextUrl.pathname.startsWith("/agent");
const isUserRoute = nextUrl.pathname.startsWith("/user");
const isApiRoute = nextUrl.pathname.startsWith("/api"); const isApiRoute = nextUrl.pathname.startsWith("/api");
const isStaticRoute = nextUrl.pathname.startsWith("/_next") || const isStaticRoute = nextUrl.pathname.startsWith("/_next") ||
nextUrl.pathname.startsWith("/assets") || nextUrl.pathname.startsWith("/assets") ||
@@ -24,7 +28,11 @@ export default auth((req) => {
// Redirect logged-in users away from public routes (login, signup) // Redirect logged-in users away from public routes (login, signup)
if (isLoggedIn && isPublicRoute) { if (isLoggedIn && isPublicRoute) {
return NextResponse.redirect(new URL("/", nextUrl.origin)); // Redirect to appropriate dashboard based on role
if (userRole === "AGENT") {
return NextResponse.redirect(new URL("/agent/dashboard", nextUrl.origin));
}
return NextResponse.redirect(new URL("/user/dashboard", nextUrl.origin));
} }
// Redirect non-logged-in users to login page for protected routes // Redirect non-logged-in users to login page for protected routes
@@ -34,6 +42,19 @@ export default auth((req) => {
return NextResponse.redirect(loginUrl); return NextResponse.redirect(loginUrl);
} }
// Role-based route protection
if (isLoggedIn) {
// Prevent regular users from accessing agent routes
if (isAgentRoute && userRole !== "AGENT") {
return NextResponse.redirect(new URL("/user/dashboard", nextUrl.origin));
}
// Prevent agents from accessing user routes
if (isUserRoute && userRole === "AGENT") {
return NextResponse.redirect(new URL("/agent/dashboard", nextUrl.origin));
}
}
return NextResponse.next(); return NextResponse.next();
}); });