import React, { useState } from "react";
const initialVacancies = {
Farmworker: { employed: 10, vacancies: 5 },
"Packing-worker": { employed: 8, vacancies: 4 },
};
const users = {
Group71HR: { password: "Organic", department: "HR" },
Group71IT: { password: "Organic", department: "IT" },
Group71OP: { password: "Organic", department: "Operations" },
Group71FN: { password: "Organic", department: "Finance" },
};
const HR_MANAGER_PASSWORD = "Harvest";
export default function DepartmentApp() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loggedIn, setLoggedIn] = useState(false);
const [department, setDepartment] = useState("");
const [loginError, setLoginError] = useState("");
const [vacancies, setVacancies] = useState(initialVacancies);
const [employeeList, setEmployeeList] = useState([]);
const [selectedType, setSelectedType] = useState("");
const [wageRate, setWageRate] = useState("Minimum");
const [customRate, setCustomRate] = useState("");
const [uploadedFile, setUploadedFile] = useState(null);
const [statusMessage, setStatusMessage] = useState("");
const [authOnboard, setAuthOnboard] = useState("");
const [termEmpId, setTermEmpId] = useState("");
const [termReason, setTermReason] = useState("");
const [authHR, setAuthHR] = useState("");
const [terminationStatus, setTerminationStatus] = useState("");
const login = () => {
if (users[username] && users[username].password === password) {
setDepartment(users[username].department);
setLoggedIn(true);
setLoginError("");
} else {
setLoginError("Incorrect username or password.");
}
};
const onboardEmployee = () => {
// Validate inputs
if (!selectedType || !uploadedFile || authOnboard !== HR_MANAGER_PASSWORD) {
setStatusMessage("❌ Submission unsuccessful: Please complete all fields and enter correct HR Manager password.");
return;
}
// Validate file size (e.g., max 5MB)
if (uploadedFile.size > 5 * 1024 * 1024) {
setStatusMessage("❌ File too large. Please upload a file smaller than 5MB.");
return;
}
if (vacancies[selectedType].vacancies <= 0) {
setStatusMessage("❌ No vacancies available for this worker type.");
return;
}
const newEmpId = Math.floor(100000000 + Math.random() * 900000000);
const finalWage = wageRate === "Other" ? customRate : wageRate;
const newEmployee = {
id: newEmpId,
type: selectedType,
wage: finalWage,
file: uploadedFile.name, // Store file name for display
};
setEmployeeList([...employeeList, newEmployee]);
setVacancies({
...vacancies,
[selectedType]: {
employed: vacancies[selectedType].employed + 1,
vacancies: vacancies[selectedType].vacancies - 1,
},
});
setStatusMessage(`✅ Employee ${newEmpId} onboarded successfully.`);
// Reset form
setSelectedType("");
setWageRate("Minimum");
setCustomRate("");
setUploadedFile(null);
setAuthOnboard("");
document.getElementById("workerType").value = ""; // Reset select
document.getElementById("wageRate").value = "Minimum"; // Reset select
document.getElementById("fileInput").value = null; // Reset file input
};
const terminateEmployee = () => {
const id = Number(termEmpId);
if (!id || !termReason || authHR !== HR_MANAGER_PASSWORD) {
setTerminationStatus("❌ Submission unsuccessful: Please fill all termination fields and enter correct HR Manager password.");
return;
}
const employeeIndex = employeeList.findIndex((emp) => emp.id === id);
if (employeeIndex === -1) {
setTerminationStatus("⚠️ Employee not found.");
return;
}
const employee = employeeList[employeeIndex];
setEmployeeList(employeeList.filter((emp) => emp.id !== id));
setVacancies({
...vacancies,
[employee.type]: {
employed: vacancies[employee.type].employed - 1,
vacancies: vacancies[employee.type].vacancies + 1,
},
});
setTerminationStatus(`✅ Employee ${id} terminated successfully.`);
// Reset form
setTermEmpId("");
setTermReason("");
setAuthHR("");
};
if (!loggedIn) {
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
<div className="bg-white p-6 rounded-lg shadow-md w-full max-w-sm">
<h2 className="text-2xl font-bold mb-4 text-center">Login</h2>
<input
className="w-full p-2 mb-4 border rounded"
placeholder="Username"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<input
className="w-full p-2 mb-4 border rounded"
placeholder="Password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button
className="w-full p-2 bg-blue-500 text-white rounded hover:bg-blue-600"
onClick={login}
>
Login
</button>
{loginError && <p className="mt-2 text-red-500">{loginError}</p>}
</div>
</div>
);
}
return (
<div className="p-6 max-w-4xl mx-auto bg-gray-50 min-h-screen">
<h2 className="text-2xl font-bold mb-4">
Welcome, {department} Department
</h2>
{department === "HR" && (
<>
<h3 className="text-xl font-bold mt-6">Dashboard</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{Object.entries(vacancies).map(([type, data]) => (
<div key={type} className="p-4 bg-white rounded shadow">
<strong>{type}:</strong> {data.employed} employed,{" "}
{data.vacancies} vacancies
</div>
))}
</div>
<div className="mt-8">
<h3 className="text-lg font-bold">Employee Onboarding</h3>
<div className="bg-white p-4 rounded shadow">
<select
id="workerType"
className="w-full p-2 mb-4 border rounded"
value={selectedType}
onChange={(e) => setSelectedType(e.target.value)}
>
<option value="" disabled>
Select worker type
</option>
<option value="Farmworker">Farmworker</option>
<option value="Packing-worker">Packing-worker</option>
</select>
<select
id="wageRate"
className="w-full p-2 mb-4 border rounded"
value={wageRate}
onChange={(e) => setWageRate(e.target.value)}
>
<option value="Minimum">Minimum wage rate</option>
<option value="Other">Other</option>
</select>
{wageRate === "Other" && (
<input
className="w-full p-2 mb-4 border rounded"
placeholder="Enter custom rate"
value={customRate}
onChange={(e) => setCustomRate(e.target.value)}
/>
)}
<input
id="fileInput"
className="w-full p-2 mb-4"
type="file"
onChange={(e) => setUploadedFile(e.target.files[0])}
/>
<input
className="w-full p-2 mb-4 border rounded"
placeholder="HR Manager Password"
type="password"
value={authOnboard}
onChange={(e) => setAuthOnboard(e.target.value)}
/>
<button
className="w-full p-2 bg-green-500 text-white rounded hover:bg-green-600"
onClick={onboardEmployee}
>
Submit
</button>
{statusMessage && (
<p className="mt-2 text-sm">{statusMessage}</p>
)}
</div>
</div>
<div className="mt-8">
<h3 className="text-lg font-bold">Employee List</h3>
{employeeList.length === 0 ? (
<p>No employees onboarded yet.</p>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{employeeList.map((emp) => (
<div key={emp.id} className="p-4 bg-white rounded shadow">
<p>
<strong>ID:</strong> {emp.id}
</p>
<p>
<strong>Type:</strong> {emp.type}
</p>
<p>
<strong>Wage:</strong> {emp.wage}
</p>
<p>
<strong>File:</strong> {emp.file}
</p>
</div>
))}
</div>
)}
</div>
<div className="mt-8">
<h3 className="text-lg font-bold">Terminate Employee</h3>
<div className="bg-white p-4 rounded shadow">
<input
className="w-full p-2 mb-4 border rounded"
placeholder="Enter employee ID"
value={termEmpId}
onChange={(e) => setTermEmpId(e.target.value)}
/>
<input
className="w-full p-2 mb-4 border rounded"
placeholder="Reason for termination"
value={termReason}
onChange={(e) => setTermReason(e.target.value)}
/>
<input
className="w-full p-2 mb-4 border rounded"
placeholder="HR Manager Password"
type="password"
value={authHR}
onChange={(e) => setAuthHR(e.target.value)}
/>
<button
className="w-full p-2 bg-red-500 text-white rounded hover:bg-red-600"
onClick={terminateEmployee}
>
Submit Termination
</button>
{terminationStatus && (
<p className="mt-2 text-sm">{terminationStatus}</p>
)}
</div>
</div>
</>
)}
</div>
);
}
This React application creates an HR management system for an agricultural business. Key features include:
The app uses React hooks for state management and implements responsive design with Tailwind CSS classes.