Building a Modern Employee Management System with React.js and Django
·
Share on LinkedIn
Share on X
Share on Facebook
Share via Email
Share on WhatsApp
Share on Telegram
Print this page
Copy Link
Share on LinkedIn
Share on X
Share on Facebook
Share on WhatsApp
Share on Telegram
Share via Email
Copy Link
Efficiently managing employees is crucial for any organization's success. From tracking attendance and managing payroll to overseeing performance and ensuring effective communication, an employee management system (EMS) can significantly streamline these tasks.
In this article, we'll walk you through creating a robust and user-friendly Employee Management System using two powerful technologies: React.js for the front end and Django for the back end. React.js, a popular JavaScript library, allows us to build interactive and dynamic user interfaces, while Django, a high-level Python web framework, provides a solid and scalable foundation for the back end.
This guide will cover the essential CRUD (Create, Read, Update, Delete) functionalities, ensuring that our EMS can handle the fundamental operations needed for managing employee data. We'll also focus on creating a robust backend that can support these operations securely and efficiently.
It's important to note that this project is a demo and may not be fully optimized for user-friendliness. However, it serves as a comprehensive starting point for anyone looking to build a more sophisticated EMS tailored to their organization's specific needs.
Whether you're a seasoned developer looking to expand your tech stack or a novice eager to dive into full-stack development, this guide will offer insights and practical steps to help you build an EMS that can handle the complexities of modern workforce management. So, let's roll up our sleeves and start building a system that can make employee management more efficient, transparent, and enjoyable for everyone involved.
Run the development server to ensure everything is set up correctly:
python manage.py runserver
Open your browser and navigate to http://127.0.0.1:8000/. You should see the Django welcome page, indicating that your Django project is up and running.
Now, let's update the Django settings to configure paths, security, installed apps, middleware, templates, and logging. Here's an example of a comprehensive settings.py file for our Employee Management System:
BASE_DIR defines the base directory for the project.
MEDIA_URL and MEDIA_ROOT configure the media files directory for storing employee photos.
Security:
SECRET_KEY is generated and stored securely in a file to ensure it remains consistent across sessions.
Applications:
INSTALLED_APPS lists the installed applications, including rest_framework for building APIs and corsheaders for handling Cross-Origin Resource Sharing.
Middleware:
MIDDLEWARE includes necessary middleware components for handling security, sessions, authentication, and CORS.
URL Configuration:
ROOT_URLCONF points to the URL configuration module for routing.
Templates:
TEMPLATES configuration for rendering HTML templates.
WSGI:
WSGI_APPLICATION specifies the WSGI application used by Django's development server and any WSGI-compatible web server.
Database:
DATABASES configuration using SQLite for simplicity in this demo.
Password Validation:
AUTH_PASSWORD_VALIDATORS ensures password strength and security.
Internationalization:
Settings for language and timezone.
Static Files:
Configuration for serving static files.
Logging:
A simple logging configuration to log debug messages to a file named debug.log.
With the Django project set up, the next step is to create the necessary components for our Employee Management System. We will follow a structured approach to build models, views, serializers, tests, URLs, and admin configurations.
Create serializers for Departments and Employees in EmployeeApp/serializers.py
Serializers in Django REST Framework are used to convert complex data types, such as querysets and model instances, into native Python datatypes that can then be easily rendered into JSON, XML, or other content types. They also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
fields: Specifies the fields to be included in the serialization process.
Define the views for handling API requests in EmployeeApp/views.py
Views in Django REST Framework are used to handle the HTTP requests and return HTTP responses. They contain the logic for the various actions (CRUD operations) that can be performed on the data.
1# EmployeeApp/views.py23from rest_framework import status
4from rest_framework.decorators import api_view
5from rest_framework.response import Response
6from.models import Departments, Employees
7from.serializers import DepartmentSerializer, EmployeeSerializer
8from django.core.files.storage import default_storage
9from django.http import Http404
10import logging
1112logger = logging.getLogger(__name__)131415@api_view(['GET','POST','PUT','DELETE'])16defdepartmentApi(request,id=None):17if request.method =='GET':18ifid:19try:20 department = Departments.objects.get(DepartmentId=id)21 logger.debug(f"GET request for department with id={id}")22except Departments.DoesNotExist:23 logger.error(f"Department with id={id} not found")24raise Http404("Department not found")25 serializer = DepartmentSerializer(department)26return Response(serializer.data)27else:28 departments = Departments.objects.all()29 logger.debug("GET request for all departments")30 serializer = DepartmentSerializer(departments, many=True)31return Response(serializer.data)3233elif request.method =='POST':34 logger.debug(f"POST request with data={request.data}")35 serializer = DepartmentSerializer(data=request.data)36if serializer.is_valid():37 serializer.save()38 logger.debug(f"Department created: {serializer.data}")39return Response(serializer.data, status=status.HTTP_201_CREATED)40 logger.error(f"Validation errors: {serializer.errors}")41return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)4243elif request.method =='PUT':44ifidisNone:45 logger.error("PUT request with id=None")46return Response({"error":"Department id is required for update"}, status=status.HTTP_400_BAD_REQUEST)47try:48 department = Departments.objects.get(DepartmentId=id)49 logger.debug(f"PUT request for department with id={id}")50except Departments.DoesNotExist:51 logger.error(f"Department with id={id} not found")52raise Http404("Department not found")5354 serializer = DepartmentSerializer(department, data=request.data)55if serializer.is_valid():56 serializer.save()57 logger.debug(f"Department updated: {serializer.data}")58return Response(serializer.data)59 logger.error(f"Validation errors: {serializer.errors}")60return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)6162elif request.method =='DELETE':63ifidisNone:64 logger.error("DELETE request with id=None")65return Response({"error":"Department id is required for delete"}, status=status.HTTP_400_BAD_REQUEST)66try:67 department = Departments.objects.get(DepartmentId=id)68 logger.debug(f"DELETE request for department with id={id}")69except Departments.DoesNotExist:70 logger.error(f"Department with id={id} not found")71raise Http404("Department not found")72 department.delete()73 logger.debug(f"Department with id={id} deleted")74return Response(status=status.HTTP_204_NO_CONTENT)757677@api_view(['GET','POST','PUT','DELETE'])78defemployeeApi(request,id=None):79if request.method =='GET':80ifid:81try:82 employee = Employees.objects.get(EmployeeId=id)83 logger.debug(f"GET request for employee with id={id}")84except Employees.DoesNotExist:85 logger.error(f"Employee with id={id} not found")86raise Http404("Employee not found")87 serializer = EmployeeSerializer(employee)88return Response(serializer.data)89else:90 employees = Employees.objects.all()91 logger.debug("GET request for all employees")92 serializer = EmployeeSerializer(employees, many=True)93return Response(serializer.data)9495elif request.method =='POST':96 logger.debug(f"POST request with data={request.data}")97 serializer = EmployeeSerializer(data=request.data)98if serializer.is_valid():99 serializer.save()100 logger.debug(f"Employee created: {serializer.data}")101return Response(serializer.data, status=status.HTTP_201_CREATED)102 logger.error(f"Validation errors: {serializer.errors}")103return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)104105elif request.method =='PUT':106ifidisNone:107 logger.error("PUT request with id=None")108return Response({"error":"Employee id is required for update"}, status=status.HTTP_400_BAD_REQUEST)109try:110 employee = Employees.objects.get(EmployeeId=id)111 logger.debug(f"PUT request for employee with id={id}")112except Employees.DoesNotExist:113 logger.error(f"Employee with id={id} not found")114raise Http404("Employee not found")115116 serializer = EmployeeSerializer(employee, data=request.data)117if serializer.is_valid():118 serializer.save()119 logger.debug(f"Employee updated: {serializer.data}")120return Response(serializer.data)121 logger.error(f"Validation errors: {serializer.errors}")122return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)123124elif request.method =='DELETE':125ifidisNone:126 logger.error("DELETE request with id=None")127return Response({"error":"Employee id is required for delete"}, status=status.HTTP_400_BAD_REQUEST)128try:129 employee = Employees.objects.get(EmployeeId=id)130 logger.debug(f"DELETE request for employee with id={id}")131except Employees.DoesNotExist:132 logger.error(f"Employee with id={id} not found")133raise Http404("Employee not found")134 employee.delete()135 logger.debug(f"Employee with id={id} deleted")136return Response(status=status.HTTP_204_NO_CONTENT)137138# Handles file upload requests. The uploaded file is saved using Django's default storage system, and the file name is returned in the response.139@api_view(['POST'])140defSaveFile(request):141file= request.FILES['file']142 logger.debug(f"File upload request: {file.name}")143 file_name = default_storage.save(file.name,file)144 logger.debug(f"File saved as: {file_name}")145return Response(file_name, status=status.HTTP_200_OK)146
GET: Retrieves a single department/employee if an id is provided, otherwise retrieves all departments.
POST: Creates a new department/employee with the provided data.
PUT: Updates an existing department/employee with the provided id and data.
DELETE: Deletes a department/employee with the provided id.
These views utilize the Django REST Framework to provide a RESTful API for the Employee Management System, allowing clients to perform CRUD operations on the Departments and Employees resources, as well as upload files. The logging statements help in tracking the flow of requests and debugging any issues that arise during API interactions.
The urls.py file in Django is used to map URL patterns to views. It determines what code is executed when a particular URL is accessed.
Maps the URL /department to the departmentApi view. This handles operations that do not require an ID (e.g., list all departments, create a new department).
Maps the URL /department/<id> to the departmentApi view. This handles operations that require an ID (e.g., retrieve, update, delete a specific department).
Serves media files during development by appending the necessary URL patterns to handle media files (e.g., photos).
Tests are used to ensure that the application works as expected. They help verify that the code performs the intended operations and handles various cases appropriately.
setUp: Initializes the test client, creates a sample department, and an employee.
test_get_all_departments: Tests retrieving all departments.
test_get_single_department: Tests retrieving a specific department by ID.
test_create_department: Tests creating a new department.
test_update_department: Tests updating an existing department.
test_delete_department: Tests deleting a department.
test_get_all_employees: Tests retrieving all employees.
test_get_single_employee: Tests retrieving a specific employee by ID.
test_create_employee: Tests creating a new employee.
test_update_employee: Tests updating an existing employee.
test_delete_employee: Tests deleting an employee.
tearDown: Closes the temporary test file after tests are run.
test_save_file: Tests uploading and saving a file.
These tests ensure the integrity and functionality of the API by verifying that the various endpoints perform the expected operations and handle different scenarios correctly.
By following the steps above, you have successfully set up a React application for the Employee Management System.
App.css
1/* Add media queries for responsive navigation */2@media(max-width:768px){3.navbar-nav{4display: none;/* Hide the nav items on small screens */5}67.navbar-nav.show{8display: block;/* Show the nav items when toggled */9}1011.navbar-toggler{12display: block;/* Show the toggle button on small screens */13}14}1516.navbar-toggler{17display: none;/* Hide the toggle button by default */18background-color:#007bff;19border: none;20color:white;21padding:0.5rem1rem;22font-size:1.25rem;23cursor: pointer;24}2526.navbar-toggler:focus{27outline: none;28}2930.dropdown-menu{31display: none;/* Hide dropdown menu by default */32}3334.dropdown.show.dropdown-menu{35display: block;/* Show dropdown menu when toggled */36position: absolute;/* Ensure the dropdown is positioned correctly */37top:100%;/* Align the dropdown menu with the bottom of the toggle button */38left:0;/* Align the dropdown menu to the left */39width:100%;/* Make sure the dropdown menu spans the width of the container */40background-color:white;/* Set background color to white */41box-shadow:04px8pxrgba(0,0,0,0.1);/* Add a subtle shadow for visibility */42}43
index.css
1/* Ensure the background color covers the entire page */2body,3html{4height:100%;5margin:0;6background-color:#f9f9f9;7overflow: hidden;8}910@media(max-width:767px){11.table th{12font-size:12px;13padding:5px;14}15.table td{16font-size:12px;17padding:5px;18}19}2021/* Responsive table */22.table-responsive{23display: block;24width:100%;25overflow-x: auto;26-webkit-overflow-scrolling: touch;27}2829.table{30width:100%;31max-width:100%;32margin-bottom:1rem;33background-color:transparent;34}3536@media(max-width:768px){37.table thead{38display: none;39}4041.table,42.table tbody,43.table tr,44.table td{45display: block;46width:100%;47}4849.table tr{50margin-bottom:15px;51}5253.table td{54text-align: right;55padding-left:50%;56position: relative;57}5859.table td::before{60content:attr(data-label);61position: absolute;62left:0;63width:50%;64padding-left:15px;65font-weight: bold;66text-align: left;67}68}6970/* Home container to center content */71.home-container{72display: flex;73flex-direction: column;74align-items: center;75justify-content: center;76min-height:75vh;77padding:20px;78background-color:#f9f9f9;79}8081.home-content{82max-width:600px;83margin:020px;/* Ensure some margin for smaller screens */84}8586/* Centered text and margins */87.text-center{88text-align: center;89}9091.my-4{92margin:2rem0;93}9495/* Responsive home content styling */96.home-content{97font-size:16px;98line-height:1.6;99max-width:600px;100width:100%;101padding:20px;102background-color:white;103border-radius:8px;104box-shadow:02px4pxrgba(0,0,0,0.1);105text-align: center;/* Center align text */106}107108.home-content p{109margin-bottom:1rem;110}111112/* Quick links styling */113.quick-links{114list-style-type: none;115padding:0;116display: flex;117justify-content: center;118}119120.quick-links li{121margin:010px;122}123124.quick-links li a{125color:#007bff;126text-decoration: none;127}128129.quick-links li a:hover{130text-decoration: underline;131}132133/* Responsive design for smaller screens */134@media(max-width:600px){135.quick-links{136flex-direction: column;137}138139.quick-links li{140margin:10px0;141}142}143
The App.js file is the main entry point of the React application. It sets up the router, navigation, and routes for the different components of the Employee Management System.
1import"./App.css";2importHomefrom"./Home";3importDepartmentfrom"./Department";4import{Employee}from"./Employee";5import{ useState }from"react";6import{7BrowserRouterasRouter,8Route,Routes,9NavLink,10}from"react-router-dom";1112functionApp(){13const[isNavOpen, setIsNavOpen]=useState(false);1415consttoggleNav=()=>{16setIsNavOpen(!isNavOpen);17};1819return(20<Router>21<divclassName="App container">22<h3className="text-center my-4">23 Welcome to Employee Management System
24</h3>2526<navclassName="navbar navbar-expand-sm bg-light navbar-light">27<buttonclassName="navbar-toggler"onClick={toggleNav}>28 ☰
29</button>30<divclassName={`navbar-nav ${isNavOpen ?"show":""}`}>31<divclassName="dropdown">32<button33className="btn btn-light btn-outline-primary dropdown-toggle"34onClick={toggleNav}35>36 Menu
37</button>38<divclassName={`dropdown-menu ${isNavOpen ?"show":""}`}>39<NavLink40className="dropdown-item"41to="/"42onClick={()=>setIsNavOpen(false)}43>44 Home
45</NavLink>46<NavLink47className="dropdown-item"48to="/department"49onClick={()=>setIsNavOpen(false)}50>51 Department
52</NavLink>53<NavLink54className="dropdown-item"55to="/employee"56onClick={()=>setIsNavOpen(false)}57>58 Employee
59</NavLink>60</div>61</div>62</div>63</nav>6465<Routes>66<Routepath="/"element={<Home/>}/>67<Routepath="/department"element={<Department/>}/>68<Routepath="/employee"element={<Employee/>}/>69</Routes>70</div>71</Router>72);73}7475exportdefaultApp;76
A collapsible navigation menu is created with NavLink components for Home, Department, and Employee pages.
The dropdown class and show class are conditionally applied based on isNavOpen state to handle the menu visibility.
The Home.js file represents the Home page of the application. It provides a brief overview and quick links to navigate to other sections.
1importReactfrom"react";2import"./index.css";34constHome=()=>{5return(6<divclassName="home-container">7<divclassName="home-content">8<p>9 This is the home page of our React application. Here, you can find
10 various resources and links to other sections of the app. Explore the
11 navigation menu to visit the Departments and Employees sections.
12</p>13<p>14 Our application is built using React, a popular JavaScript library for
15 building user interfaces. We have implemented various features to
16 provide a seamless experience for managing departments and employees.
17</p>18<p>Below are some quick links to get you started:</p>19<ulclassName="quick-links">20<li>21<ahref="/">Home</a>22</li>23<li>24<ahref="/department">Departments</a>25</li>26<li>27<ahref="/employee">Employees</a>28</li>29</ul>30</div>31</div>32);33};3435exportdefaultHome;36
API_URL: This property is a string "http://127.0.0.1:8000/". It represents the base URL for an API endpoint. In this case, it points to a local development server running on 127.0.0.1 (localhost) at port 8000. This URL is typically used to communicate with a backend server to perform operations like fetching data, updating data, etc.
PHOTO_URL: This property is also a string "http://127.0.0.1:8000/Photos/". It represents the base URL for accessing photos or images served by the same local development server. This URL is used to construct the complete path to fetch or display images stored on the server.
Both Department and Employee components use the DraggableRow component to enable drag-and-drop functionality for table rows.
State Management: Uses React's useState to manage employee data, modal states, and image uploads.
CRUD Operations: Uses fetch API for Create, Read, Update, and Delete operations.
Drag and Drop: Uses react-dnd to enable drag-and-drop functionality for employee rows.
Image Upload: Handles image uploads for employee photos.
These components are designed to be modular and reusable, focusing on managing data with CRUD operations and enhancing user experience with sorting, filtering, and drag-and-drop features.
Remember, adaptability and clarity in your codebase not only benefit your current development efforts but also pave the way for smoother collaboration and growth in your software projects.