Skip to content

Commit 7689b35

Browse files
committed
Add user settings tabs (profile, security, notifications)
1 parent 077e402 commit 7689b35

3 files changed

Lines changed: 323 additions & 0 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Link from "next/link";
2+
3+
export default function ButtonGoUserSettings() {
4+
return (
5+
<Link href="/user_settings">
6+
<button
7+
style={{
8+
padding: "10px 20px",
9+
marginTop: "20px",
10+
backgroundColor: "#0070f3",
11+
color: "white",
12+
borderRadius: "5px",
13+
textDecoration: "none",
14+
fontSize: "1.1em",
15+
}}
16+
>
17+
Go to User Settings
18+
</button>
19+
</Link>
20+
);
21+
}

client/src/pages/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import ButtonGoOrganizationDashboard from "../components/ui/button_go_organization_dashboard";
55
import ButtonGoUserDashboard from "../components/ui/button_go_user_dashboard";
66
import ButtonGoUserProfilePage from "../components/ui/button_go_user_profile_page";
7+
import ButtonGoUserSettings from "../components/ui/button_go_user_settings";
78

89
// this is a react functional component
910
// it returns a html element that will render the jsx inside it
@@ -30,6 +31,7 @@ const LandingPage = () => {
3031
<ButtonGoOrganizationDashboard />
3132
<ButtonGoUserDashboard />
3233
<ButtonGoUserProfilePage />
34+
<ButtonGoUserSettings />
3335
</div>
3436
);
3537
};

