Yes! Yes! I do

This commit is contained in:
Anushlinux
2025-07-07 00:21:17 +05:30
parent 95d1d1e773
commit c7111b4670
5 changed files with 779 additions and 361 deletions

View File

@@ -16,54 +16,7 @@ import {
Download, Download,
Share2 Share2
} from "lucide-react" } from "lucide-react"
import { getStudentApplications } from "../actions"
// Mock data for applications - in real app this would come from database
const mockApplications = [
{
id: 1,
jobTitle: "Software Engineer Intern",
company: "TechCorp Solutions",
status: "pending",
appliedDate: "2024-01-15",
deadline: "2024-02-15",
location: "San Francisco, CA",
salary: "$25/hour",
resume: "Resume_v2.pdf"
},
{
id: 2,
jobTitle: "Data Analyst",
company: "DataFlow Inc",
status: "reviewed",
appliedDate: "2024-01-10",
deadline: "2024-02-10",
location: "New York, NY",
salary: "$30/hour",
resume: "Resume_v2.pdf"
},
{
id: 3,
jobTitle: "Frontend Developer",
company: "WebSolutions",
status: "accepted",
appliedDate: "2024-01-05",
deadline: "2024-02-05",
location: "Remote",
salary: "$28/hour",
resume: "Resume_v2.pdf"
},
{
id: 4,
jobTitle: "Product Manager Intern",
company: "InnovateTech",
status: "rejected",
appliedDate: "2024-01-01",
deadline: "2024-02-01",
location: "Seattle, WA",
salary: "$32/hour",
resume: "Resume_v2.pdf"
}
]
const getStatusConfig = (status: string) => { const getStatusConfig = (status: string) => {
switch (status) { switch (status) {
@@ -100,15 +53,73 @@ const getStatusConfig = (status: string) => {
} }
} }
export default function ApplicationsPage() { export default async function ApplicationsPage() {
const statusConfig = getStatusConfig('pending') // Get real applications data - using student ID 1 for demo
const StatusIcon = statusConfig.icon const { success, applications, error } = await getStudentApplications(1);
// Fallback to mock data if database query fails
const mockApplications = [
{
id: 1,
job: {
title: "Software Engineer Intern",
company: { name: "TechCorp Solutions" },
location: "San Francisco, CA",
salary: "$25/hour",
applicationDeadline: new Date("2024-02-15")
},
resume: { title: "Resume_v2.pdf" },
status: "pending",
createdAt: new Date("2024-01-15")
},
{
id: 2,
job: {
title: "Data Analyst",
company: { name: "DataFlow Inc" },
location: "New York, NY",
salary: "$30/hour",
applicationDeadline: new Date("2024-02-10")
},
resume: { title: "Resume_v2.pdf" },
status: "reviewed",
createdAt: new Date("2024-01-10")
},
{
id: 3,
job: {
title: "Frontend Developer",
company: { name: "WebSolutions" },
location: "Remote",
salary: "$28/hour",
applicationDeadline: new Date("2024-02-05")
},
resume: { title: "Resume_v2.pdf" },
status: "accepted",
createdAt: new Date("2024-01-05")
},
{
id: 4,
job: {
title: "Product Manager Intern",
company: { name: "InnovateTech" },
location: "Seattle, WA",
salary: "$32/hour",
applicationDeadline: new Date("2024-02-01")
},
resume: { title: "Resume_v2.pdf" },
status: "rejected",
createdAt: new Date("2024-01-01")
}
];
const allApplications = success && applications ? applications : mockApplications;
// Calculate stats // Calculate stats
const totalApplications = mockApplications.length const totalApplications = allApplications.length;
const pendingApplications = mockApplications.filter(app => app.status === 'pending').length const pendingApplications = allApplications.filter(app => app.status === 'pending').length;
const acceptedApplications = mockApplications.filter(app => app.status === 'accepted').length const acceptedApplications = allApplications.filter(app => app.status === 'accepted').length;
const rejectedApplications = mockApplications.filter(app => app.status === 'rejected').length const rejectedApplications = allApplications.filter(app => app.status === 'rejected').length;
return ( return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100"> <div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100">
@@ -117,6 +128,12 @@ export default function ApplicationsPage() {
<div className="mb-8"> <div className="mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-2">My Applications</h1> <h1 className="text-4xl font-bold text-gray-900 mb-2">My Applications</h1>
<p className="text-xl text-gray-600">Track your job applications and their status</p> <p className="text-xl text-gray-600">Track your job applications and their status</p>
{!success && error && (
<div className="mt-4 p-3 bg-yellow-100 text-yellow-700 rounded-lg">
<AlertCircle className="w-4 h-4 inline mr-2" />
Using demo data: {error}
</div>
)}
</div> </div>
{/* Stats Cards */} {/* Stats Cards */}
@@ -180,9 +197,9 @@ export default function ApplicationsPage() {
</Button> </Button>
</div> </div>
{mockApplications.map((application) => { {allApplications.map((application) => {
const appStatusConfig = getStatusConfig(application.status) const appStatusConfig = getStatusConfig(application.status);
const AppStatusIcon = appStatusConfig.icon const AppStatusIcon = appStatusConfig.icon;
return ( return (
<Card key={application.id} className="bg-white shadow-sm hover:shadow-lg transition-all duration-200"> <Card key={application.id} className="bg-white shadow-sm hover:shadow-lg transition-all duration-200">
@@ -193,20 +210,20 @@ export default function ApplicationsPage() {
<Building2 className="w-6 h-6 text-white" /> <Building2 className="w-6 h-6 text-white" />
</div> </div>
<div> <div>
<h3 className="text-lg font-semibold text-gray-900 mb-1">{application.jobTitle}</h3> <h3 className="text-lg font-semibold text-gray-900 mb-1">{application.job.title}</h3>
<p className="text-blue-600 font-medium">{application.company}</p> <p className="text-blue-600 font-medium">{application.job.company.name}</p>
<div className="flex items-center gap-4 mt-2 text-sm text-gray-500"> <div className="flex items-center gap-4 mt-2 text-sm text-gray-500">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<Calendar className="w-4 h-4" /> <Calendar className="w-4 h-4" />
Applied: {application.appliedDate} Applied: {application.createdAt.toLocaleDateString()}
</span> </span>
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<MapPin className="w-4 h-4" /> <MapPin className="w-4 h-4" />
{application.location} {application.job.location}
</span> </span>
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<DollarSign className="w-4 h-4" /> <DollarSign className="w-4 h-4" />
{application.salary} {application.job.salary}
</span> </span>
</div> </div>
</div> </div>
@@ -228,11 +245,11 @@ export default function ApplicationsPage() {
<div className="flex items-center gap-4 text-sm text-gray-600"> <div className="flex items-center gap-4 text-sm text-gray-600">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<FileText className="w-4 h-4" /> <FileText className="w-4 h-4" />
Resume: {application.resume} Resume: {application.resume.title}
</span> </span>
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<Calendar className="w-4 h-4" /> <Calendar className="w-4 h-4" />
Deadline: {application.deadline} Deadline: {application.job.applicationDeadline.toLocaleDateString()}
</span> </span>
</div> </div>
<div className="flex gap-2"> <div className="flex gap-2">
@@ -253,7 +270,7 @@ export default function ApplicationsPage() {
</div> </div>
{/* Empty State */} {/* Empty State */}
{mockApplications.length === 0 && ( {allApplications.length === 0 && (
<Card className="bg-white shadow-sm"> <Card className="bg-white shadow-sm">
<CardContent className="p-12 text-center"> <CardContent className="p-12 text-center">
<FileText className="w-16 h-16 text-gray-300 mx-auto mb-4" /> <FileText className="w-16 h-16 text-gray-300 mx-auto mb-4" />

View File

@@ -1,3 +1,6 @@
'use client';
import { useState, useEffect } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from "@workspace/ui/components/card" import { Card, CardContent, CardHeader, CardTitle } from "@workspace/ui/components/card"
import { Button } from "@workspace/ui/components/button" import { Button } from "@workspace/ui/components/button"
import { Badge } from "@workspace/ui/components/badge" import { Badge } from "@workspace/ui/components/badge"
@@ -19,33 +22,41 @@ import {
Users, Users,
Star, Star,
CheckCircle, CheckCircle,
ExternalLink ExternalLink,
Loader2,
AlertCircle
} from "lucide-react" } from "lucide-react"
import { db, jobs, companies } from "@workspace/db" import { getAvailableJobs } from "../actions"
import { eq } from "drizzle-orm" import JobApplicationModal from "../../../components/job-application-modal"
import JobApplicationModal from "../../components/job-application-modal"
async function getJobsData() { interface Job {
try { id: number;
const availableJobs = await db.query.jobs.findMany({ title: string;
where: eq(jobs.active, true), company: {
with: { name: string;
company: true email: string;
} };
}); location: string;
salary: string;
return availableJobs; description: string;
} catch (error) { applicationDeadline: Date;
console.error("Error fetching jobs:", error); minCGPA: number;
return []; active: boolean;
} link?: string;
} }
export default async function JobsPage() { export default function JobsPage() {
const jobs = await getJobsData(); const [jobs, setJobs] = useState<Job[]>([]);
const [filteredJobs, setFilteredJobs] = useState<Job[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [searchTerm, setSearchTerm] = useState('');
const [locationFilter, setLocationFilter] = useState('all');
const [jobTypeFilter, setJobTypeFilter] = useState('all');
const [showLoadMore, setShowLoadMore] = useState(false);
// Mock data for demonstration // Mock data for demonstration
const mockJobs = [ const mockJobs: Job[] = [
{ {
id: 1, id: 1,
title: "Software Engineer Intern", title: "Software Engineer Intern",
@@ -138,7 +149,94 @@ export default async function JobsPage() {
} }
]; ];
const allJobs = [...jobs, ...mockJobs]; useEffect(() => {
loadJobs();
}, []);
const loadJobs = async () => {
try {
const result = await getAvailableJobs();
if (result.success && result.jobs) {
setJobs(result.jobs as any);
setFilteredJobs(result.jobs as any);
} else {
setJobs(mockJobs);
setFilteredJobs(mockJobs);
setError(result.error || 'Using demo data');
}
} catch (err) {
setJobs(mockJobs);
setFilteredJobs(mockJobs);
setError('Failed to load jobs, using demo data');
} finally {
setIsLoading(false);
}
};
useEffect(() => {
filterJobs();
}, [jobs, searchTerm, locationFilter, jobTypeFilter]);
const filterJobs = () => {
let filtered = [...jobs];
// Search filter
if (searchTerm) {
filtered = filtered.filter(job =>
job.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
job.company.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
job.description.toLowerCase().includes(searchTerm.toLowerCase())
);
}
// Location filter
if (locationFilter && locationFilter !== 'all') {
filtered = filtered.filter(job =>
job.location.toLowerCase().includes(locationFilter.toLowerCase())
);
}
// Job type filter (simplified - could be enhanced with job type field)
if (jobTypeFilter && jobTypeFilter !== 'all') {
filtered = filtered.filter(job =>
job.title.toLowerCase().includes(jobTypeFilter.toLowerCase())
);
}
setFilteredJobs(filtered);
setShowLoadMore(filtered.length > 6);
};
const handleSearch = (value: string) => {
setSearchTerm(value);
};
const handleLocationFilter = (value: string) => {
setLocationFilter(value);
};
const handleJobTypeFilter = (value: string) => {
setJobTypeFilter(value);
};
const clearFilters = () => {
setSearchTerm('');
setLocationFilter('all');
setJobTypeFilter('all');
};
const displayedJobs = filteredJobs.slice(0, showLoadMore ? 6 : filteredJobs.length);
if (isLoading) {
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 flex items-center justify-center">
<div className="text-center">
<Loader2 className="w-12 h-12 animate-spin text-blue-600 mx-auto mb-4" />
<p className="text-gray-600">Loading jobs...</p>
</div>
</div>
);
}
return ( return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100"> <div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100">
@@ -147,6 +245,12 @@ export default async function JobsPage() {
<div className="mb-8"> <div className="mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-2">Browse Jobs</h1> <h1 className="text-4xl font-bold text-gray-900 mb-2">Browse Jobs</h1>
<p className="text-xl text-gray-600">Find the perfect opportunity that matches your skills and aspirations</p> <p className="text-xl text-gray-600">Find the perfect opportunity that matches your skills and aspirations</p>
{error && (
<div className="mt-4 p-3 bg-yellow-100 text-yellow-700 rounded-lg">
<AlertCircle className="w-4 h-4 inline mr-2" />
{error}
</div>
)}
</div> </div>
{/* Search and Filter Section */} {/* Search and Filter Section */}
@@ -159,38 +263,53 @@ export default async function JobsPage() {
<Input <Input
placeholder="Search jobs by title, company, or skills..." placeholder="Search jobs by title, company, or skills..."
className="pl-10" className="pl-10"
value={searchTerm}
onChange={(e) => handleSearch(e.target.value)}
/> />
</div> </div>
</div> </div>
<div> <div>
<Select> <Select value={locationFilter} onValueChange={handleLocationFilter}>
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Location" /> <SelectValue placeholder="Location" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="all">All Locations</SelectItem>
<SelectItem value="remote">Remote</SelectItem> <SelectItem value="remote">Remote</SelectItem>
<SelectItem value="san-francisco">San Francisco</SelectItem> <SelectItem value="san francisco">San Francisco</SelectItem>
<SelectItem value="new-york">New York</SelectItem> <SelectItem value="new york">New York</SelectItem>
<SelectItem value="seattle">Seattle</SelectItem> <SelectItem value="seattle">Seattle</SelectItem>
<SelectItem value="austin">Austin</SelectItem> <SelectItem value="austin">Austin</SelectItem>
<SelectItem value="los-angeles">Los Angeles</SelectItem> <SelectItem value="los angeles">Los Angeles</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<div> <div>
<Select> <Select value={jobTypeFilter} onValueChange={handleJobTypeFilter}>
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Job Type" /> <SelectValue placeholder="Job Type" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="internship">Internship</SelectItem> <SelectItem value="all">All Types</SelectItem>
<SelectItem value="full-time">Full Time</SelectItem> <SelectItem value="intern">Internship</SelectItem>
<SelectItem value="part-time">Part Time</SelectItem> <SelectItem value="engineer">Engineering</SelectItem>
<SelectItem value="contract">Contract</SelectItem> <SelectItem value="analyst">Analyst</SelectItem>
<SelectItem value="designer">Design</SelectItem>
<SelectItem value="manager">Management</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
</div> </div>
{(searchTerm || (locationFilter && locationFilter !== 'all') || (jobTypeFilter && jobTypeFilter !== 'all')) && (
<div className="mt-4 flex items-center gap-2">
<Button variant="outline" size="sm" onClick={clearFilters}>
Clear Filters
</Button>
<span className="text-sm text-gray-500">
{filteredJobs.length} of {jobs.length} jobs
</span>
</div>
)}
</CardContent> </CardContent>
</Card> </Card>
@@ -201,7 +320,7 @@ export default async function JobsPage() {
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<p className="text-sm font-medium text-gray-600">Total Jobs</p> <p className="text-sm font-medium text-gray-600">Total Jobs</p>
<p className="text-3xl font-bold text-gray-800">{allJobs.length}</p> <p className="text-3xl font-bold text-gray-800">{jobs.length}</p>
</div> </div>
<Briefcase className="w-8 h-8 text-blue-600" /> <Briefcase className="w-8 h-8 text-blue-600" />
</div> </div>
@@ -214,7 +333,7 @@ export default async function JobsPage() {
<div> <div>
<p className="text-sm font-medium text-gray-600">Active Companies</p> <p className="text-sm font-medium text-gray-600">Active Companies</p>
<p className="text-3xl font-bold text-gray-800"> <p className="text-3xl font-bold text-gray-800">
{new Set(allJobs.map(job => job.company.name)).size} {new Set(jobs.map(job => job.company.name)).size}
</p> </p>
</div> </div>
<Building2 className="w-8 h-8 text-green-600" /> <Building2 className="w-8 h-8 text-green-600" />
@@ -228,7 +347,7 @@ export default async function JobsPage() {
<div> <div>
<p className="text-sm font-medium text-gray-600">Remote Jobs</p> <p className="text-sm font-medium text-gray-600">Remote Jobs</p>
<p className="text-3xl font-bold text-gray-800"> <p className="text-3xl font-bold text-gray-800">
{allJobs.filter(job => job.location.toLowerCase().includes('remote')).length} {jobs.filter(job => job.location.toLowerCase().includes('remote')).length}
</p> </p>
</div> </div>
<Users className="w-8 h-8 text-purple-600" /> <Users className="w-8 h-8 text-purple-600" />
@@ -251,7 +370,7 @@ export default async function JobsPage() {
{/* Jobs Grid */} {/* Jobs Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{allJobs.map((job) => ( {displayedJobs.map((job) => (
<Card key={job.id} className="group hover:shadow-lg transition-all duration-300 border border-gray-200 bg-white"> <Card key={job.id} className="group hover:shadow-lg transition-all duration-300 border border-gray-200 bg-white">
<CardContent className="p-6"> <CardContent className="p-6">
<div className="flex items-start justify-between mb-4"> <div className="flex items-start justify-between mb-4">
@@ -263,8 +382,8 @@ export default async function JobsPage() {
<h3 className="text-lg font-semibold text-gray-900 mb-1 group-hover:text-blue-600 transition-colors"> <h3 className="text-lg font-semibold text-gray-900 mb-1 group-hover:text-blue-600 transition-colors">
{job.title} {job.title}
</h3> </h3>
<p className="text-blue-600 font-medium mb-2">{job.company.name}</p> <p className="text-blue-600 font-medium">{job.company.name}</p>
<div className="flex items-center gap-4 text-sm text-gray-500"> <div className="flex items-center gap-4 mt-2 text-sm text-gray-500">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<MapPin className="w-4 h-4" /> <MapPin className="w-4 h-4" />
{job.location} {job.location}
@@ -332,21 +451,23 @@ export default async function JobsPage() {
</div> </div>
{/* Load More */} {/* Load More */}
{showLoadMore && (
<div className="text-center mt-12"> <div className="text-center mt-12">
<Button size="lg" variant="outline" className="px-8 py-3"> <Button size="lg" variant="outline" className="px-8 py-3">
Load More Jobs Load More Jobs
<ArrowRight className="w-5 h-5 ml-2" /> <ArrowRight className="w-5 h-5 ml-2" />
</Button> </Button>
</div> </div>
)}
{/* Empty State */} {/* Empty State */}
{allJobs.length === 0 && ( {filteredJobs.length === 0 && (
<Card className="bg-white shadow-sm"> <Card className="bg-white shadow-sm">
<CardContent className="p-12 text-center"> <CardContent className="p-12 text-center">
<Briefcase className="w-16 h-16 text-gray-300 mx-auto mb-4" /> <Briefcase className="w-16 h-16 text-gray-300 mx-auto mb-4" />
<h3 className="text-xl font-semibold text-gray-700 mb-2">No jobs found</h3> <h3 className="text-xl font-semibold text-gray-700 mb-2">No jobs found</h3>
<p className="text-gray-500 mb-6">Try adjusting your search criteria or check back later for new opportunities</p> <p className="text-gray-500 mb-6">Try adjusting your search criteria or check back later for new opportunities</p>
<Button className="bg-blue-600 hover:bg-blue-700"> <Button className="bg-blue-600 hover:bg-blue-700" onClick={clearFilters}>
Clear Filters Clear Filters
</Button> </Button>
</CardContent> </CardContent>

View File

@@ -48,6 +48,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
const [isScrolled, setIsScrolled] = useState(false); const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isProfileDropdownOpen, setIsProfileDropdownOpen] = useState(false); const [isProfileDropdownOpen, setIsProfileDropdownOpen] = useState(false);
const [isSearchOpen, setIsSearchOpen] = useState(false);
// Handle scroll effect // Handle scroll effect
useEffect(() => { useEffect(() => {
@@ -63,6 +64,16 @@ export default function MainLayout({ children }: { children: React.ReactNode })
setIsMobileMenuOpen(false); setIsMobileMenuOpen(false);
}, [pathname]); }, [pathname]);
const handleSearchClick = () => {
// Navigate to jobs page with search focus
window.location.href = '/jobs';
};
const handleNotificationClick = () => {
// Navigate to applications page to see status updates
window.location.href = '/applications';
};
return ( return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 font-sans"> <div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 font-sans">
{/* Modern Student Navbar */} {/* Modern Student Navbar */}
@@ -127,6 +138,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
onClick={handleSearchClick}
className="hidden sm:flex items-center gap-2 text-gray-600 hover:text-blue-600 hover:bg-blue-50 transition-all duration-200" className="hidden sm:flex items-center gap-2 text-gray-600 hover:text-blue-600 hover:bg-blue-50 transition-all duration-200"
> >
<Search className="w-4 h-4" /> <Search className="w-4 h-4" />
@@ -137,6 +149,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
onClick={handleNotificationClick}
className="relative text-gray-600 hover:text-blue-600 hover:bg-blue-50 transition-all duration-200" className="relative text-gray-600 hover:text-blue-600 hover:bg-blue-50 transition-all duration-200"
> >
<Bell className="w-4 h-4" /> <Bell className="w-4 h-4" />
@@ -167,6 +180,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
<p className="text-xs text-gray-500">student@college.edu</p> <p className="text-xs text-gray-500">student@college.edu</p>
</div> </div>
<div className="py-1"> <div className="py-1">
<Link href="/profile">
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
@@ -175,6 +189,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
<Settings className="w-4 h-4 mr-2" /> <Settings className="w-4 h-4 mr-2" />
Settings Settings
</Button> </Button>
</Link>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
@@ -247,6 +262,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
</div> </div>
</div> </div>
<div className="px-4 py-2 space-y-1"> <div className="px-4 py-2 space-y-1">
<Link href="/profile">
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
@@ -255,6 +271,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
<Settings className="w-4 h-4 mr-2" /> <Settings className="w-4 h-4 mr-2" />
Settings Settings
</Button> </Button>
</Link>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"

View File

@@ -21,7 +21,8 @@ import {
Filter, Filter,
Bookmark, Bookmark,
Share2, Share2,
Eye Eye,
AlertCircle
} from "lucide-react" } from "lucide-react"
async function getDashboardData() { async function getDashboardData() {
@@ -43,19 +44,22 @@ async function getDashboardData() {
return { return {
companies: companiesWithActiveJobs, companies: companiesWithActiveJobs,
totalStudents: studentCount.length totalStudents: studentCount.length,
success: true
} }
} catch (error) { } catch (error) {
console.error("Database query error:", error) console.error("Database query error:", error)
return { return {
companies: [], companies: [],
totalStudents: 0 totalStudents: 0,
success: false,
error: "Failed to load dashboard data"
} }
} }
} }
export default async function DashboardPage() { export default async function DashboardPage() {
const { companies: data, totalStudents } = await getDashboardData() const { companies: data, totalStudents, success, error } = await getDashboardData()
// Calculate stats // Calculate stats
const totalActiveJobs = data.reduce((acc, company) => acc + company.jobs.filter((job) => job.active).length, 0) const totalActiveJobs = data.reduce((acc, company) => acc + company.jobs.filter((job) => job.active).length, 0)
@@ -78,14 +82,18 @@ export default async function DashboardPage() {
Explore opportunities from top companies and find the perfect role that matches your skills and aspirations Explore opportunities from top companies and find the perfect role that matches your skills and aspirations
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link href="/jobs">
<Button size="lg" className="bg-white text-blue-600 hover:bg-blue-50 px-8 py-3 text-lg font-semibold"> <Button size="lg" className="bg-white text-blue-600 hover:bg-blue-50 px-8 py-3 text-lg font-semibold">
<Search className="w-5 h-5 mr-2" /> <Search className="w-5 h-5 mr-2" />
Browse All Jobs Browse All Jobs
</Button> </Button>
</Link>
<Link href="/applications">
<Button size="lg" variant="outline" className="border-white text-white hover:bg-white/10 px-8 py-3 text-lg font-semibold"> <Button size="lg" variant="outline" className="border-white text-white hover:bg-white/10 px-8 py-3 text-lg font-semibold">
<Bookmark className="w-5 h-5 mr-2" /> <Bookmark className="w-5 h-5 mr-2" />
Saved Jobs My Applications
</Button> </Button>
</Link>
</div> </div>
</div> </div>
</div> </div>
@@ -94,6 +102,12 @@ export default async function DashboardPage() {
{/* Stats Section */} {/* Stats Section */}
<section className="py-16 bg-white"> <section className="py-16 bg-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{!success && error && (
<div className="mb-8 p-4 bg-yellow-100 text-yellow-700 rounded-lg">
<AlertCircle className="w-4 h-4 inline mr-2" />
Using demo data: {error}
</div>
)}
<div className="grid grid-cols-1 md:grid-cols-4 gap-8"> <div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div className="text-center"> <div className="text-center">
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4"> <div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
@@ -137,6 +151,7 @@ export default async function DashboardPage() {
</p> </p>
</div> </div>
{featuredCompanies.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{featuredCompanies.map((company) => ( {featuredCompanies.map((company) => (
<Card key={company.id} className="group hover:shadow-xl transition-all duration-300 overflow-hidden border-0 bg-white"> <Card key={company.id} className="group hover:shadow-xl transition-all duration-300 overflow-hidden border-0 bg-white">
@@ -195,10 +210,12 @@ export default async function DashboardPage() {
</div> </div>
<div className="flex gap-2"> <div className="flex gap-2">
<Link href="/jobs">
<Button className="flex-1 bg-blue-600 hover:bg-blue-700"> <Button className="flex-1 bg-blue-600 hover:bg-blue-700">
View All Jobs View All Jobs
<ArrowRight className="w-4 h-4 ml-2" /> <ArrowRight className="w-4 h-4 ml-2" />
</Button> </Button>
</Link>
<Button variant="outline" size="sm"> <Button variant="outline" size="sm">
<Bookmark className="w-4 h-4" /> <Bookmark className="w-4 h-4" />
</Button> </Button>
@@ -207,6 +224,20 @@ export default async function DashboardPage() {
</Card> </Card>
))} ))}
</div> </div>
) : (
<Card className="bg-white shadow-sm">
<CardContent className="p-12 text-center">
<Building2 className="w-16 h-16 text-gray-300 mx-auto mb-4" />
<h3 className="text-xl font-semibold text-gray-700 mb-2">No featured companies yet</h3>
<p className="text-gray-500 mb-6">Check back later for exciting opportunities</p>
<Link href="/jobs">
<Button className="bg-blue-600 hover:bg-blue-700">
Browse All Jobs
</Button>
</Link>
</CardContent>
</Card>
)}
</div> </div>
</section> </section>
@@ -218,12 +249,15 @@ export default async function DashboardPage() {
<h2 className="text-4xl font-bold text-gray-900 mb-4">Recent Opportunities</h2> <h2 className="text-4xl font-bold text-gray-900 mb-4">Recent Opportunities</h2>
<p className="text-xl text-gray-600">Latest job postings from top companies</p> <p className="text-xl text-gray-600">Latest job postings from top companies</p>
</div> </div>
<Link href="/jobs">
<Button variant="outline" className="hidden md:flex"> <Button variant="outline" className="hidden md:flex">
<Filter className="w-4 h-4 mr-2" /> <Filter className="w-4 h-4 mr-2" />
Filter Jobs Filter Jobs
</Button> </Button>
</Link>
</div> </div>
{recentJobs.length > 0 ? (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{recentJobs.map((job) => ( {recentJobs.map((job) => (
<Card key={job.id} className="group hover:shadow-lg transition-all duration-300 border border-gray-200"> <Card key={job.id} className="group hover:shadow-lg transition-all duration-300 border border-gray-200">
@@ -278,10 +312,12 @@ export default async function DashboardPage() {
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex gap-2"> <div className="flex gap-2">
<Link href="/jobs">
<Button size="sm" className="bg-blue-600 hover:bg-blue-700"> <Button size="sm" className="bg-blue-600 hover:bg-blue-700">
Apply Now Apply Now
<ArrowRight className="w-4 h-4 ml-2" /> <ArrowRight className="w-4 h-4 ml-2" />
</Button> </Button>
</Link>
{job.link && ( {job.link && (
<Button size="sm" variant="outline"> <Button size="sm" variant="outline">
<ExternalLink className="w-4 h-4 mr-2" /> <ExternalLink className="w-4 h-4 mr-2" />
@@ -297,12 +333,28 @@ export default async function DashboardPage() {
</Card> </Card>
))} ))}
</div> </div>
) : (
<Card className="bg-white shadow-sm">
<CardContent className="p-12 text-center">
<Briefcase className="w-16 h-16 text-gray-300 mx-auto mb-4" />
<h3 className="text-xl font-semibold text-gray-700 mb-2">No recent opportunities</h3>
<p className="text-gray-500 mb-6">Check back later for new job postings</p>
<Link href="/jobs">
<Button className="bg-blue-600 hover:bg-blue-700">
Browse All Jobs
</Button>
</Link>
</CardContent>
</Card>
)}
<div className="text-center mt-12"> <div className="text-center mt-12">
<Link href="/jobs">
<Button size="lg" variant="outline" className="px-8 py-3"> <Button size="lg" variant="outline" className="px-8 py-3">
View All Opportunities View All Opportunities
<ArrowRight className="w-5 h-5 ml-2" /> <ArrowRight className="w-5 h-5 ml-2" />
</Button> </Button>
</Link>
</div> </div>
</div> </div>
</section> </section>
@@ -315,13 +367,17 @@ export default async function DashboardPage() {
Join thousands of students who have found their dream jobs through NextPlacement Join thousands of students who have found their dream jobs through NextPlacement
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link href="/profile">
<Button size="lg" className="bg-white text-blue-600 hover:bg-blue-50 px-8 py-3 text-lg font-semibold"> <Button size="lg" className="bg-white text-blue-600 hover:bg-blue-50 px-8 py-3 text-lg font-semibold">
Create Your Profile Create Your Profile
<ArrowRight className="w-5 h-5 ml-2" /> <ArrowRight className="w-5 h-5 ml-2" />
</Button> </Button>
</Link>
<Link href="/jobs">
<Button size="lg" variant="outline" className="border-white text-white hover:bg-white/10 px-8 py-3 text-lg font-semibold"> <Button size="lg" variant="outline" className="border-white text-white hover:bg-white/10 px-8 py-3 text-lg font-semibold">
Learn More Browse Jobs
</Button> </Button>
</Link>
</div> </div>
</div> </div>
</section> </section>

View File

@@ -1,3 +1,6 @@
'use client';
import { useState, useEffect } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from "@workspace/ui/components/card" import { Card, CardContent, CardHeader, CardTitle } from "@workspace/ui/components/card"
import { Button } from "@workspace/ui/components/button" import { Button } from "@workspace/ui/components/button"
import { Badge } from "@workspace/ui/components/badge" import { Badge } from "@workspace/ui/components/badge"
@@ -23,10 +26,12 @@ import {
Download, Download,
Upload, Upload,
CheckCircle, CheckCircle,
AlertCircle AlertCircle,
X
} from "lucide-react" } from "lucide-react"
import { getStudentProfile, updateStudentProfile } from "../actions"
// Mock student data - in real app this would come from database // Mock student data as fallback
const mockStudent = { const mockStudent = {
id: 1, id: 1,
firstName: "John", firstName: "John",
@@ -49,10 +54,82 @@ const mockStudent = {
isDiploma: false, isDiploma: false,
verified: true, verified: true,
markedOut: false, markedOut: false,
profilePicture: null profilePicture: null,
resumes: [
{ id: 1, title: "Resume_v2.pdf", link: "/resumes/resume_v2.pdf" }
]
} }
export default function ProfilePage() { export default function ProfilePage() {
const [student, setStudent] = useState(mockStudent);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [editingSection, setEditingSection] = useState<string | null>(null);
const [editData, setEditData] = useState<any>({});
const [isSaving, setIsSaving] = useState(false);
useEffect(() => {
loadStudentProfile();
}, []);
const loadStudentProfile = async () => {
try {
const result = await getStudentProfile(1); // Using student ID 1 for demo
if (result.success && result.student) {
setStudent(result.student as any);
} else {
setError(result.error || 'Failed to load profile');
}
} catch (err) {
setError('Failed to load profile data');
} finally {
setIsLoading(false);
}
};
const handleEdit = (section: string) => {
setEditingSection(section);
setEditData({});
};
const handleCancel = () => {
setEditingSection(null);
setEditData({});
};
const handleSave = async (section: string) => {
setIsSaving(true);
try {
const result = await updateStudentProfile(student.id, editData);
if (result.success) {
setStudent(prev => ({ ...prev, ...editData }));
setEditingSection(null);
setEditData({});
} else {
setError(result.error || 'Failed to update profile');
}
} catch (err) {
setError('Failed to update profile');
} finally {
setIsSaving(false);
}
};
const handleInputChange = (field: string, value: string) => {
setEditData((prev: any) => ({ ...prev, [field]: value }));
};
if (isLoading) {
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
<p className="text-gray-600">Loading profile...</p>
</div>
</div>
);
}
return ( return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100"> <div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
@@ -60,6 +137,12 @@ export default function ProfilePage() {
<div className="mb-8"> <div className="mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-2">My Profile</h1> <h1 className="text-4xl font-bold text-gray-900 mb-2">My Profile</h1>
<p className="text-xl text-gray-600">Manage your personal information and academic details</p> <p className="text-xl text-gray-600">Manage your personal information and academic details</p>
{error && (
<div className="mt-4 p-3 bg-red-100 text-red-700 rounded-lg">
<AlertCircle className="w-4 h-4 inline mr-2" />
{error}
</div>
)}
</div> </div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
@@ -70,19 +153,19 @@ export default function ProfilePage() {
<div className="text-center mb-6"> <div className="text-center mb-6">
<div className="relative inline-block"> <div className="relative inline-block">
<div className="w-32 h-32 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-full flex items-center justify-center text-white text-4xl font-bold mb-4"> <div className="w-32 h-32 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-full flex items-center justify-center text-white text-4xl font-bold mb-4">
{mockStudent.firstName[0]}{mockStudent.lastName[0]} {student.firstName?.[0] || 'S'}{student.lastName?.[0] || 'T'}
</div> </div>
<Button size="sm" className="absolute bottom-2 right-2 w-8 h-8 rounded-full p-0"> <Button size="sm" className="absolute bottom-2 right-2 w-8 h-8 rounded-full p-0">
<Camera className="w-4 h-4" /> <Camera className="w-4 h-4" />
</Button> </Button>
</div> </div>
<h2 className="text-2xl font-bold text-gray-900 mb-2"> <h2 className="text-2xl font-bold text-gray-900 mb-2">
{mockStudent.firstName} {mockStudent.middleName} {mockStudent.lastName} {student.firstName} {student.middleName} {student.lastName}
</h2> </h2>
<p className="text-gray-600 mb-4">{mockStudent.email}</p> <p className="text-gray-600 mb-4">{student.email}</p>
<div className="flex items-center justify-center gap-2 mb-4"> <div className="flex items-center justify-center gap-2 mb-4">
<Badge className={mockStudent.verified ? "bg-green-100 text-green-700" : "bg-yellow-100 text-yellow-700"}> <Badge className={student.verified ? "bg-green-100 text-green-700" : "bg-yellow-100 text-yellow-700"}>
{mockStudent.verified ? ( {student.verified ? (
<> <>
<CheckCircle className="w-3 h-3 mr-1" /> <CheckCircle className="w-3 h-3 mr-1" />
Verified Verified
@@ -94,14 +177,14 @@ export default function ProfilePage() {
</> </>
)} )}
</Badge> </Badge>
{mockStudent.markedOut && ( {student.markedOut && (
<Badge className="bg-red-100 text-red-700"> <Badge className="bg-red-100 text-red-700">
Marked Out Marked Out
</Badge> </Badge>
)} )}
</div> </div>
<div className="text-sm text-gray-500"> <div className="text-sm text-gray-500">
Roll Number: {mockStudent.rollNumber} Roll Number: {student.rollNumber}
</div> </div>
</div> </div>
@@ -111,19 +194,19 @@ export default function ProfilePage() {
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Academic Year</span> <span className="text-sm text-gray-600">Academic Year</span>
<span className="font-medium">{mockStudent.year}</span> <span className="font-medium">{student.year}</span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Branch</span> <span className="text-sm text-gray-600">Branch</span>
<span className="font-medium">{mockStudent.branch}</span> <span className="font-medium">{student.branch}</span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-sm text-gray-600">SSC Score</span> <span className="text-sm text-gray-600">SSC Score</span>
<span className="font-medium">{mockStudent.ssc}/10</span> <span className="font-medium">{student.ssc}/10</span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-sm text-gray-600">HSC Score</span> <span className="text-sm text-gray-600">HSC Score</span>
<span className="font-medium">{mockStudent.hsc}/10</span> <span className="font-medium">{student.hsc}/10</span>
</div> </div>
</div> </div>
@@ -157,45 +240,114 @@ export default function ProfilePage() {
<User className="w-5 h-5" /> <User className="w-5 h-5" />
Personal Information Personal Information
</CardTitle> </CardTitle>
<Button size="sm" variant="outline"> {editingSection !== 'personal' ? (
<Button size="sm" variant="outline" onClick={() => handleEdit('personal')}>
<Edit className="w-4 h-4 mr-2" /> <Edit className="w-4 h-4 mr-2" />
Edit Edit
</Button> </Button>
) : (
<div className="flex gap-2">
<Button size="sm" onClick={() => handleSave('personal')} disabled={isSaving}>
<Save className="w-4 h-4 mr-2" />
{isSaving ? 'Saving...' : 'Save'}
</Button>
<Button size="sm" variant="outline" onClick={handleCancel}>
<X className="w-4 h-4 mr-2" />
Cancel
</Button>
</div>
)}
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<Label htmlFor="firstName">First Name</Label> <Label htmlFor="firstName">First Name</Label>
<Input id="firstName" value={mockStudent.firstName} readOnly /> {editingSection === 'personal' ? (
<Input
id="firstName"
value={editData.firstName || student.firstName || ''}
onChange={(e) => handleInputChange('firstName', e.target.value)}
/>
) : (
<Input id="firstName" value={student.firstName || ''} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="middleName">Middle Name</Label> <Label htmlFor="middleName">Middle Name</Label>
<Input id="middleName" value={mockStudent.middleName} readOnly /> {editingSection === 'personal' ? (
<Input
id="middleName"
value={editData.middleName || student.middleName || ''}
onChange={(e) => handleInputChange('middleName', e.target.value)}
/>
) : (
<Input id="middleName" value={student.middleName || ''} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="lastName">Last Name</Label> <Label htmlFor="lastName">Last Name</Label>
<Input id="lastName" value={mockStudent.lastName} readOnly /> {editingSection === 'personal' ? (
<Input
id="lastName"
value={editData.lastName || student.lastName || ''}
onChange={(e) => handleInputChange('lastName', e.target.value)}
/>
) : (
<Input id="lastName" value={student.lastName || ''} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="email">Email</Label> <Label htmlFor="email">Email</Label>
<Input id="email" value={mockStudent.email} readOnly /> <Input id="email" value={student.email || ''} readOnly />
</div> </div>
<div> <div>
<Label htmlFor="phone">Phone Number</Label> <Label htmlFor="phone">Phone Number</Label>
<Input id="phone" value={mockStudent.phoneNumber} readOnly /> {editingSection === 'personal' ? (
<Input
id="phone"
value={editData.phoneNumber || student.phoneNumber || ''}
onChange={(e) => handleInputChange('phoneNumber', e.target.value)}
/>
) : (
<Input id="phone" value={student.phoneNumber || ''} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="gender">Gender</Label> <Label htmlFor="gender">Gender</Label>
<Input id="gender" value={mockStudent.gender} readOnly /> {editingSection === 'personal' ? (
<Input
id="gender"
value={editData.gender || student.gender || ''}
onChange={(e) => handleInputChange('gender', e.target.value)}
/>
) : (
<Input id="gender" value={student.gender || ''} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="dob">Date of Birth</Label> <Label htmlFor="dob">Date of Birth</Label>
<Input id="dob" value={mockStudent.dob} readOnly /> {editingSection === 'personal' ? (
<Input
id="dob"
value={editData.dob || student.dob || ''}
onChange={(e) => handleInputChange('dob', e.target.value)}
/>
) : (
<Input id="dob" value={student.dob || ''} readOnly />
)}
</div> </div>
<div className="md:col-span-2"> <div className="md:col-span-2">
<Label htmlFor="address">Address</Label> <Label htmlFor="address">Address</Label>
<Textarea id="address" value={mockStudent.address} readOnly /> {editingSection === 'personal' ? (
<Textarea
id="address"
value={editData.address || student.address || ''}
onChange={(e) => handleInputChange('address', e.target.value)}
/>
) : (
<Textarea id="address" value={student.address || ''} readOnly />
)}
</div> </div>
</div> </div>
</CardContent> </CardContent>
@@ -209,37 +361,90 @@ export default function ProfilePage() {
<GraduationCap className="w-5 h-5" /> <GraduationCap className="w-5 h-5" />
Academic Information Academic Information
</CardTitle> </CardTitle>
<Button size="sm" variant="outline"> {editingSection !== 'academic' ? (
<Button size="sm" variant="outline" onClick={() => handleEdit('academic')}>
<Edit className="w-4 h-4 mr-2" /> <Edit className="w-4 h-4 mr-2" />
Edit Edit
</Button> </Button>
) : (
<div className="flex gap-2">
<Button size="sm" onClick={() => handleSave('academic')} disabled={isSaving}>
<Save className="w-4 h-4 mr-2" />
{isSaving ? 'Saving...' : 'Save'}
</Button>
<Button size="sm" variant="outline" onClick={handleCancel}>
<X className="w-4 h-4 mr-2" />
Cancel
</Button>
</div>
)}
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<Label htmlFor="degree">Degree</Label> <Label htmlFor="degree">Degree</Label>
<Input id="degree" value={mockStudent.degree} readOnly /> {editingSection === 'academic' ? (
<Input
id="degree"
value={editData.degree || student.degree || ''}
onChange={(e) => handleInputChange('degree', e.target.value)}
/>
) : (
<Input id="degree" value={student.degree || ''} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="branch">Branch</Label> <Label htmlFor="branch">Branch</Label>
<Input id="branch" value={mockStudent.branch} readOnly /> {editingSection === 'academic' ? (
<Input
id="branch"
value={editData.branch || student.branch || ''}
onChange={(e) => handleInputChange('branch', e.target.value)}
/>
) : (
<Input id="branch" value={student.branch || ''} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="year">Year</Label> <Label htmlFor="year">Year</Label>
<Input id="year" value={mockStudent.year} readOnly /> {editingSection === 'academic' ? (
<Input
id="year"
value={editData.year || student.year || ''}
onChange={(e) => handleInputChange('year', e.target.value)}
/>
) : (
<Input id="year" value={student.year || ''} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="isDiploma">Diploma Student</Label> <Label htmlFor="isDiploma">Diploma Student</Label>
<Input id="isDiploma" value={mockStudent.isDiploma ? "Yes" : "No"} readOnly /> <Input id="isDiploma" value={student.isDiploma ? "Yes" : "No"} readOnly />
</div> </div>
<div> <div>
<Label htmlFor="ssc">SSC Score</Label> <Label htmlFor="ssc">SSC Score</Label>
<Input id="ssc" value={`${mockStudent.ssc}/10`} readOnly /> {editingSection === 'academic' ? (
<Input
id="ssc"
value={editData.ssc || student.ssc || ''}
onChange={(e) => handleInputChange('ssc', e.target.value)}
/>
) : (
<Input id="ssc" value={`${student.ssc}/10`} readOnly />
)}
</div> </div>
<div> <div>
<Label htmlFor="hsc">HSC Score</Label> <Label htmlFor="hsc">HSC Score</Label>
<Input id="hsc" value={`${mockStudent.hsc}/10`} readOnly /> {editingSection === 'academic' ? (
<Input
id="hsc"
value={editData.hsc || student.hsc || ''}
onChange={(e) => handleInputChange('hsc', e.target.value)}
/>
) : (
<Input id="hsc" value={`${student.hsc}/10`} readOnly />
)}
</div> </div>
</div> </div>
</CardContent> </CardContent>
@@ -261,7 +466,7 @@ export default function ProfilePage() {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{mockStudent.skills.map((skill, index) => ( {student.skills?.map((skill, index) => (
<Badge key={index} variant="secondary" className="bg-blue-100 text-blue-700"> <Badge key={index} variant="secondary" className="bg-blue-100 text-blue-700">
{skill} {skill}
</Badge> </Badge>
@@ -280,11 +485,12 @@ export default function ProfilePage() {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between p-4 border border-gray-200 rounded-lg"> {student.resumes?.map((resume) => (
<div key={resume.id} className="flex items-center justify-between p-4 border border-gray-200 rounded-lg">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<FileText className="w-8 h-8 text-blue-600" /> <FileText className="w-8 h-8 text-blue-600" />
<div> <div>
<h4 className="font-medium">Resume_v2.pdf</h4> <h4 className="font-medium">{resume.title}</h4>
<p className="text-sm text-gray-500">Updated 2 days ago</p> <p className="text-sm text-gray-500">Updated 2 days ago</p>
</div> </div>
</div> </div>
@@ -299,6 +505,7 @@ export default function ProfilePage() {
</Button> </Button>
</div> </div>
</div> </div>
))}
<p className="text-sm text-gray-600"> <p className="text-sm text-gray-600">
Keep your resume updated to increase your chances of getting hired. Keep your resume updated to increase your chances of getting hired.
Make sure it reflects your latest skills and experiences. Make sure it reflects your latest skills and experiences.