Skip to content

Commit 5cc9978

Browse files
committed
making ui changes
1 parent 1bd4817 commit 5cc9978

4 files changed

Lines changed: 246 additions & 120 deletions

File tree

frontend/app/(protected)/settings/page.tsx

Lines changed: 117 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,128 @@
11
'use client';
2+
3+
import React, { useState } from 'react';
4+
import { useAuthStore } from '@/lib/store';
5+
import toast from 'react-hot-toast';
6+
27
export default function SettingsPage() {
8+
const { user } = useAuthStore();
9+
const [resumeFile, setResumeFile] = useState<File | null>(null);
10+
const [resumeUploaded, setResumeUploaded] = useState(false);
11+
12+
const handleResumeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
13+
const file = e.target.files?.[0];
14+
if (!file) return;
15+
if (file.type !== 'application/pdf') {
16+
toast.error('Only PDF files are supported');
17+
return;
18+
}
19+
if (file.size > 5 * 1024 * 1024) {
20+
toast.error('File size must be under 5MB');
21+
return;
22+
}
23+
setResumeFile(file);
24+
};
25+
26+
const handleResumeUpload = () => {
27+
if (!resumeFile) return;
28+
// Placeholder — wire to your backend when ready
29+
toast.success(`Resume "${resumeFile.name}" saved successfully`);
30+
setResumeUploaded(true);
31+
};
32+
333
return (
4-
<div className="max-w-7xl mx-auto px-4 py-8">
5-
<div className="mb-8">
6-
<div className="flex items-center justify-between">
7-
<div>
8-
<h1 className="text-3xl font-bold text-gray-900 mb-2">Settings</h1>
9-
<p className="text-gray-600">
10-
Configure your preferences and pipeline settings
11-
</p>
34+
<div className="max-w-3xl mx-auto px-6 py-10">
35+
{/* Header */}
36+
<div className="mb-10">
37+
<h1 className="text-2xl font-bold text-gray-900">Settings</h1>
38+
<p className="text-gray-500 mt-1">Manage your account and preferences</p>
39+
</div>
40+
41+
<div className="space-y-6">
42+
43+
{/* Profile Section */}
44+
<div className="bg-white rounded-xl border border-gray-200 p-6">
45+
<h2 className="text-base font-semibold text-gray-900 mb-4">Profile</h2>
46+
<div className="space-y-4">
47+
<div>
48+
<label className="block text-sm font-medium text-gray-600 mb-1">
49+
Name
50+
</label>
51+
<div className="px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-lg text-gray-900 text-sm">
52+
{user?.email?.split('@')[0] || '—'}
53+
</div>
54+
</div>
55+
<div>
56+
<label className="block text-sm font-medium text-gray-600 mb-1">
57+
Email Address
58+
</label>
59+
<div className="px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-lg text-gray-900 text-sm">
60+
{user?.email || '—'}
61+
</div>
62+
</div>
63+
</div>
64+
</div>
65+
66+
{/* Resume Section */}
67+
<div className="bg-white rounded-xl border border-gray-200 p-6">
68+
<h2 className="text-base font-semibold text-gray-900 mb-1">Resume</h2>
69+
<p className="text-sm text-gray-500 mb-4">
70+
Upload your resume to attach it to job applications. PDF only, max 5MB.
71+
</p>
72+
73+
<div className="border-2 border-dashed border-gray-200 rounded-xl p-8 text-center hover:border-gray-300 transition">
74+
<input
75+
type="file"
76+
accept=".pdf"
77+
onChange={handleResumeChange}
78+
className="hidden"
79+
id="resume-upload"
80+
/>
81+
<label htmlFor="resume-upload" className="cursor-pointer">
82+
<div className="text-3xl mb-2">📄</div>
83+
<p className="text-sm font-medium text-gray-700">
84+
{resumeFile ? resumeFile.name : 'Click to upload your resume'}
85+
</p>
86+
<p className="text-xs text-gray-400 mt-1">PDF up to 5MB</p>
87+
</label>
1288
</div>
13-
{!process.env.NEXT_PUBLIC_API_URL && (
14-
<span className="px-3 py-1 bg-yellow-100 text-yellow-800 rounded-full text-sm font-medium">
15-
⚠️ Demo Mode
16-
</span>
89+
90+
{resumeFile && !resumeUploaded && (
91+
<button
92+
onClick={handleResumeUpload}
93+
className="mt-4 w-full px-4 py-2.5 bg-gray-900 text-white text-sm font-medium rounded-lg hover:bg-gray-700 transition"
94+
>
95+
Save Resume
96+
</button>
97+
)}
98+
99+
{resumeUploaded && (
100+
<div className="mt-4 px-4 py-2.5 bg-green-50 border border-green-200 rounded-lg text-sm text-green-700 text-center">
101+
✓ Resume uploaded successfully
102+
</div>
17103
)}
18104
</div>
19-
</div>
20-
<div className="max-w-2xl">
21-
<div className="bg-white rounded-lg border border-gray-200 p-8">
22-
<div className="text-center py-12">
23-
<p className="text-gray-600 text-lg">⚙️ Settings page coming soon!</p>
24-
<p className="text-gray-500 mt-2">
25-
Here you will be able to configure:
26-
</p>
27-
<ul className="text-gray-600 mt-4 space-y-2">
28-
<li>✓ Pipeline scheduling</li>
29-
<li>✓ Job preferences and filters</li>
30-
<li>✓ Notification settings</li>
31-
<li>✓ Account preferences</li>
32-
</ul>
105+
106+
{/* Preferences Section */}
107+
<div className="bg-white rounded-xl border border-gray-200 p-6">
108+
<h2 className="text-base font-semibold text-gray-900 mb-1">Preferences</h2>
109+
<p className="text-sm text-gray-500 mb-4">More settings coming soon.</p>
110+
<div className="space-y-3 text-sm text-gray-400">
111+
<div className="flex items-center gap-2">
112+
<span className="w-4 h-4 rounded-full bg-gray-100 flex items-center justify-center text-xs"></span>
113+
Pipeline scheduling
114+
</div>
115+
<div className="flex items-center gap-2">
116+
<span className="w-4 h-4 rounded-full bg-gray-100 flex items-center justify-center text-xs"></span>
117+
Notification settings
118+
</div>
119+
<div className="flex items-center gap-2">
120+
<span className="w-4 h-4 rounded-full bg-gray-100 flex items-center justify-center text-xs"></span>
121+
Job preferences
122+
</div>
33123
</div>
34124
</div>
125+
35126
</div>
36127
</div>
37128
);

frontend/app/layout.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,21 @@ export const metadata: Metadata = {
99
export default function RootLayout({ children }: { children: React.ReactNode }) {
1010
return (
1111
<html lang="en">
12-
<body>{children}</body>
12+
<body className="min-h-screen flex flex-col bg-gray-50">
13+
<main className="flex-1">
14+
{children}
15+
</main>
16+
<footer className="border-t border-gray-200 bg-white mt-auto">
17+
<div className="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
18+
<span className="text-sm text-gray-400">
19+
© {new Date().getFullYear()} JobRec. All rights reserved.
20+
</span>
21+
<span className="text-sm text-gray-400">
22+
Built by <span className="text-gray-600 font-medium">Pranav</span>
23+
</span>
24+
</div>
25+
</footer>
26+
</body>
1327
</html>
1428
);
1529
}

frontend/components/FilterPanel.tsx

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,48 @@ export default function FilterPanel({ onFilterChange, onReset }: FilterPanelProp
4242

4343
const jobTypes = ['Internship', 'Full-time', 'Part-time', 'Contract', 'Freelance'];
4444

45-
const indiaLocations = [
46-
'India',
47-
'Remote (India)',
48-
'Bangalore',
49-
'Mumbai',
50-
'Delhi',
51-
'Hyderabad',
52-
'Pune',
53-
'Chennai',
54-
'Kolkata',
55-
'Ahmedabad',
56-
'Noida',
57-
'Gurgaon',
58-
];
59-
60-
const globalLocations = ['Remote', 'Remote (Global)'];
61-
62-
// Remaining locations from API excluding ones already in hardcoded groups
63-
const hardcodedSet = new Set([...indiaLocations, ...globalLocations]);
45+
// Dynamically filter India locations from API data
46+
const indiaLocations = locations?.data?.filter((loc: string) =>
47+
loc && (
48+
loc.toLowerCase().includes('india') ||
49+
loc.toLowerCase().includes('gujarat') ||
50+
loc.toLowerCase().includes('karnataka') ||
51+
loc.toLowerCase().includes('tamil nadu') ||
52+
loc.toLowerCase().includes('maharashtra') ||
53+
loc.toLowerCase().includes('telangana') ||
54+
loc.toLowerCase().includes('uttar pradesh') ||
55+
loc.toLowerCase().includes('rajasthan') ||
56+
loc.toLowerCase().includes('west bengal') ||
57+
loc.toLowerCase().includes('bangalore') ||
58+
loc.toLowerCase().includes('mumbai') ||
59+
loc.toLowerCase().includes('delhi') ||
60+
loc.toLowerCase().includes('hyderabad') ||
61+
loc.toLowerCase().includes('pune') ||
62+
loc.toLowerCase().includes('chennai') ||
63+
loc.toLowerCase().includes('kolkata') ||
64+
loc.toLowerCase().includes('ahmedabad') ||
65+
loc.toLowerCase().includes('noida') ||
66+
loc.toLowerCase().includes('gurgaon') ||
67+
loc.toLowerCase().includes('coimbatore') ||
68+
loc.toLowerCase().includes('remote (india)')
69+
)
70+
) ?? [];
71+
72+
// Dynamically filter global/remote locations
73+
const globalLocations = locations?.data?.filter((loc: string) =>
74+
loc && (
75+
loc.toLowerCase() === 'remote' ||
76+
loc.toLowerCase().includes('remote (global)') ||
77+
loc.toLowerCase().includes('worldwide') ||
78+
loc.toLowerCase().includes('anywhere')
79+
)
80+
) ?? [];
81+
82+
// Everything else
83+
const indiaSet = new Set(indiaLocations);
84+
const globalSet = new Set(globalLocations);
6485
const otherLocations = locations?.data?.filter(
65-
(loc: string) => loc && !hardcodedSet.has(loc)
86+
(loc: string) => loc && !indiaSet.has(loc) && !globalSet.has(loc)
6687
) ?? [];
6788

6889
const hasPendingChanges =
@@ -136,20 +157,24 @@ export default function FilterPanel({ onFilterChange, onReset }: FilterPanelProp
136157
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
137158
>
138159
<option value="">All Locations</option>
139-
<optgroup label="🇮🇳 India">
140-
{indiaLocations.map((loc) => (
141-
<option key={loc} value={loc}>
142-
{loc}
143-
</option>
144-
))}
145-
</optgroup>
146-
<optgroup label="🌍 Global / Remote">
147-
{globalLocations.map((loc) => (
148-
<option key={loc} value={loc}>
149-
{loc}
150-
</option>
151-
))}
152-
</optgroup>
160+
{indiaLocations.length > 0 && (
161+
<optgroup label="🇮🇳 India">
162+
{indiaLocations.map((loc: string) => (
163+
<option key={loc} value={loc}>
164+
{loc}
165+
</option>
166+
))}
167+
</optgroup>
168+
)}
169+
{globalLocations.length > 0 && (
170+
<optgroup label="🌍 Global / Remote">
171+
{globalLocations.map((loc: string) => (
172+
<option key={loc} value={loc}>
173+
{loc}
174+
</option>
175+
))}
176+
</optgroup>
177+
)}
153178
{otherLocations.length > 0 && (
154179
<optgroup label="Other">
155180
{otherLocations.slice(0, 30).map((loc: string) => (

0 commit comments

Comments
 (0)