-
Notifications
You must be signed in to change notification settings - Fork 76
Closed
Labels
Stellar WaveIssues in the Stellar wave programIssues in the Stellar wave program
Description
🏷️ Context: Guest/Host Role System
We’re implementing a dual-role system where users can have two profiles:
- Guest (Tenant): Users who search and book properties
- Host: Users who list and manage properties
- Dual: Users who can be both at the same time
Role Flow:
-
All users start as Guest by default
-
To become a Host, they must complete the “Become a Host” flow
-
Dashboard access depends on role:
- Guest Dashboard: Always accessible (bookings, profile, wallet)
- Host Dashboard: Only if
hostStatus === 'verified'and they have properties
Architecture:
- Reuse 90% of the existing codebase (components, hooks, services)
- Add role logic on top of the current infrastructure
- Do not change existing dashboard components (they already work)
References:
- Existing auth system:
hooks/auth/use-auth.tsx - Current dashboards:
/tenant-dashboard(guest) and/dashboard/host-dashboard(host) - Reusable components:
components/dashboard/*
📌 Task: Create RoleGuard component to protect routes
Goal: Guard that protects routes based on the user’s role.
Files to create:
apps/web/src/components/guards/RoleGuard.tsx
Dependencies:
- ✅
useUserRole(Issue Implement User Login #2) - ✅
useAuth(already exists)
Implementation:
Note: The snippet below is a helper scaffold and should NOT be treated as the final implementation. Review redirect behavior, loading states, accessibility, and SSR concerns for Next.js.
// apps/web/src/components/guards/RoleGuard.tsx
'use client';
import { useUserRole } from '~/hooks/useUserRole';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import type { UserRole } from '~/types/roles';
interface RoleGuardProps {
children: React.ReactNode;
requiredRole: UserRole;
fallbackPath?: string;
}
export function RoleGuard({
children,
requiredRole,
fallbackPath = '/become-host',
}: RoleGuardProps) {
const { role, canAccessHostDashboard } = useUserRole();
const router = useRouter();
useEffect(() => {
if (requiredRole === 'host' && !canAccessHostDashboard) {
router.push(fallbackPath);
}
}, [requiredRole, canAccessHostDashboard, router, fallbackPath]);
if (requiredRole === 'host' && !canAccessHostDashboard) {
return (
<div className="flex flex-col items-center justify-center min-h-screen p-4">
<div className="text-center max-w-md">
<h2 className="text-2xl font-bold mb-4">Host Access Required</h2>
<p className="text-gray-600 mb-6">
You need to become a host to access this page.
</p>
<button
onClick={() => router.push('/become-host')}
className="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700"
>
Become a Host
</button>
</div>
</div>
);
}
return <>{children}</>;
}Acceptance Criteria:
- Component created at
components/guards/RoleGuard.tsx - Protects host routes correctly
- Shows message when access is denied
- Auto-redirects to
fallbackPath - No TypeScript errors
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Stellar WaveIssues in the Stellar wave programIssues in the Stellar wave program