aki-008 commited on
Commit
b86abde
·
1 Parent(s): 6c6eb30

feat: fixed frontend for Interview page

Browse files
Frontend/src/components/dashboard/Sidebar.tsx CHANGED
@@ -27,60 +27,68 @@ const Sidebar: React.FC = () => {
27
 
28
  return (
29
  <aside
30
- className={`flex flex-col justify-between h-screen bg-maya-dark text-white transition-all duration-300 shadow-xl border-r border-indigo-400/30 ${
 
31
  collapsed ? "w-20" : "w-64"
32
  }`}
33
  >
34
  {/* Top Section */}
35
  <div>
36
- <div className="flex items-center justify-between font-bold py-6 px-6 border-b border-indigo-400/30">
37
  {!collapsed && (
38
- <span className="text-xl tracking-wide font-handwriting">
39
- Maya AI
40
  </span>
41
  )}
42
  <button
43
  onClick={() => setCollapsed(!collapsed)}
44
- className="p-1 hover:bg-white/10 rounded-full transition"
45
  >
46
  {collapsed ? <ChevronRight size={20} /> : <ChevronLeft size={20} />}
47
  </button>
48
  </div>
49
 
50
- <nav className="p-4 space-y-2">
51
  {navItems.map((item) => (
52
  <Link
53
  key={item.path}
54
  to={item.path}
55
- className={`flex items-center space-x-3 p-3 rounded-xl transition-all duration-200
 
 
 
 
56
  ${
57
  location.pathname === item.path
58
- ? "bg-white text-maya-dark shadow-md font-semibold translate-x-1"
59
- : "hover:bg-white/10 text-indigo-50"
60
  }`}
61
  >
62
- {item.icon}
63
- {!collapsed && <span>{item.label}</span>}
 
 
64
  </Link>
65
  ))}
66
  </nav>
67
  </div>
68
 
69
  {/* Bottom Section */}
70
- <div className="p-4 border-t border-indigo-400/30 space-y-2">
71
- <button className="flex items-center space-x-3 p-3 rounded-xl hover:bg-white/10 transition w-full text-left text-indigo-100">
72
  <Settings size={20} />
73
  {!collapsed && <span>Settings</span>}
74
  </button>
75
 
76
- <button className="flex items-center space-x-3 p-3 rounded-xl hover:bg-white/10 transition w-full text-left text-indigo-100">
77
  <User size={20} />
78
  {!collapsed && <span>{username}</span>}
79
  </button>
80
 
 
81
  <button
82
  onClick={logout}
83
- className="flex items-center space-x-3 p-3 rounded-xl bg-red-400/20 hover:bg-red-400/40 text-red-100 hover:text-white transition w-full text-left"
84
  >
85
  <LogOut size={20} />
86
  {!collapsed && <span>Logout</span>}
 
27
 
28
  return (
29
  <aside
30
+ // 1. MAIN BACKGROUND: #434E78
31
+ className={`flex flex-col justify-between h-screen bg-[#434E78] text-white transition-all duration-300 shadow-xl border-r border-[#607B8F]/50 ${
32
  collapsed ? "w-20" : "w-64"
33
  }`}
34
  >
35
  {/* Top Section */}
36
  <div>
37
+ <div className="flex items-center justify-between font-bold py-6 px-6 border-b border-[#607B8F]/50">
38
  {!collapsed && (
39
+ <span className="text-xl tracking-wide font-handwriting text-[#F7E396]">
40
+ Prep AI
41
  </span>
42
  )}
43
  <button
44
  onClick={() => setCollapsed(!collapsed)}
45
+ className="p-1 hover:bg-[#E97F4A] rounded-full transition text-white"
46
  >
47
  {collapsed ? <ChevronRight size={20} /> : <ChevronLeft size={20} />}
48
  </button>
49
  </div>
50
 
51
+ <nav className="p-4 space-y-3">
52
  {navItems.map((item) => (
53
  <Link
54
  key={item.path}
55
  to={item.path}
56
+ // 2. BUTTON LOGIC:
57
+ // - Default: bg-[#607B8F]
58
+ // - Hover: bg-[#E97F4A]
59
+ // - Active: Border #F7E396 (Highlight)
60
+ className={`flex items-center space-x-3 p-3 rounded-xl transition-all duration-200 border-2
61
  ${
62
  location.pathname === item.path
63
+ ? "bg-[#607B8F] border-[#F7E396] shadow-lg translate-x-1"
64
+ : "bg-[#607B8F] border-transparent hover:bg-[#E97F4A] text-gray-100 hover:text-white"
65
  }`}
66
  >
67
+ <span className="text-white">{item.icon}</span>
68
+ {!collapsed && (
69
+ <span className="font-medium text-white">{item.label}</span>
70
+ )}
71
  </Link>
72
  ))}
73
  </nav>
74
  </div>
75
 
76
  {/* Bottom Section */}
77
+ <div className="p-4 border-t border-[#607B8F]/50 space-y-3">
78
+ <button className="flex items-center space-x-3 p-3 rounded-xl bg-[#607B8F] border-2 border-transparent hover:bg-[#E97F4A] transition w-full text-left text-white">
79
  <Settings size={20} />
80
  {!collapsed && <span>Settings</span>}
81
  </button>
82
 
83
+ <button className="flex items-center space-x-3 p-3 rounded-xl bg-[#607B8F] border-2 border-transparent hover:bg-[#E97F4A] transition w-full text-left text-white">
84
  <User size={20} />
85
  {!collapsed && <span>{username}</span>}
86
  </button>
87
 
88
+ {/* Logout */}
89
  <button
90
  onClick={logout}
91
+ className="flex items-center space-x-3 p-3 rounded-xl bg-red-500/80 border-2 border-transparent hover:bg-red-600 transition w-full text-left text-white"
92
  >
93
  <LogOut size={20} />
94
  {!collapsed && <span>Logout</span>}
Frontend/src/pages/AiInterview.tsx CHANGED
@@ -1,41 +1,55 @@
1
  import React, { useEffect, useState } from "react";
2
  import Vapi from "@vapi-ai/web";
3
- import { Mic, PhoneOff, Send, Loader2, Volume2 } from "lucide-react";
 
 
 
 
 
 
 
 
 
 
4
 
5
  // --- CONFIG ---
6
- const VAPI_PUBLIC_KEY = "6e393730-74a2-4690-8cb7-845ed3880488"; // Replace with yours
7
  const BACKEND_URL = "http://localhost:8000";
8
 
9
  const vapi = new Vapi(VAPI_PUBLIC_KEY);
10
 
11
  function AIInterview() {
12
- // View State
13
  const [viewState, setViewState] = useState<"config" | "interview">("config");
14
-
15
- // Vapi State
16
  const [isSessionActive, setIsSessionActive] = useState(false);
17
  const [isSpeaking, setIsSpeaking] = useState(false);
 
18
  const [status, setStatus] = useState("Idle");
19
 
20
  // Form State
21
- const [name, setName] = useState("Prakhar"); // Default from screenshot
22
  const [role, setRole] = useState("Senior Frontend Developer");
23
  const [exp, setExp] = useState("5");
 
24
  const [difficulty, setDifficulty] = useState("Medium (Intermediate)");
25
 
26
  useEffect(() => {
27
- // Vapi Event Listeners
 
 
 
28
  vapi.on("call-start", () => {
29
  setStatus("Connected");
30
  setIsSessionActive(true);
31
- setViewState("interview"); // Switch to bubble view
 
32
  });
33
 
34
  vapi.on("call-end", () => {
35
  setStatus("Call Ended");
36
  setIsSessionActive(false);
37
  setIsSpeaking(false);
38
- setViewState("config"); // Go back to config
39
  });
40
 
41
  vapi.on("speech-start", () => setIsSpeaking(true));
@@ -87,149 +101,157 @@ function AIInterview() {
87
  vapi.stop();
88
  };
89
 
 
 
 
 
 
 
90
  // --- RENDER ---
91
  return (
92
- <div className="min-h-screen w-full font-sans text-gray-800 relative bg-white">
93
- {/* 1. SKETCHY GRID BACKGROUND */}
94
- <div className="absolute inset-0 z-0 bg-sketchy-grid bg-sketchy opacity-40 pointer-events-none"></div>
95
 
96
- {/* 2. COLOR BLOBS (Palette: #F5D3C4, #F2AEBB) */}
97
- <div className="absolute top-[-10%] right-[-5%] w-96 h-96 bg-maya-pink rounded-full mix-blend-multiply filter blur-3xl opacity-30 animate-blob"></div>
98
- <div className="absolute bottom-[-10%] left-[-10%] w-96 h-96 bg-maya-beige rounded-full mix-blend-multiply filter blur-3xl opacity-30 animate-blob animation-delay-2000"></div>
99
-
100
- {/* MAIN CONTENT AREA */}
101
- <div className="relative z-10 flex flex-col items-center justify-center min-h-screen p-6">
102
- {/* --- VIEW 1: CONFIG CARD (The "Maya" UI) --- */}
103
  {viewState === "config" && (
104
- <div className="w-full max-w-2xl bg-white rounded-xl shadow-2xl border border-gray-200 p-8 md:p-12 transition-all transform hover:scale-[1.005]">
105
  <div className="mb-8 text-center">
106
- <h1 className="text-4xl font-bold text-gray-800 mb-2 font-handwriting">
107
- Maya
108
  </h1>
109
- <div className="flex items-center justify-center gap-2 text-maya-dark">
110
- <BrainIcon />
111
- <span className="font-semibold">Configure Your Interview</span>
 
 
112
  </div>
113
  </div>
114
 
115
  <div className="space-y-6">
116
- {/* Input 1: Role */}
117
  <div>
118
- <label className="block text-sm font-semibold text-gray-600 mb-2">
 
 
 
 
 
 
 
 
 
 
 
 
119
  1. Job Role/Position
120
  </label>
121
  <input
122
  type="text"
123
  value={role}
124
  onChange={(e) => setRole(e.target.value)}
125
- className="w-full p-4 rounded-lg border-2 border-gray-200 focus:border-maya-light focus:ring-0 outline-none transition bg-gray-50 text-gray-700 font-medium placeholder-gray-400"
126
- placeholder="e.g. Senior Frontend Developer"
127
  />
128
  </div>
129
 
130
- {/* Input 2: Experience */}
131
  <div>
132
- <label className="block text-sm font-semibold text-gray-600 mb-2">
133
  2. Years of Professional Experience
134
  </label>
135
  <input
136
- type="text" // using text to match wireframe style, backend handles parsing
137
  value={exp}
138
  onChange={(e) => setExp(e.target.value)}
139
- className="w-full p-4 rounded-lg border-2 border-gray-200 focus:border-maya-light focus:ring-0 outline-none transition bg-gray-50 text-gray-700 font-medium placeholder-gray-400"
140
- placeholder="e.g. 5"
141
  />
142
  </div>
143
 
144
- {/* Input 3: Difficulty */}
145
  <div>
146
- <label className="block text-sm font-semibold text-gray-600 mb-2">
147
  3. Difficulty Level
148
  </label>
149
- <input
150
- type="text"
151
- value={difficulty}
152
- onChange={(e) => setDifficulty(e.target.value)}
153
- className="w-full p-4 rounded-lg border-2 border-gray-200 focus:border-maya-light focus:ring-0 outline-none transition bg-gray-50 text-gray-700 font-medium placeholder-gray-400"
154
- placeholder="Medium (Intermediate)"
155
- />
 
 
 
 
 
 
 
156
  </div>
157
 
158
- {/* Action Button */}
159
  <button
160
  onClick={startInterview}
161
  disabled={
162
  status === "Configuring..." || status === "Connecting..."
163
  }
164
- className="mt-4 px-8 py-4 bg-white border-2 border-gray-800 text-gray-800 font-bold rounded-lg shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] hover:shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] hover:translate-x-[2px] hover:translate-y-[2px] transition-all flex items-center gap-3 active:bg-gray-50"
165
  >
166
  {status === "Configuring..." || status === "Connecting..." ? (
167
- <Loader2 className="animate-spin w-5 h-5" />
168
  ) : (
169
- <Send className="w-5 h-5" />
170
  )}
171
  <span>Start Interview</span>
172
  </button>
173
  </div>
174
-
175
- {/* Decorative Color Codes (from wireframe) */}
176
- <div className="absolute bottom-4 right-6 flex flex-col items-end text-xs text-gray-400 font-mono">
177
- <span>#A7AAE1</span>
178
- <span>#F5D3C4</span>
179
- </div>
180
  </div>
181
  )}
182
 
183
- {/* --- VIEW 2: INTERVIEW BUBBLE UI (Active Call) --- */}
184
  {viewState === "interview" && (
185
  <div className="flex flex-col items-center justify-center w-full h-full animate-fade-in-up">
186
- {/* The Visualizer Orb */}
187
- <div className="relative mb-12">
188
- {/* Orb Style: Light Blue/White Swirling
189
- We use CSS gradients + shadowing + pulsing animation
190
- */}
191
  <div
192
  className={`
193
- w-48 h-48 rounded-full
194
- bg-gradient-radial from-white via-blue-100 to-blue-300
195
- shadow-[0_0_60px_rgba(167,170,225,0.6)]
196
  transition-all duration-300 ease-in-out
197
  flex items-center justify-center
198
- border border-white/50
199
  ${
200
  isSpeaking
201
- ? "scale-110 animate-pulse shadow-[0_0_80px_rgba(105,111,199,0.8)]"
202
- : "scale-100 animate-orb-float"
203
  }
204
  `}
205
  >
206
- {/* Inner shine for "liquid" look */}
207
- <div className="absolute top-4 left-6 w-12 h-6 bg-white opacity-60 rounded-full blur-md transform -rotate-45"></div>
208
-
209
  {isSpeaking ? (
210
- <Volume2 className="text-maya-dark w-12 h-12 opacity-50" />
211
  ) : (
212
- <div className="w-3 h-3 bg-maya-dark rounded-full opacity-30"></div>
213
  )}
214
  </div>
215
  </div>
216
 
217
- {/* Status Text */}
218
- <h2 className="text-2xl font-bold text-gray-700 mb-8 font-handwriting">
219
- {isSpeaking ? "Maya is speaking..." : "Listening to you..."}
220
  </h2>
221
 
222
- {/* Controls */}
223
- <div className="flex gap-6">
224
- <button className="flex items-center gap-2 px-6 py-3 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-full transition font-medium shadow-sm">
225
- <Mic size={18} /> Mute
 
 
 
 
 
 
 
226
  </button>
227
 
228
  <button
229
  onClick={stopInterview}
230
- className="flex items-center gap-2 px-6 py-3 bg-red-100 hover:bg-red-200 text-red-600 rounded-full transition font-medium shadow-sm"
231
  >
232
- <PhoneOff size={18} /> End call
233
  </button>
234
  </div>
235
  </div>
@@ -239,21 +261,4 @@ function AIInterview() {
239
  );
240
  }
241
 
242
- // Simple Icon Component
243
- const BrainIcon = () => (
244
- <svg
245
- width="24"
246
- height="24"
247
- viewBox="0 0 24 24"
248
- fill="none"
249
- stroke="currentColor"
250
- strokeWidth="2"
251
- strokeLinecap="round"
252
- strokeLinejoin="round"
253
- >
254
- <path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2Z" />
255
- <path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2Z" />
256
- </svg>
257
- );
258
-
259
  export default AIInterview;
 
1
  import React, { useEffect, useState } from "react";
2
  import Vapi from "@vapi-ai/web";
3
+ import {
4
+ Mic,
5
+ MicOff,
6
+ PhoneOff,
7
+ Send,
8
+ Loader2,
9
+ Volume2,
10
+ ChevronDown,
11
+ } from "lucide-react";
12
+ // Import useAuth to get dynamic username
13
+ import { useAuth } from "../components/context/AuthContext";
14
 
15
  // --- CONFIG ---
16
+ const VAPI_PUBLIC_KEY = "6e393730-74a2-4690-8cb7-845ed3880488";
17
  const BACKEND_URL = "http://localhost:8000";
18
 
19
  const vapi = new Vapi(VAPI_PUBLIC_KEY);
20
 
21
  function AIInterview() {
22
+ const { username } = useAuth();
23
  const [viewState, setViewState] = useState<"config" | "interview">("config");
 
 
24
  const [isSessionActive, setIsSessionActive] = useState(false);
25
  const [isSpeaking, setIsSpeaking] = useState(false);
26
+ const [isMuted, setIsMuted] = useState(false);
27
  const [status, setStatus] = useState("Idle");
28
 
29
  // Form State
30
+ const [name, setName] = useState(username || "Candidate");
31
  const [role, setRole] = useState("Senior Frontend Developer");
32
  const [exp, setExp] = useState("5");
33
+ // UPDATED: Default difficulty
34
  const [difficulty, setDifficulty] = useState("Medium (Intermediate)");
35
 
36
  useEffect(() => {
37
+ if (username) setName(username);
38
+ }, [username]);
39
+
40
+ useEffect(() => {
41
  vapi.on("call-start", () => {
42
  setStatus("Connected");
43
  setIsSessionActive(true);
44
+ setViewState("interview");
45
+ setIsMuted(false);
46
  });
47
 
48
  vapi.on("call-end", () => {
49
  setStatus("Call Ended");
50
  setIsSessionActive(false);
51
  setIsSpeaking(false);
52
+ setViewState("config");
53
  });
54
 
55
  vapi.on("speech-start", () => setIsSpeaking(true));
 
101
  vapi.stop();
102
  };
103
 
104
+ const toggleMute = () => {
105
+ const newMuteState = !isMuted;
106
+ vapi.setMuted(newMuteState);
107
+ setIsMuted(newMuteState);
108
+ };
109
+
110
  // --- RENDER ---
111
  return (
112
+ <div className="h-screen w-full font-sans text-white relative bg-[#434E78] overflow-hidden flex items-center justify-center">
113
+ <div className="absolute top-[-10%] right-[-5%] w-96 h-96 bg-[#F7E396] rounded-full mix-blend-overlay filter blur-3xl opacity-10 animate-blob"></div>
114
+ <div className="absolute bottom-[-10%] left-[-10%] w-96 h-96 bg-[#607B8F] rounded-full mix-blend-overlay filter blur-3xl opacity-10 animate-blob animation-delay-2000"></div>
115
 
116
+ <div className="relative z-10 w-full max-w-4xl p-6 flex flex-col items-center">
 
 
 
 
 
 
117
  {viewState === "config" && (
118
+ <div className="w-full max-w-2xl bg-[#607B8F] rounded-xl shadow-2xl border border-white/10 p-8 md:p-12 transition-all transform animate-fade-in-up">
119
  <div className="mb-8 text-center">
120
+ <h1 className="text-5xl font-bold text-white mb-2 font-handwriting drop-shadow-md">
121
+ Prep AI
122
  </h1>
123
+ <div className="flex items-center justify-center gap-2 text-[#F7E396]">
124
+ <Volume2 className="w-6 h-6" />
125
+ <span className="font-semibold tracking-wide">
126
+ Configure Your Interview
127
+ </span>
128
  </div>
129
  </div>
130
 
131
  <div className="space-y-6">
 
132
  <div>
133
+ <label className="block text-sm font-bold text-[#F7E396] mb-2 tracking-wide">
134
+ Candidate Name
135
+ </label>
136
+ <input
137
+ type="text"
138
+ value={name}
139
+ onChange={(e) => setName(e.target.value)}
140
+ className="w-full p-4 rounded-lg bg-[#434E78]/50 border-2 border-transparent focus:border-[#F7E396] focus:ring-0 outline-none transition text-white font-medium placeholder-gray-300 shadow-inner"
141
+ />
142
+ </div>
143
+
144
+ <div>
145
+ <label className="block text-sm font-bold text-[#F7E396] mb-2 tracking-wide">
146
  1. Job Role/Position
147
  </label>
148
  <input
149
  type="text"
150
  value={role}
151
  onChange={(e) => setRole(e.target.value)}
152
+ className="w-full p-4 rounded-lg bg-[#434E78]/50 border-2 border-transparent focus:border-[#F7E396] focus:ring-0 outline-none transition text-white font-medium placeholder-gray-300 shadow-inner"
 
153
  />
154
  </div>
155
 
 
156
  <div>
157
+ <label className="block text-sm font-bold text-[#F7E396] mb-2 tracking-wide">
158
  2. Years of Professional Experience
159
  </label>
160
  <input
161
+ type="text"
162
  value={exp}
163
  onChange={(e) => setExp(e.target.value)}
164
+ className="w-full p-4 rounded-lg bg-[#434E78]/50 border-2 border-transparent focus:border-[#F7E396] focus:ring-0 outline-none transition text-white font-medium placeholder-gray-300 shadow-inner"
 
165
  />
166
  </div>
167
 
168
+ {/* UPDATED: Difficulty Selection Dropdown */}
169
  <div>
170
+ <label className="block text-sm font-bold text-[#F7E396] mb-2 tracking-wide">
171
  3. Difficulty Level
172
  </label>
173
+ <div className="relative">
174
+ <select
175
+ value={difficulty}
176
+ onChange={(e) => setDifficulty(e.target.value)}
177
+ className="w-full p-4 rounded-lg bg-[#434E78]/50 border-2 border-transparent focus:border-[#F7E396] focus:ring-0 outline-none transition text-white font-medium shadow-inner appearance-none cursor-pointer"
178
+ >
179
+ <option value="Easy (Beginner)">Easy (Beginner)</option>
180
+ <option value="Medium (Intermediate)">
181
+ Medium (Intermediate)
182
+ </option>
183
+ <option value="Hard (Advanced)">Hard (Advanced)</option>
184
+ </select>
185
+ <ChevronDown className="absolute right-4 top-1/2 -translate-y-1/2 text-white pointer-events-none w-5 h-5" />
186
+ </div>
187
  </div>
188
 
 
189
  <button
190
  onClick={startInterview}
191
  disabled={
192
  status === "Configuring..." || status === "Connecting..."
193
  }
194
+ className="mt-6 px-8 py-4 bg-[#F7E396] text-[#434E78] font-bold text-lg rounded-lg shadow-lg hover:bg-[#E97F4A] hover:text-white transition-all duration-300 transform hover:-translate-y-1 flex items-center gap-3 w-full justify-center"
195
  >
196
  {status === "Configuring..." || status === "Connecting..." ? (
197
+ <Loader2 className="animate-spin w-6 h-6" />
198
  ) : (
199
+ <Send className="w-6 h-6" />
200
  )}
201
  <span>Start Interview</span>
202
  </button>
203
  </div>
 
 
 
 
 
 
204
  </div>
205
  )}
206
 
 
207
  {viewState === "interview" && (
208
  <div className="flex flex-col items-center justify-center w-full h-full animate-fade-in-up">
209
+ <div className="relative mb-16">
 
 
 
 
210
  <div
211
  className={`
212
+ w-56 h-56 rounded-full
213
+ bg-[#607B8F]
214
+ shadow-[0_0_40px_#F7E396]
215
  transition-all duration-300 ease-in-out
216
  flex items-center justify-center
217
+ border-4 border-white/20
218
  ${
219
  isSpeaking
220
+ ? "animate-pulse scale-110 shadow-[0_0_60px_#F7E396]"
221
+ : "animate-bounce"
222
  }
223
  `}
224
  >
 
 
 
225
  {isSpeaking ? (
226
+ <Volume2 className="text-white w-20 h-20 opacity-90 drop-shadow-md" />
227
  ) : (
228
+ <div className="w-4 h-4 bg-white rounded-full opacity-50 shadow-[0_0_10px_white]"></div>
229
  )}
230
  </div>
231
  </div>
232
 
233
+ <h2 className="text-3xl font-bold text-white mb-10 font-handwriting tracking-wider drop-shadow-md">
234
+ {isSpeaking ? "Prep AI is speaking..." : "Listening to you..."}
 
235
  </h2>
236
 
237
+ <div className="bg-[#607B8F] p-4 rounded-2xl shadow-xl border border-white/10 flex gap-6">
238
+ <button
239
+ onClick={toggleMute}
240
+ className={`flex items-center gap-2 px-6 py-3 rounded-xl transition font-bold shadow-md ${
241
+ isMuted
242
+ ? "bg-[#E97F4A] text-white hover:bg-orange-600"
243
+ : "bg-white/10 text-white hover:bg-white/20 border border-white/20"
244
+ }`}
245
+ >
246
+ {isMuted ? <MicOff size={20} /> : <Mic size={20} />}
247
+ {isMuted ? "Unmute" : "Mute"}
248
  </button>
249
 
250
  <button
251
  onClick={stopInterview}
252
+ className="flex items-center gap-2 px-6 py-3 bg-red-500 hover:bg-red-600 text-white border border-transparent rounded-xl transition font-bold shadow-md"
253
  >
254
+ <PhoneOff size={20} /> End Call
255
  </button>
256
  </div>
257
  </div>
 
261
  );
262
  }
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  export default AIInterview;
Frontend/src/pages/dashboard.tsx CHANGED
@@ -4,10 +4,11 @@ import SkillRadarChart from "../components/dashboard/SkillRadarChart";
4
  import WeakAreaBanner from "../components/dashboard/WeakAreaBanner";
5
  import InterviewPlayback from "../components/dashboard/InterviewPlayback";
6
  import { generateYearlyStreakData } from "../utils/generateYearlyStreakData";
 
7
 
8
  const Dashboard = () => {
 
9
  const streakData = generateYearlyStreakData();
10
-
11
  const radarData = [
12
  { skill: "DSA", value: 70 },
13
  { skill: "System Design", value: 60 },
@@ -16,38 +17,36 @@ const Dashboard = () => {
16
  { skill: "Accuracy", value: 68 },
17
  { skill: "Time Mgmt", value: 80 },
18
  ];
19
-
20
  const weakTopic = "Dynamic Programming";
21
 
22
  return (
23
- // PRIMARY CHANGE: Background Gradient inspired by landing page
24
- // Using a custom CSS class for a more complex gradient if needed, or approximating with Tailwind.
25
- // For now, let's use a subtle linear gradient that implies the dark blue-black.
26
- <div className="px-6 py-8 space-y-10 min-h-screen text-gray-100 bg-black font-OpenSans">
27
- {/* Font sans is a good default for modern look */}
28
-
29
- {/* ----------- HEADER SECTION (Updated for new theme) ----------- */}
30
  <div className="flex flex-col md:flex-row md:items-center justify-between mb-4">
31
- <h1 className="text-3xl lg:text-4xl font-extrabold text-gray-50 tracking-tight">
32
- 👋 Welcome back, <span className="text-blue-400">Prakhar</span>
 
 
33
  </h1>
34
 
35
  <div className="flex items-center space-x-3 mt-4 md:mt-0">
36
- {/* PRIMARY BUTTON: Vibrant Purple Theme Color, matching "Start Free Trial" */}
37
- <button className="px-6 py-2 bg-gradient-to-r from-blue-600 to-blue-800 text-white rounded-lg shadow-lg shadow-purple-500/30 hover:from-blue-500 hover:to-blue-700 transition-all duration-300 ease-in-out font-semibold">
38
  Start Interview
39
  </button>
40
  </div>
41
  </div>
42
 
43
- {/* ----------- GRID MAIN LAYOUT (2 COLUMNS for top content) ----------- */}
44
  <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
45
-
46
  {/* LEFT PANEL (Feedback Score) */}
47
  <div className="space-y-6 col-span-1">
48
- {/* CARD BACKGROUND CHANGE: Dark Card Color, subtle border/shadow */}
49
- <div className="bg-gradient-to-br from-[#1a202c] to-[#2d3748] rounded-xl shadow-lg p-6 border border-gray-700/50 h-full">
50
- <h2 className="text-xl font-bold mb-4 text-gray-50">AI Feedback Score</h2>
 
 
51
  <FeedbackScore
52
  confidence={78}
53
  clarity={82}
@@ -64,21 +63,21 @@ const Dashboard = () => {
64
 
65
  {/* RIGHT PANEL (Skill Chart) */}
66
  <div className="space-y-6 col-span-1">
67
- {/* CARD BACKGROUND CHANGE: Dark Card Color, subtle border/shadow */}
68
- <div className="bg-gradient-to-br from-[#1a202c] to-[#2d3748] rounded-xl shadow-lg p-6 border border-gray-700/50 h-full">
69
- <h2 className="text-xl font-bold mb-4 text-gray-50">Skill Strength Chart</h2>
 
70
  <SkillRadarChart data={radarData} />
71
  </div>
72
  </div>
73
  </div>
74
-
75
- {/* ----------- MIDDLE ROW: INTERVIEW PLAYBACK (LEFT) AND WEAK AREA (RIGHT) ----------- */}
76
- <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
77
 
78
- {/* INTERVIEW PLAYBACK (2/3 width on large screens, LEFT) */}
79
- {/* CARD BACKGROUND CHANGE: Dark Card Color, subtle border/shadow */}
80
- <div className="bg-gradient-to-br from-[#1a202c] to-[#2d3748] rounded-xl shadow-lg p-6 border border-gray-700/50 lg:col-span-2">
81
- <h2 className="text-xl font-bold mb-4 text-gray-50">Interview Playback AI Feedback</h2>
 
 
82
  <InterviewPlayback
83
  audioUrl="https://example.com/audio.mp3"
84
  transcript={`Interviewer: Explain polymorphism.\nYou: Polymorphism means...`}
@@ -90,23 +89,19 @@ const Dashboard = () => {
90
  />
91
  </div>
92
 
93
- {/* WEAK AREA (1/3 width on large screens, RIGHT) */}
94
- {/* CARD BACKGROUND CHANGE: Dark Card Color, subtle border/shadow */}
95
- <div className="bg-gradient-to-br from-[#1a202c] to-[#2d3748] rounded-xl shadow-lg p-5 border border-gray-700/50 col-span-1 flex-col items-center justify-center">
96
- {/* WeakAreaBanner will need internal styling adjustments for its alert nature */}
97
- <h2 className="text-xl font-bold mb-4 text-gray-50">WeakAreaBanner</h2>
98
  <WeakAreaBanner topic={weakTopic} />
99
  </div>
100
  </div>
101
 
102
- {/* ----------- BOTTOM ROW: YEARLY STREAK (FULL WIDTH) ----------- */}
103
- {/* CARD BACKGROUND CHANGE: Dark Card Color, subtle border/shadow */}
104
- <div className="bg-gradient-to-br from-[#1a202c] to-[#2d3748] rounded-xl shadow-lg p-6 border border-gray-700/50">
105
- <h2 className="text-xl font-bold mb-3 text-gray-50">Yearly Streak</h2>
106
  <YearlyStreak data={streakData} />
107
  </div>
108
  </div>
109
  );
110
  };
111
 
112
- export default Dashboard;
 
4
  import WeakAreaBanner from "../components/dashboard/WeakAreaBanner";
5
  import InterviewPlayback from "../components/dashboard/InterviewPlayback";
6
  import { generateYearlyStreakData } from "../utils/generateYearlyStreakData";
7
+ import { useAuth } from "../components/context/AuthContext"; // Import AuthContext
8
 
9
  const Dashboard = () => {
10
+ const { username } = useAuth(); // Get dynamic username
11
  const streakData = generateYearlyStreakData();
 
12
  const radarData = [
13
  { skill: "DSA", value: 70 },
14
  { skill: "System Design", value: 60 },
 
17
  { skill: "Accuracy", value: 68 },
18
  { skill: "Time Mgmt", value: 80 },
19
  ];
 
20
  const weakTopic = "Dynamic Programming";
21
 
22
  return (
23
+ // Updated background to match the new dark blue theme
24
+ <div className="px-6 py-8 space-y-10 min-h-screen text-gray-100 bg-[#434E78] font-OpenSans">
25
+ {/* ----------- HEADER SECTION ----------- */}
 
 
 
 
26
  <div className="flex flex-col md:flex-row md:items-center justify-between mb-4">
27
+ {/* Replaced Hardcoded Name with {username} */}
28
+ <h1 className="text-3xl lg:text-4xl font-extrabold text-white tracking-tight">
29
+ 👋 Welcome back,{" "}
30
+ <span className="text-[#F7E396]">{username || "User"}</span>
31
  </h1>
32
 
33
  <div className="flex items-center space-x-3 mt-4 md:mt-0">
34
+ {/* Updated Button to match new Highlight (#F7E396) theme */}
35
+ <button className="px-6 py-2 bg-[#F7E396] text-[#434E78] rounded-lg shadow-lg hover:bg-[#E97F4A] hover:text-white transition-all duration-300 ease-in-out font-bold">
36
  Start Interview
37
  </button>
38
  </div>
39
  </div>
40
 
41
+ {/* ----------- GRID MAIN LAYOUT ----------- */}
42
  <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
 
43
  {/* LEFT PANEL (Feedback Score) */}
44
  <div className="space-y-6 col-span-1">
45
+ {/* Updated Card Background to Secondary Blue (#607B8F) */}
46
+ <div className="bg-[#607B8F] rounded-xl shadow-lg p-6 border border-white/10 h-full">
47
+ <h2 className="text-xl font-bold mb-4 text-white">
48
+ AI Feedback Score
49
+ </h2>
50
  <FeedbackScore
51
  confidence={78}
52
  clarity={82}
 
63
 
64
  {/* RIGHT PANEL (Skill Chart) */}
65
  <div className="space-y-6 col-span-1">
66
+ <div className="bg-[#607B8F] rounded-xl shadow-lg p-6 border border-white/10 h-full">
67
+ <h2 className="text-xl font-bold mb-4 text-white">
68
+ Skill Strength Chart
69
+ </h2>
70
  <SkillRadarChart data={radarData} />
71
  </div>
72
  </div>
73
  </div>
 
 
 
74
 
75
+ {/* ----------- MIDDLE ROW ----------- */}
76
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
77
+ <div className="bg-[#607B8F] rounded-xl shadow-lg p-6 border border-white/10 lg:col-span-2">
78
+ <h2 className="text-xl font-bold mb-4 text-white">
79
+ Interview Playback AI Feedback
80
+ </h2>
81
  <InterviewPlayback
82
  audioUrl="https://example.com/audio.mp3"
83
  transcript={`Interviewer: Explain polymorphism.\nYou: Polymorphism means...`}
 
89
  />
90
  </div>
91
 
92
+ <div className="bg-[#607B8F] rounded-xl shadow-lg p-5 border border-white/10 col-span-1 flex-col items-center justify-center">
93
+ <h2 className="text-xl font-bold mb-4 text-white">WeakAreaBanner</h2>
 
 
 
94
  <WeakAreaBanner topic={weakTopic} />
95
  </div>
96
  </div>
97
 
98
+ {/* ----------- BOTTOM ROW ----------- */}
99
+ <div className="bg-[#607B8F] rounded-xl shadow-lg p-6 border border-white/10">
100
+ <h2 className="text-xl font-bold mb-3 text-white">Yearly Streak</h2>
 
101
  <YearlyStreak data={streakData} />
102
  </div>
103
  </div>
104
  );
105
  };
106
 
107
+ export default Dashboard;
Frontend/tailwind.config.cjs CHANGED
@@ -6,25 +6,15 @@ module.exports = {
6
  theme: {
7
  extend: {
8
  colors: {
9
- maya: {
10
- dark: "#696FC7", // Sidebar purple
11
- light: "#A7AAE1", // Light purple buttons/accents
12
- beige: "#F5D3C4", // Background accent
13
- pink: "#F2AEBB", // Background accent
14
- grid: "#cfd1e6", // Grid line color
15
  }
16
  },
17
- backgroundImage: {
18
- // Creates the "Graph Paper" sketchy look
19
- 'sketchy-grid': `
20
- linear-gradient(to right, #cfd1e6 1px, transparent 1px),
21
- linear-gradient(to bottom, #cfd1e6 1px, transparent 1px)
22
- `,
23
- },
24
- backgroundSize: {
25
- 'sketchy': '24px 24px',
26
- },
27
- // Added Font Family for the Sketchy Look
28
  fontFamily: {
29
  handwriting: ['"Patrick Hand"', 'cursive'],
30
  sans: ['"Open Sans"', 'sans-serif'],
@@ -32,7 +22,7 @@ module.exports = {
32
  animation: {
33
  spotlight: "spotlight 2s ease .75s 1 forwards",
34
  'orb-float': "float 6s ease-in-out infinite",
35
- 'orb-breathe': "breathe 4s ease-in-out infinite",
36
  },
37
  keyframes: {
38
  spotlight: {
@@ -43,9 +33,9 @@ module.exports = {
43
  "0%, 100%": { transform: "translateY(0px)" },
44
  "50%": { transform: "translateY(-10px)" },
45
  },
46
- breathe: {
47
- "0%, 100%": { transform: "scale(1)" },
48
- "50%": { transform: "scale(1.05)" },
49
  }
50
  },
51
  },
 
6
  theme: {
7
  extend: {
8
  colors: {
9
+ // Defined based on your specific request
10
+ palette: {
11
+ primary: "#434E78", // Main Sidebar & Page Background
12
+ secondary: "#607B8F", // Buttons & Cards & Controls Box
13
+ highlight: "#F7E396", // Active states, Start Button, Glow
14
+ accent: "#E97F4A", // Hover states
15
  }
16
  },
17
+ // Keeping your existing animations
 
 
 
 
 
 
 
 
 
 
18
  fontFamily: {
19
  handwriting: ['"Patrick Hand"', 'cursive'],
20
  sans: ['"Open Sans"', 'sans-serif'],
 
22
  animation: {
23
  spotlight: "spotlight 2s ease .75s 1 forwards",
24
  'orb-float': "float 6s ease-in-out infinite",
25
+ 'orb-pulse-glow': "pulse-glow 2s infinite",
26
  },
27
  keyframes: {
28
  spotlight: {
 
33
  "0%, 100%": { transform: "translateY(0px)" },
34
  "50%": { transform: "translateY(-10px)" },
35
  },
36
+ "pulse-glow": {
37
+ "0%, 100%": { boxShadow: "0 0 20px #F7E396", transform: "scale(1)" },
38
+ "50%": { boxShadow: "0 0 50px #F7E396", transform: "scale(1.05)" },
39
  }
40
  },
41
  },