From dc7e35943c86d5961a2c51c6efd4feec1363ddf5 Mon Sep 17 00:00:00 2001 From: Smartnewb Date: Thu, 6 Mar 2025 16:17:11 +0000 Subject: [PATCH] second commit --- src/app/company/dashboard/page.tsx | 6 + src/app/page.tsx | 4 +- src/components/company/CandidateResults.tsx | 355 ++++++++++++++++ src/components/company/CompanyProfile.tsx | 388 ++++++++++++++++++ src/components/company/Dashboard.tsx | 65 +++ src/components/company/DashboardOverview.tsx | 170 ++++++++ src/components/company/RecentActivityList.tsx | 183 +++++++++ src/components/company/Sidebar.tsx | 144 +++++++ src/components/company/TestManagement.tsx | 298 ++++++++++++++ .../company/charts/TestScoreChart.tsx | 52 +++ .../company/charts/TestStatusChart.tsx | 52 +++ src/components/dashboard/Sidebar.tsx | 2 + 12 files changed, 1718 insertions(+), 1 deletion(-) create mode 100644 src/app/company/dashboard/page.tsx create mode 100644 src/components/company/CandidateResults.tsx create mode 100644 src/components/company/CompanyProfile.tsx create mode 100644 src/components/company/Dashboard.tsx create mode 100644 src/components/company/DashboardOverview.tsx create mode 100644 src/components/company/RecentActivityList.tsx create mode 100644 src/components/company/Sidebar.tsx create mode 100644 src/components/company/TestManagement.tsx create mode 100644 src/components/company/charts/TestScoreChart.tsx create mode 100644 src/components/company/charts/TestStatusChart.tsx diff --git a/src/app/company/dashboard/page.tsx b/src/app/company/dashboard/page.tsx new file mode 100644 index 0000000..01ca02f --- /dev/null +++ b/src/app/company/dashboard/page.tsx @@ -0,0 +1,6 @@ +import React from "react"; +import CompanyDashboard from "@/components/company/Dashboard"; + +export default function CompanyDashboardPage() { + return ; +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 02c5980..3e4caf7 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,9 @@ +import CompanyDashboard from "@/components/company/Dashboard"; export default function Page() { return ( -
+
+
); } diff --git a/src/components/company/CandidateResults.tsx b/src/components/company/CandidateResults.tsx new file mode 100644 index 0000000..cd37668 --- /dev/null +++ b/src/components/company/CandidateResults.tsx @@ -0,0 +1,355 @@ +import React, { useState } from "react"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { Badge } from "@/components/ui/badge"; +import { + Search, + Filter, + MoreHorizontal, + FileText, + Mail, + CheckCircle, + Clock, + AlertCircle, + ThumbsUp, + ThumbsDown, + HelpCircle, +} from "lucide-react"; + +interface Candidate { + id: string; + name: string; + email: string; + testTitle: string; + score: number; + submittedAt: string; + status: "Completed" | "In Progress" | "Failed"; + suitability: "Suitable" | "Pending" | "Not Suitable"; +} + +const CandidateResults = () => { + const [searchQuery, setSearchQuery] = useState(""); + const [statusFilter, setStatusFilter] = useState(null); + const [suitabilityFilter, setSuitabilityFilter] = useState( + null, + ); + + // Mock candidate data + const candidates: Candidate[] = [ + { + id: "1", + name: "Kim Min-ji", + email: "minji.kim@example.com", + testTitle: "JavaScript Fundamentals", + score: 92, + submittedAt: "2023-11-25 14:30", + status: "Completed", + suitability: "Suitable", + }, + { + id: "2", + name: "Park Ji-hoon", + email: "jihoon.park@example.com", + testTitle: "React Component Architecture", + score: 78, + submittedAt: "2023-11-24 10:15", + status: "Completed", + suitability: "Suitable", + }, + { + id: "3", + name: "Lee Soo-jin", + email: "soojin.lee@example.com", + testTitle: "Advanced Algorithms", + score: 0, + submittedAt: "2023-11-26 09:45", + status: "In Progress", + suitability: "Pending", + }, + { + id: "4", + name: "Choi Tae-woo", + email: "taewoo.choi@example.com", + testTitle: "JavaScript Fundamentals", + score: 65, + submittedAt: "2023-11-23 16:20", + status: "Failed", + suitability: "Not Suitable", + }, + { + id: "5", + name: "Kang Hye-jin", + email: "hyejin.kang@example.com", + testTitle: "Database Design", + score: 88, + submittedAt: "2023-12-01 11:30", + status: "Completed", + suitability: "Suitable", + }, + { + id: "6", + name: "Yoon Jae-hyun", + email: "jaehyun.yoon@example.com", + testTitle: "API Development with Node.js", + score: 72, + submittedAt: "2023-12-02 13:45", + status: "Completed", + suitability: "Pending", + }, + ]; + + // Filter candidates based on search query and filters + const filteredCandidates = candidates.filter((candidate) => { + const matchesSearch = + candidate.name.toLowerCase().includes(searchQuery.toLowerCase()) || + candidate.email.toLowerCase().includes(searchQuery.toLowerCase()) || + candidate.testTitle.toLowerCase().includes(searchQuery.toLowerCase()); + + const matchesStatus = !statusFilter || candidate.status === statusFilter; + const matchesSuitability = + !suitabilityFilter || candidate.suitability === suitabilityFilter; + + return matchesSearch && matchesStatus && matchesSuitability; + }); + + const getStatusIcon = (status: string) => { + switch (status) { + case "Completed": + return ; + case "In Progress": + return ; + case "Failed": + return ; + default: + return null; + } + }; + + const getStatusColor = (status: string) => { + switch (status) { + case "Completed": + return "bg-green-100 text-green-800"; + case "In Progress": + return "bg-blue-100 text-blue-800"; + case "Failed": + return "bg-red-100 text-red-800"; + default: + return ""; + } + }; + + const getSuitabilityIcon = (suitability: string) => { + switch (suitability) { + case "Suitable": + return ; + case "Not Suitable": + return ; + case "Pending": + return ; + default: + return null; + } + }; + + const getSuitabilityColor = (suitability: string) => { + switch (suitability) { + case "Suitable": + return "bg-green-100 text-green-800"; + case "Not Suitable": + return "bg-red-100 text-red-800"; + case "Pending": + return "bg-amber-100 text-amber-800"; + default: + return ""; + } + }; + + return ( +
+
+

Candidate Results

+
+ + + + Candidate Evaluations + + Review test results and candidate performance + + + + +
+
+ + setSearchQuery(e.target.value)} + /> +
+ + + + + + setStatusFilter(null)}> + All Statuses + + setStatusFilter("Completed")}> + Completed + + setStatusFilter("In Progress")} + > + In Progress + + setStatusFilter("Failed")}> + Failed + + + + + + + + + setSuitabilityFilter(null)}> + All Suitability + + setSuitabilityFilter("Suitable")} + > + Suitable + + setSuitabilityFilter("Pending")} + > + Pending + + setSuitabilityFilter("Not Suitable")} + > + Not Suitable + + + +
+ +
+ + + + Candidate + Test + Score + Submitted + Status + Suitability + Actions + + + + {filteredCandidates.map((candidate) => ( + + +
+
{candidate.name}
+
+ {candidate.email} +
+
+
+ {candidate.testTitle} + + {candidate.status === "In Progress" + ? "-" + : `${candidate.score}%`} + + {candidate.submittedAt} + + + {getStatusIcon(candidate.status)} + {candidate.status} + + + + + {getSuitabilityIcon(candidate.suitability)} + {candidate.suitability} + + + + + + + + + + View Report + + + Contact Candidate + + + + +
+ ))} +
+
+
+
+ + +
+ Showing {filteredCandidates.length} of {candidates.length}{" "} + candidates +
+ +
+
+
+ ); +}; + +export default CandidateResults; diff --git a/src/components/company/CompanyProfile.tsx b/src/components/company/CompanyProfile.tsx new file mode 100644 index 0000000..05027bf --- /dev/null +++ b/src/components/company/CompanyProfile.tsx @@ -0,0 +1,388 @@ +import React, { useState } from "react"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Label } from "@/components/ui/label"; +import { Badge } from "@/components/ui/badge"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { Separator } from "@/components/ui/separator"; +import { + Building2, + Users, + Mail, + Globe, + MapPin, + Phone, + Github, + Trello, + Plus, + X, + Save, + Upload, +} from "lucide-react"; + +interface CompanyProfileProps { + companyData: { + name: string; + logo?: string; + industry: string; + employeeCount: number; + email: string; + techStack: string[]; + githubConnected: boolean; + jiraConnected: boolean; + website?: string; + location?: string; + phone?: string; + description?: string; + }; +} + +const CompanyProfile = ({ companyData }: CompanyProfileProps) => { + const [editMode, setEditMode] = useState(false); + const [company, setCompany] = useState(companyData); + const [newTech, setNewTech] = useState(""); + + const handleAddTech = () => { + if (newTech.trim() && !company.techStack.includes(newTech.trim())) { + setCompany({ + ...company, + techStack: [...company.techStack, newTech.trim()], + }); + setNewTech(""); + } + }; + + const handleRemoveTech = (tech: string) => { + setCompany({ + ...company, + techStack: company.techStack.filter((t) => t !== tech), + }); + }; + + const handleInputChange = ( + e: React.ChangeEvent, + ) => { + const { name, value } = e.target; + setCompany({ + ...company, + [name]: value, + }); + }; + + const handleSave = () => { + // Here you would typically make an API call to save the data + console.log("Saving company profile:", company); + setEditMode(false); + }; + + return ( +
+
+

Company Profile

+ {!editMode ? ( + + ) : ( +
+ + +
+ )} +
+ +
+ {/* Company Basic Info */} + + + Company Information + Your company's basic information + + +
+ + {company.logo ? ( + + ) : ( + + {company.name.slice(0, 2).toUpperCase()} + + )} + + {editMode && ( + + )} +
+ +
+
+
+ + Company Name +
+ {editMode ? ( + + ) : ( +

{company.name}

+ )} +
+ +
+
+ + Email +
+ {editMode ? ( + + ) : ( +

{company.email}

+ )} +
+ +
+
+ + Industry +
+ {editMode ? ( + + ) : ( +

{company.industry}

+ )} +
+ +
+
+ + Employee Count +
+ {editMode ? ( + + ) : ( +

{company.employeeCount}

+ )} +
+ + {editMode && ( + <> +
+
+ + Website +
+ +
+ +
+
+ + Location +
+ +
+ +
+
+ + Phone +
+ +
+ + )} + + {!editMode && ( + <> + {company.website && ( +
+
+ + Website +
+

{company.website}

+
+ )} + + {company.location && ( +
+
+ + Location +
+

{company.location}

+
+ )} + + {company.phone && ( +
+
+ + Phone +
+

{company.phone}

+
+ )} + + )} +
+
+
+ + {/* Company Details */} + + + Company Details + + Additional information about your company + + + +
+
+ + {editMode ? ( +