Skip to content

Commit 6c85b52

Browse files
committed
Made CRM working
1 parent d2877c3 commit 6c85b52

4 files changed

Lines changed: 296 additions & 86 deletions

File tree

src/App.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ import Architects from "./pages/categories/Architects";
2525
import Contractors from "./pages/categories/Contractors";
2626
import CategoriesLayout from "./pages/categories/CategoriesLayout";
2727
import ArchitectDetail from "./pages/categories/ArchitectDetail";
28-
28+
import ProtectedRoute from "./components/ProtectedRoute";
29+
import ArchitectDashboard from "./pages/ArchitectDashboard.tsx";
2930

3031
// Import i18n configuration
3132
import './i18n';
@@ -44,6 +45,7 @@ const AppRoutes = () => {
4445
<Route path="/about" element={<AboutUs />} />
4546
<Route path="/contact" element={<ContactUs />} />
4647
<Route path="/profile" element={<Profile />} />
48+
<Route path="/architectDashboard" element={<ProtectedRoute requiredRole="architect"><ArchitectDashboard /></ProtectedRoute>} />
4749
<Route path="/categories" element={<CategoriesLayout />}>
4850
<Route path="workers" element={<Workers />} />
4951
<Route path="suppliers" element={<Suppliers />} />

src/components/Navbar.tsx

Lines changed: 115 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState, useEffect } from 'react';
2-
import { Menu, X, User, Search } from 'lucide-react';
2+
import { Menu, X, User, Search, LayoutDashboard } from 'lucide-react'; // ⚡ added LayoutDashboard icon
33
import { Button } from "@/components/ui/button";
44
import { Input } from "@/components/ui/input";
55
import { Link, NavLink } from 'react-router-dom';
@@ -111,6 +111,19 @@ const Navbar: React.FC = () => {
111111

112112
<div className="hidden md:flex items-center space-x-2">
113113
<LanguageSelector />
114+
115+
{/* ⚡ Architect Dashboard button added here */}
116+
{user && (
117+
<Button
118+
variant="outline"
119+
className="flex items-center space-x-2 border-primary text-primary hover:bg-primary hover:text-white"
120+
onClick={() => navigate('/architectDashboard')}
121+
>
122+
<LayoutDashboard className="h-4 w-4" />
123+
<span>Dashboard</span>
124+
</Button>
125+
)}
126+
114127
{user ? (
115128
<UserProfileMenu />
116129
) : (
@@ -142,98 +155,115 @@ const Navbar: React.FC = () => {
142155
</div>
143156

144157
{/* Mobile Menu */}
145-
{isOpen && (
146-
<div className="bg-white md:hidden pt-4 pb-4 animate-fade-in">
147-
<div className="flex flex-col space-y-4">
148-
<div className="relative">
149-
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
150-
<Input
151-
type="search"
152-
placeholder={t('common.search')}
153-
className="pl-8"
154-
onKeyDown={(e) => {
155-
if (e.key === 'Enter') {
156-
handleSearchClick();
157-
setIsOpen(false);
158-
}
159-
}}
160-
/>
161-
</div>
158+
{isOpen && (
159+
<div className="bg-white md:hidden pt-4 pb-4 animate-fade-in">
160+
<div className="flex flex-col space-y-4">
161+
<div className="relative">
162+
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
163+
<Input
164+
type="search"
165+
placeholder={t('common.search')}
166+
className="pl-8"
167+
onKeyDown={(e) => {
168+
if (e.key === 'Enter') {
169+
handleSearchClick();
170+
setIsOpen(false);
171+
}
172+
}}
173+
/>
174+
</div>
162175

163-
<Link to="/" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>Home</Link>
176+
<Link to="/" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>Home</Link>
164177

165-
{/* Services main link (redirect only) */}
166-
<Link to="/services" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>Services</Link>
178+
{/* Services main link (redirect only) */}
179+
<Link to="/services" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>Services</Link>
167180

168-
{/* New "All Services" mobile button */}
169-
<button
170-
className="w-full text-left px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors flex justify-between items-center"
171-
onClick={() => setIsMobileServicesOpen(!isMobileServicesOpen)}
172-
>
173-
{t('common.solutions')}
174-
<span className={`transform transition-transform duration-200 ${isMobileServicesOpen ? 'rotate-180' : 'rotate-0'}`}></span>
175-
</button>
176-
177-
{isMobileServicesOpen && (
178-
<div className="pl-4 mt-2 space-y-1">
179-
<Link to="/categories/workers" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Worker</Link>
180-
{/* <Link to="/categories/houseowners" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Home Owners</Link> */}
181-
<Link to="/categories/architects" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Architects/Designers</Link>
182-
<Link to="/categories/contractors" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Contractors</Link>
183-
<Link to="/categories/developers" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Developers</Link>
184-
<Link to="/categories/suppliers" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Material Suppliers</Link>
185-
</div>
186-
)}
181+
{/* New "All Services" mobile button */}
182+
<button
183+
className="w-full text-left px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors flex justify-between items-center"
184+
onClick={() => setIsMobileServicesOpen(!isMobileServicesOpen)}
185+
>
186+
{t('common.solutions')}
187+
<span className={`transform transition-transform duration-200 ${isMobileServicesOpen ? 'rotate-180' : 'rotate-0'}`}></span>
188+
</button>
187189

188-
<Link to="/blog" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>Blog</Link>
189-
<Link to="/about" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>About</Link>
190-
<Link to="/contact" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>Contact</Link>
191-
192-
<div className="pt-2 space-y-2">
193-
194-
{/* Profile Button added above sign out */}
195-
{user && (
196-
<Button
197-
variant="outline"
198-
className="w-full flex items-center justify-center space-x-2"
199-
onClick={() => {
200-
setIsOpen(false);
201-
navigate('/profile'); // Navigate to profile route using react-router-dom
202-
}}
203-
>
204-
<User className="h-5 w-5" />
205-
<span>{t('common.profile')}</span>
206-
</Button>
207-
)}
208-
209-
{user ? (
210-
<UserProfileMenu />
211-
) : (
212-
<>
213-
<Button
214-
variant="outline"
215-
className="w-full animate-pulse-shadow"
216-
asChild
217-
onClick={() => setIsOpen(false)}
218-
>
219-
<Link to="/auth/login">{t('common.signIn')}</Link>
220-
</Button>
221-
<Button
222-
className="w-full animate-pulse-shadow"
223-
asChild
224-
onClick={() => setIsOpen(false)}
225-
>
226-
<Link to="/auth/register">{t('common.joinNow')}</Link>
227-
</Button>
228-
</>
229-
)}
230-
</div>
231-
</div>
232-
</div>
190+
{isMobileServicesOpen && (
191+
<div className="pl-4 mt-2 space-y-1">
192+
<Link to="/categories/workers" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Worker</Link>
193+
{/* <Link to="/categories/houseowners" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Home Owners</Link> */}
194+
<Link to="/categories/architects" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Architects/Designers</Link>
195+
<Link to="/categories/contractors" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Contractors</Link>
196+
<Link to="/categories/developers" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Developers</Link>
197+
<Link to="/categories/suppliers" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md" onClick={() => setIsOpen(false)}>Material Suppliers</Link>
198+
</div>
199+
)}
200+
201+
<Link to="/blog" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>Blog</Link>
202+
<Link to="/about" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>About</Link>
203+
<Link to="/contact" className="block px-3 py-2 rounded-md text-base font-medium text-foreground hover:bg-muted hover:text-primary transition-colors" onClick={() => setIsOpen(false)}>Contact</Link>
204+
205+
<div className="pt-2 space-y-2">
206+
207+
{/* Profile Button added above sign out */}
208+
{user && (
209+
<Button
210+
variant="outline"
211+
className="w-full flex items-center justify-center space-x-2"
212+
onClick={() => {
213+
setIsOpen(false);
214+
navigate('/profile'); // Navigate to profile route using react-router-dom
215+
}}
216+
>
217+
<User className="h-5 w-5" />
218+
<span>{t('common.profile')}</span>
219+
</Button>
220+
)}
221+
222+
{/* 🔹 Architect Dashboard Button (added, do not remove) */}
223+
{user && (
224+
<Button
225+
variant="outline"
226+
className="w-full flex items-center justify-center space-x-2"
227+
onClick={() => {
228+
setIsOpen(false);
229+
navigate('/architectDashboard');
230+
}}
231+
>
232+
<span>Architect Dashboard</span>
233+
</Button>
234+
)}
235+
236+
{user ? (
237+
<UserProfileMenu />
238+
) : (
239+
<>
240+
<Button
241+
variant="outline"
242+
className="w-full animate-pulse-shadow"
243+
asChild
244+
onClick={() => setIsOpen(false)}
245+
>
246+
<Link to="/auth/login">{t('common.signIn')}</Link>
247+
</Button>
248+
<Button
249+
className="w-full animate-pulse-shadow"
250+
asChild
251+
onClick={() => setIsOpen(false)}
252+
>
253+
<Link to="/auth/register">{t('common.joinNow')}</Link>
254+
</Button>
255+
</>
233256
)}
234257
</div>
258+
</div>
259+
</div>
260+
)}
261+
262+
</div>
235263
</nav>
236264
);
237265
};
238266

239267
export default Navbar;
268+
269+

src/components/ProtectedRoute.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React, { ReactNode } from "react";
2+
import { Navigate } from "react-router-dom";
3+
import { useAuth } from "@/contexts/AuthContext";
4+
5+
interface ProtectedRouteProps {
6+
children: ReactNode;
7+
requiredRole?: string;
8+
}
9+
10+
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children, requiredRole }) => {
11+
const { user, userRole, loading } = useAuth();
12+
13+
if (loading) {
14+
return <p className="p-6 text-lg">Checking authentication...</p>;
15+
}
16+
17+
// If user is not logged in
18+
if (!user) {
19+
return <Navigate to="/auth/login" replace />;
20+
}
21+
22+
// If user role doesn't match required role
23+
if (requiredRole && userRole !== requiredRole) {
24+
return <Navigate to="/" replace />;
25+
}
26+
27+
return <>{children}</>;
28+
};
29+
30+
export default ProtectedRoute;

0 commit comments

Comments
 (0)