client/src/pages/user_settings.tsx

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
import Head from "next/head";
2+
import { useState } from "react";
3+
4+
import Navbar from "../components/ui/user_navbar";
5+
6+
export default function UserSettings() {
7+
const [activeTab, setActiveTab] = useState<
8+
"profile" | "security" | "notifications"
9+
>("profile");
10+
return (
11+
<>
12+
<Head>
13+
<title>User Settings</title>
14+
</Head>
15+
16+
<Navbar />
17+
18+
<div
19+
style={{
20+
backgroundColor: "#e6e6e6",
21+
minHeight: "100vh",
22+
paddingTop: "64px",
23+
paddingBottom: "40px",
24+
display: "flex",
25+
justifyContent: "center",
26+
}}
27+
>
28+
{/* Main container */}
29+
<div
30+
style={{
31+
display: "flex",
32+
width: "1000px",
33+
marginTop: "30px",
34+
gap: "24px",
35+
alignItems: "flex-start",
36+
}}
37+
>
38+
{/* Sidebar */}
39+
<div
40+
style={{
41+
width: "200px",
42+
backgroundColor: "#ffffff",
43+
borderRadius: "8px",
44+
padding: "24px",
45+
height: "fit-content",
46+
gap: "32px",
47+
display: "flex",
48+
flexDirection: "column",
49+
}}
50+
>
51+
<div
52+
onClick={() => setActiveTab("profile")}
53+
style={{
54+
cursor: "pointer",
55+
fontWeight: activeTab === "profile" ? "bold" : "normal",
56+
}}
57+
>
58+
Profile
59+
</div>
60+
61+
<div
62+
onClick={() => setActiveTab("notifications")}
63+
style={{
64+
cursor: "pointer",
65+
fontWeight: activeTab === "notifications" ? "bold" : "normal",
66+
}}
67+
>
68+
Notifications
69+
</div>
70+
71+
<div
72+
onClick={() => setActiveTab("security")}
73+
style={{
74+
cursor: "pointer",
75+
fontWeight: activeTab === "security" ? "bold" : "normal",
76+
}}
77+
>
78+
Security
79+
</div>
80+
</div>
81+
82+
{/* Content */}
83+
<div
84+
style={{
85+
flex: 1,
86+
backgroundColor: "#ffffff",
87+
borderRadius: "8px",
88+
padding: "32px",
89+
}}
90+
>
91+
{activeTab === "profile" && <ProfileTab />}
92+
{activeTab === "security" && <SecurityTab />}
93+
{activeTab === "notifications" && <NotificationsTab />}
94+
</div>
95+
</div>
96+
</div>
97+
</>
98+
);
99+
}
100+
101+
function FormRow({ children }: { children: React.ReactNode }) {
102+
return (
103+
<div
104+
style={{
105+
display: "flex",
106+
gap: "16px",
107+
marginBottom: "20px",
108+
}}
109+
>
110+
{children}
111+
</div>
112+
);
113+
}
114+
115+
function Input({
116+
placeholder,
117+
full = false,
118+
}: {
119+
placeholder: string;
120+
full?: boolean;
121+
}) {
122+
return (
123+
<input
124+
placeholder={placeholder}
125+
style={{
126+
width: full ? "100%" : "100%",
127+
padding: "12px",
128+
borderRadius: "8px",
129+
border: "none",
130+
backgroundColor: "#f1f1f1",
131+
}}
132+
/>
133+
);
134+
}
135+
136+
function ProfileTab() {
137+
return (
138+
<>
139+
{/* Avatar */}
140+
<div style={{ display: "flex", alignItems: "center", gap: "16px" }}>
141+
<div
142+
style={{
143+
width: "72px",
144+
height: "72px",
145+
borderRadius: "50%",
146+
backgroundColor: "#5b84b1",
147+
color: "white",
148+
display: "flex",
149+
alignItems: "center",
150+
justifyContent: "center",
151+
fontSize: "28px",
152+
}}
153+
>
154+
U
155+
</div>
156+
157+
<div>
158+
<h2 style={{ marginBottom: "4px" }}>New User</h2>
159+
<p style={{ color: "#666", fontSize: "14px" }}>
160+
Member since December 2025
161+
</p>
162+
</div>
163+
</div>
164+
165+
{/* Form */}
166+
<div style={{ marginTop: "32px" }}>
167+
<FormRow>
168+
<Input placeholder="First name" />
169+
<Input placeholder="Last name" />
170+
</FormRow>
171+
172+
<FormRow>
173+
<Input placeholder="Date of Birth" />
174+
<Input placeholder="Phone number" />
175+
</FormRow>
176+
177+
<div style={{ marginBottom: "20px" }}>
178+
<Input placeholder="Email address" full />
179+
</div>
180+
181+
<div style={{ marginBottom: "16px" }}>
182+
<Input placeholder="Address" full />
183+
</div>
184+
185+
<button
186+
style={{
187+
marginTop: "24px",
188+
width: "100%",
189+
padding: "12px",
190+
borderRadius: "8px",
191+
border: "none",
192+
backgroundColor: "#e6e6e6",
193+
cursor: "pointer",
194+
}}
195+
>
196+
Save changes
197+
</button>
198+
</div>
199+
</>
200+
);
201+
}
202+
203+
function SecurityTab() {
204+
return (
205+
<div>
206+
<h2 style={{ marginBottom: "24px" }}>Password</h2>
207+
208+
<div style={{ marginBottom: "16px" }}>
209+
<input
210+
type="password"
211+
placeholder="Current password"
212+
style={inputStyle}
213+
/>
214+
</div>
215+
216+
<div style={{ marginBottom: "16px" }}>
217+
<input type="password" placeholder="New password" style={inputStyle} />
218+
</div>
219+
220+
<div style={{ marginBottom: "6px" }}>
221+
<input
222+
type="password"
223+
placeholder="Confirm new password"
224+
style={inputStyle}
225+
/>
226+
</div>
227+
228+
<p style={{ fontSize: "15px", color: "#777", marginBottom: "24px" }}>
229+
At least 8 characters
230+
</p>
231+
232+
<button style={primaryButtonStyle}>Change password</button>
233+
</div>
234+
);
235+
}
236+
237+
function NotificationsTab() {
238+
return (
239+
<div>
240+
<h2 style={{ marginBottom: "24px" }}>Notifications</h2>
241+
242+
<div style={notificationHeaderStyle}>
243+
<span></span>
244+
245+
<div style={{ display: "flex", justifyContent: "center" }}>
246+
<strong>Email</strong>
247+
</div>
248+
249+
<div style={{ display: "flex", justifyContent: "center" }}>
250+
<strong>Mobile</strong>
251+
</div>
252+
</div>
253+
254+
{["Inbox messages", "Order messages", "Promotions", "Updates"].map(
255+
(label) => (
256+
<div key={label} style={notificationRowStyle}>
257+
<span>{label}</span>
258+
<input type="checkbox" />
259+
<input type="checkbox" />
260+
</div>
261+
),
262+
)}
263+
</div>
264+
);
265+
}
266+
267+
const inputStyle: React.CSSProperties = {
268+
width: "100%",
269+
padding: "14px 16px",
270+
borderRadius: "12px",
271+
border: "none",
272+
backgroundColor: "#f2f2f2",
273+
fontSize: "16px",
274+
};
275+
276+
const primaryButtonStyle: React.CSSProperties = {
277+
width: "100%",
278+
padding: "16px",
279+
borderRadius: "12px",
280+
border: "none",
281+
backgroundColor: "#e6e6e6",
282+
cursor: "pointer",
283+
fontSize: "16px",
284+
};
285+
286+
const notificationHeaderStyle: React.CSSProperties = {
287+
display: "grid",
288+
gridTemplateColumns: "1fr 80px 80px",
289+
paddingBottom: "8px",
290+
borderBottom: "1px solid #ccc",
291+
marginBottom: "12px",
292+
};
293+
294+
const notificationRowStyle: React.CSSProperties = {
295+
display: "grid",
296+
gridTemplateColumns: "1fr 80px 80px",
297+
alignItems: "center",
298+
padding: "12px 0",
299+
borderBottom: "1px solid #eee",
300+
};

0 commit comments

Comments
 (0)