Skip to content

Commit 910ff96

Browse files
committed
added feature profile page on navbar
1 parent 4ae0ef6 commit 910ff96

3 files changed

Lines changed: 217 additions & 45 deletions

File tree

src/Routes/Router.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import ContributorProfile from "../pages/ContributorProfile/ContributorProfile.t
99
import Home from "../pages/Home/Home.tsx";
1010
import Activity from "../pages/Activity.tsx";
1111
import PrivacyPolicy from "../pages/Privacy/PrivacyPolicy.tsx"; // ✅ Updated import path to match your new folder structure
12+
import Profile from "../pages/Profile/Profile.tsx";
1213

1314
const Router = () => {
1415
return (
@@ -21,6 +22,7 @@ const Router = () => {
2122
<Route path="/contact" element={<Contact />} />
2223
<Route path="/contributors" element={<Contributors />} />
2324
<Route path="/contributor/:username" element={<ContributorProfile />} />
25+
<Route path="/profile" element={<Profile />} />
2426
<Route path="/activity" element={<Activity />} />
2527

2628
{/* Privacy Policy page route */}

src/components/Navbar.tsx

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NavLink, Link } from "react-router-dom";
22
import { useState, useContext } from "react";
33
import { ThemeContext } from "../context/ThemeContext";
4-
import { Moon, Sun, Menu, X, Github } from "lucide-react";
4+
import { Moon, Sun, Menu, X, User } from "lucide-react";
55

66
const Navbar: React.FC = () => {
77
const [isOpen, setIsOpen] = useState(false);
@@ -24,40 +24,30 @@ const Navbar: React.FC = () => {
2424
return (
2525
<nav className="sticky top-0 z-50 bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800 transition-colors duration-300 backdrop-blur">
2626
<div className="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
27-
28-
{/* Logo */}
2927
<Link
3028
to="/"
3129
className="flex items-center gap-3 text-xl font-bold text-slate-900 dark:text-white"
3230
>
33-
<img
34-
src="/crl-icon.png"
35-
alt="CRL Icon"
36-
className="h-8 w-8 object-contain"
37-
/>
38-
31+
<img src="/crl-icon.png" alt="CRL Icon" className="h-8 w-8 object-contain" />
3932
<span>GitHub Tracker</span>
4033
</Link>
4134

42-
{/* Desktop Navigation */}
4335
<div className="hidden md:flex items-center gap-3">
4436
<NavLink to="/" className={navLinkStyles}>
4537
Home
4638
</NavLink>
47-
4839
<NavLink to="/track" className={navLinkStyles}>
4940
Tracker
5041
</NavLink>
51-
5242
<NavLink to="/contributors" className={navLinkStyles}>
5343
Contributors
5444
</NavLink>
55-
45+
<NavLink to="/profile" className={navLinkStyles}>
46+
Profile
47+
</NavLink>
5648
<NavLink to="/login" className={navLinkStyles}>
5749
Login
5850
</NavLink>
59-
60-
{/* Theme Toggle */}
6151
<button
6252
onClick={toggleTheme}
6353
className="ml-2 p-2 rounded-xl border border-gray-300 dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
@@ -71,10 +61,7 @@ const Navbar: React.FC = () => {
7161
</button>
7262
</div>
7363

74-
{/* Mobile Controls */}
7564
<div className="md:hidden flex items-center gap-2">
76-
77-
{/* Theme Toggle */}
7865
<button
7966
onClick={toggleTheme}
8067
className="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
@@ -86,8 +73,6 @@ const Navbar: React.FC = () => {
8673
<Moon className="h-5 w-5 text-white" />
8774
)}
8875
</button>
89-
90-
{/* Menu Toggle */}
9176
<button
9277
onClick={() => setIsOpen(!isOpen)}
9378
className="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
@@ -102,40 +87,22 @@ const Navbar: React.FC = () => {
10287
</div>
10388
</div>
10489

105-
{/* Mobile Menu */}
10690
{isOpen && (
10791
<div className="md:hidden border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900">
10892
<div className="px-6 py-5 flex flex-col gap-3">
109-
110-
<NavLink
111-
to="/"
112-
className={navLinkStyles}
113-
onClick={closeMenu}
114-
>
93+
<NavLink to="/" className={navLinkStyles} onClick={closeMenu}>
11594
Home
11695
</NavLink>
117-
118-
<NavLink
119-
to="/track"
120-
className={navLinkStyles}
121-
onClick={closeMenu}
122-
>
96+
<NavLink to="/track" className={navLinkStyles} onClick={closeMenu}>
12397
Tracker
12498
</NavLink>
125-
126-
<NavLink
127-
to="/contributors"
128-
className={navLinkStyles}
129-
onClick={closeMenu}
130-
>
99+
<NavLink to="/contributors" className={navLinkStyles} onClick={closeMenu}>
131100
Contributors
132101
</NavLink>
133-
134-
<NavLink
135-
to="/login"
136-
className={navLinkStyles}
137-
onClick={closeMenu}
138-
>
102+
<NavLink to="/profile" className={navLinkStyles} onClick={closeMenu}>
103+
<span className="inline-flex items-center gap-2"><User className="h-4 w-4" />Profile</span>
104+
</NavLink>
105+
<NavLink to="/login" className={navLinkStyles} onClick={closeMenu}>
139106
Login
140107
</NavLink>
141108
</div>

src/pages/Profile/Profile.tsx

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import { useContext } from "react";
2+
import { Link } from "react-router-dom";
3+
import { ArrowRight, BadgeCheck, CalendarDays, Clock3, History, Mail, ShieldCheck, Sparkles, UserCircle2 } from "lucide-react";
4+
import { motion } from "framer-motion";
5+
import { ThemeContext } from "../../context/ThemeContext";
6+
7+
const Profile = () => {
8+
const themeContext = useContext(ThemeContext);
9+
if (!themeContext) return null;
10+
11+
const { mode } = themeContext;
12+
13+
const profile = {
14+
username: "Profile",
15+
email: "profile@githubtracker.dev",
16+
joined: "Always available",
17+
status: "Active",
18+
};
19+
20+
const profileCompleteness = 100;
21+
22+
const quickStats = [
23+
{ label: "Account status", value: "Active", icon: BadgeCheck, tone: "text-emerald-500" },
24+
{ label: "Session", value: "Secure", icon: ShieldCheck, tone: "text-cyan-500" },
25+
{ label: "Profile score", value: `${profileCompleteness}%`, icon: Sparkles, tone: "text-fuchsia-500" },
26+
];
27+
28+
return (
29+
<div className={`min-h-[calc(100vh-8rem)] w-full overflow-hidden px-4 py-10 ${mode === "dark" ? "bg-slate-950 text-white" : "bg-slate-50 text-slate-900"}`}>
30+
<div className="mx-auto w-full max-w-6xl">
31+
<motion.div
32+
initial={{ opacity: 0, y: 14 }}
33+
animate={{ opacity: 1, y: 0 }}
34+
transition={{ duration: 0.45 }}
35+
className={`relative overflow-hidden rounded-[2rem] border shadow-2xl ${mode === "dark" ? "border-white/10 bg-white/5 backdrop-blur-xl" : "border-slate-200 bg-white"}`}
36+
>
37+
<div className="absolute inset-0 opacity-70">
38+
<div className="absolute -left-12 top-8 h-40 w-40 rounded-full bg-cyan-400/20 blur-3xl" />
39+
<div className="absolute right-0 top-0 h-56 w-56 rounded-full bg-emerald-400/20 blur-3xl" />
40+
<div className="absolute bottom-0 left-1/2 h-48 w-48 rounded-full bg-blue-500/10 blur-3xl" />
41+
</div>
42+
43+
<div className="relative bg-gradient-to-r from-blue-600 via-cyan-500 to-emerald-500 px-6 py-8 text-white sm:px-10 sm:py-10">
44+
<div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
45+
<div>
46+
<p className="text-sm uppercase tracking-[0.35em] text-white/80">Account Overview</p>
47+
<h1 className="mt-2 text-3xl font-black sm:text-4xl">Your profile dashboard</h1>
48+
<p className="mt-3 max-w-2xl text-sm text-white/80 sm:text-base">
49+
Review your profile setup and jump back into tracking without leaving the profile screen.
50+
</p>
51+
</div>
52+
53+
<div className="inline-flex w-fit items-center gap-2 rounded-full border border-white/20 bg-white/10 px-4 py-2 text-sm font-medium backdrop-blur">
54+
<Clock3 className="h-4 w-4" />
55+
Updated today
56+
</div>
57+
</div>
58+
</div>
59+
60+
<div className="relative grid gap-6 px-6 py-8 sm:px-10 lg:grid-cols-[1.25fr_0.75fr]">
61+
<div className={`rounded-[1.75rem] border p-6 shadow-sm ${mode === "dark" ? "border-white/10 bg-slate-900/60" : "border-slate-200 bg-slate-50"}`}>
62+
<div className="flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
63+
<div className="flex items-center gap-4">
64+
<div className="flex h-20 w-20 items-center justify-center rounded-[1.5rem] bg-gradient-to-br from-blue-600 to-cyan-500 text-3xl font-black text-white shadow-lg shadow-cyan-500/20">
65+
<UserCircle2 className="h-10 w-10" />
66+
</div>
67+
<div>
68+
<div className="flex flex-wrap items-center gap-2">
69+
<h2 className="text-3xl font-extrabold tracking-tight">{profile.username}</h2>
70+
<span className="inline-flex items-center gap-1 rounded-full bg-emerald-500/10 px-3 py-1 text-xs font-semibold text-emerald-500">
71+
<BadgeCheck className="h-3.5 w-3.5" />
72+
{profile.status}
73+
</span>
74+
</div>
75+
<p className={`${mode === "dark" ? "text-slate-300" : "text-slate-600"}`}>
76+
A focused profile page for your GitHub tracking workspace.
77+
</p>
78+
</div>
79+
</div>
80+
81+
<div className={`rounded-2xl border px-4 py-3 ${mode === "dark" ? "border-white/10 bg-white/5" : "border-slate-200 bg-white"}`}>
82+
<p className="text-xs uppercase tracking-[0.2em] text-slate-400">Profile completeness</p>
83+
<div className="mt-2 h-2 w-48 overflow-hidden rounded-full bg-slate-200 dark:bg-slate-800">
84+
<div className="h-full rounded-full bg-gradient-to-r from-blue-600 to-emerald-500" style={{ width: `${profileCompleteness}%` }} />
85+
</div>
86+
<p className="mt-2 text-sm font-semibold">{profileCompleteness}% complete</p>
87+
</div>
88+
</div>
89+
90+
<div className="mt-8 grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
91+
<div className={`rounded-2xl border p-4 ${mode === "dark" ? "border-white/10 bg-white/5" : "border-slate-200 bg-white"}`}>
92+
<div className="flex items-center gap-2 text-sm font-medium uppercase tracking-wide text-slate-500">
93+
<Mail className="h-4 w-4" />
94+
Email
95+
</div>
96+
<p className="mt-3 break-all text-base font-semibold">{profile.email}</p>
97+
</div>
98+
99+
<div className={`rounded-2xl border p-4 ${mode === "dark" ? "border-white/10 bg-white/5" : "border-slate-200 bg-white"}`}>
100+
<div className="flex items-center gap-2 text-sm font-medium uppercase tracking-wide text-slate-500">
101+
<CalendarDays className="h-4 w-4" />
102+
Joined
103+
</div>
104+
<p className="mt-3 text-base font-semibold">{profile.joined}</p>
105+
</div>
106+
107+
<div className={`rounded-2xl border p-4 ${mode === "dark" ? "border-white/10 bg-white/5" : "border-slate-200 bg-white"}`}>
108+
<div className="flex items-center gap-2 text-sm font-medium uppercase tracking-wide text-slate-500">
109+
<History className="h-4 w-4" />
110+
Account ID
111+
</div>
112+
<p className="mt-3 break-all text-sm font-semibold text-slate-900 dark:text-slate-100">profile</p>
113+
</div>
114+
</div>
115+
116+
<div className="mt-8 grid gap-4 md:grid-cols-3">
117+
{quickStats.map((stat) => {
118+
const Icon = stat.icon;
119+
120+
return (
121+
<div key={stat.label} className={`rounded-2xl border p-4 ${mode === "dark" ? "border-white/10 bg-white/5" : "border-slate-200 bg-white"}`}>
122+
<div className="flex items-center justify-between gap-3">
123+
<div>
124+
<p className="text-xs uppercase tracking-[0.2em] text-slate-400">{stat.label}</p>
125+
<p className="mt-2 text-lg font-bold">{stat.value}</p>
126+
</div>
127+
<Icon className={`h-5 w-5 ${stat.tone}`} />
128+
</div>
129+
</div>
130+
);
131+
})}
132+
</div>
133+
134+
<div className="mt-8 flex flex-wrap gap-3">
135+
<Link to="/track" className="inline-flex items-center gap-2 rounded-2xl border border-slate-300 bg-transparent px-5 py-3 text-sm font-semibold text-slate-700 transition hover:-translate-y-0.5 hover:bg-slate-100 dark:border-white/15 dark:text-slate-200 dark:hover:bg-white/5">
136+
<ArrowRight className="h-4 w-4" />
137+
Go to tracker
138+
</Link>
139+
</div>
140+
</div>
141+
142+
<aside className="flex flex-col gap-6">
143+
<div className={`rounded-[1.75rem] border p-6 shadow-sm ${mode === "dark" ? "border-white/10 bg-slate-900/60" : "border-slate-200 bg-slate-50"}`}>
144+
<div className="flex items-center justify-between gap-3">
145+
<div>
146+
<h3 className="text-lg font-bold">Session summary</h3>
147+
<p className={`mt-1 text-sm ${mode === "dark" ? "text-slate-400" : "text-slate-500"}`}>
148+
A quick overview of this profile page.
149+
</p>
150+
</div>
151+
<div className="rounded-2xl bg-emerald-500/10 p-3 text-emerald-500">
152+
<ShieldCheck className="h-5 w-5" />
153+
</div>
154+
</div>
155+
156+
<dl className="mt-6 space-y-5 text-sm">
157+
<div>
158+
<dt className={`${mode === "dark" ? "text-slate-400" : "text-slate-500"}`}>Session state</dt>
159+
<dd className="mt-1 font-semibold text-emerald-500">Ready</dd>
160+
</div>
161+
<div>
162+
<dt className={`${mode === "dark" ? "text-slate-400" : "text-slate-500"}`}>Username</dt>
163+
<dd className="mt-1 font-semibold">{profile.username}</dd>
164+
</div>
165+
<div>
166+
<dt className={`${mode === "dark" ? "text-slate-400" : "text-slate-500"}`}>Email</dt>
167+
<dd className="mt-1 break-all font-semibold">{profile.email}</dd>
168+
</div>
169+
<div>
170+
<dt className={`${mode === "dark" ? "text-slate-400" : "text-slate-500"}`}>Joined</dt>
171+
<dd className="mt-1 font-semibold">{profile.joined}</dd>
172+
</div>
173+
</dl>
174+
</div>
175+
176+
<div className={`rounded-[1.75rem] border p-6 shadow-sm ${mode === "dark" ? "border-white/10 bg-slate-900/60" : "border-slate-200 bg-slate-50"}`}>
177+
<h3 className="text-lg font-bold">Next steps</h3>
178+
<div className="mt-5 space-y-3 text-sm">
179+
<Link to="/contributors" className="flex items-center justify-between rounded-2xl border border-transparent px-4 py-3 transition hover:border-blue-200 hover:bg-blue-50 dark:hover:border-cyan-500/20 dark:hover:bg-white/5">
180+
<span>
181+
<span className="block font-semibold">Browse contributors</span>
182+
<span className={`block text-xs ${mode === "dark" ? "text-slate-400" : "text-slate-500"}`}>Explore the full contributor directory</span>
183+
</span>
184+
<ArrowRight className="h-4 w-4 text-blue-500" />
185+
</Link>
186+
<Link to="/track" className="flex items-center justify-between rounded-2xl border border-transparent px-4 py-3 transition hover:border-blue-200 hover:bg-blue-50 dark:hover:border-cyan-500/20 dark:hover:bg-white/5">
187+
<span>
188+
<span className="block font-semibold">Open tracker</span>
189+
<span className={`block text-xs ${mode === "dark" ? "text-slate-400" : "text-slate-500"}`}>Jump straight into issue and PR analytics</span>
190+
</span>
191+
<ArrowRight className="h-4 w-4 text-blue-500" />
192+
</Link>
193+
</div>
194+
</div>
195+
</aside>
196+
</div>
197+
</motion.div>
198+
</div>
199+
</div>
200+
);
201+
};
202+
203+
export default Profile;

0 commit comments

Comments
 (0)