Skip to content

Commit

Permalink
changes
Browse files Browse the repository at this point in the history
  • Loading branch information
MoonKnight30 committed Oct 28, 2024
1 parent 508cb48 commit e1d9a7c
Show file tree
Hide file tree
Showing 13 changed files with 341 additions and 76 deletions.
4 changes: 3 additions & 1 deletion backend/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
PORT= 4001
MongoDBURI="mongodb+srv://prajwalkoppad30:[email protected]/?retryWrites=true&w=majority&appName=Cluster0"
JWT_SECRET=sleepyboiswinsleeplesscodingsaga
JWT_SECRET=sleepyboiswinsleeplesscodingsaga
EMAIL_USER=[email protected]
EMAIL_PASS=mfst dgwr wtwp jslf
63 changes: 62 additions & 1 deletion backend/controller/leave.controller.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
import LeaveApplication from "../models/leave.model.js";
import User from "../models/user.model.js";
import nodemailer from "nodemailer";
import dotenv from "dotenv";

dotenv.config();

// Configure nodemailer
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS
}
});


const sendEmail = (to, subject, text) => {
const mailOptions = {
from: process.env.EMAIL_USER,
to,
subject,
text
};

console.log('Attempting to send email to:', to);

transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.error('Error sending email:', error);
} else {
console.log('Email sent:', info.response);
}
});
};


// Apply for Leave
export const applyForLeave = async (req, res) => {
Expand Down Expand Up @@ -68,10 +102,11 @@ export const getLeaveStatus = async (req, res) => {
};



// Warden approval
export const updateLeaveStatus = async (req, res) => {
try {
const { applicationId } = req.params; // Get applicationId from request parameters
const { applicationId } = req.params; // Get applicationId from request parameters takes leave id
const { status } = req.body; // Get status from request body

// Validate the status
Expand All @@ -90,6 +125,14 @@ export const updateLeaveStatus = async (req, res) => {
return res.status(404).json({ message: "Leave application not found" });
}

// If status is approved, send email to the user
if (status === 'Approved') {
const user = await User.findById(updatedApplication.userID);
const subject = "Your Leave Application has been Approved";
const text = `Dear ${user.name},\n\nYour leave application for ${updatedApplication.placeOfVisit} has been approved.\n\nBest regards,\nYour College`;
await sendEmail(user.email, subject, text);
}

res.status(200).json({
message: "Leave application status updated successfully.",
application: updatedApplication
Expand Down Expand Up @@ -162,3 +205,21 @@ export const scanLeaveApplication = async (req, res) => {
res.status(500).json({ message: "Internal server error" });
}
};

export const deleteLeaveApplication = async (req, res) => {
try {
const { id } = req.params; // Get applicationId from request parameters
const leaveApplication = await LeaveApplication.findByIdAndDelete(id);

if (!leaveApplication) {
return res.status(404).json({ message: "Leave application not found" });
}

res.status(200).json({
message: "Leave application deleted successfully.",
});
} catch (error) {
console.log("Error:", error.message);
res.status(500).json({ message: "Internal server error" });
}
};
23 changes: 20 additions & 3 deletions backend/controller/outing.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,14 @@ export const getOutingStatus = async (req, res) => {
const { userID } = req.body; // Ensure you're getting userID correctly

// Use findOne to get only one outing request for the user
const outingRequest = await OutingRequest.findOne({ userID }).populate('userID', 'name email'); // Populate user details if needed
const outingRequest = await OutingRequest.findOne({ userID })

if (!outingRequest) {
return res.status(404).json({ message: "No outing applications found." });
return res.status(404).json({ message: "No outing application found." });
}

// Return the single outing request
res.status(200).json({
message: "Outing application retrieved successfully.",
outingRequest
});
} catch (error) {
Expand Down Expand Up @@ -103,4 +102,22 @@ export const scanOutingApplication = async (req, res) => {
console.log("Error:", error.message);
res.status(500).json({ message: "Internal server error" });
}
};

export const deleteOutingRequest = async (req, res) => {
try {
const { applicationId } = req.params; // Get applicationId from request parameters
const outingRequest = await OutingRequest.findByIdAndDelete(applicationId);

if (!outingRequest) {
return res.status(404).json({ message: "outing request not found" });
}

res.status(200).json({
message: "outing request deleted successfully.",
});
} catch (error) {
console.log("Error:", error.message);
res.status(500).json({ message: "Internal server error" });
}
};
2 changes: 1 addition & 1 deletion backend/controller/user.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const login = async (req, res) => {

// If userId is provided, find by userId; otherwise, find by rollNumber
if (userId) {
user = await User.findById(userId, "name rollNumber email phnumber hostel roomNumber course branch year");
user = await User.findById(userId, "leaveApplication outingRequest name rollNumber email phnumber hostel roomNumber course branch year");
} else if (rollNumber) {
user = await User.findOne({ rollNumber }, "name rollNumber email"); // Find by rollNumber
}
Expand Down
9 changes: 9 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"express": "^4.21.1",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.7.3",
"nodemailer": "^6.9.16",
"nodemon": "^3.1.7"
},
"type": "module",
Expand Down
3 changes: 2 additions & 1 deletion backend/route/leave.route.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from "express";
import { applyForLeave, getAllLeaveApplications, getLeaveStatus, updateLeaveExtension, updateLeaveStatus,scanLeaveApplication } from '../controller/leave.controller.js'
import { applyForLeave, getAllLeaveApplications, getLeaveStatus, updateLeaveExtension, updateLeaveStatus,scanLeaveApplication, deleteLeaveApplication } from '../controller/leave.controller.js'



Expand All @@ -11,6 +11,7 @@ router.put("/update/:applicationId", updateLeaveStatus);
router.put("/extension/:applicationId", updateLeaveExtension);
router.get("/all", getAllLeaveApplications);
router.patch('/scan/:applicationId', scanLeaveApplication);
router.delete('/delete/:id', deleteLeaveApplication);


export default router;
5 changes: 3 additions & 2 deletions backend/route/outing.route.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// outing.routes.js

import express from "express";
import { applyForOuting, getOutingStatus, getAllOutings,scanOutingApplication } from "../controller/outing.controller.js";
import { applyForOuting, getOutingStatus, getAllOutings,scanOutingApplication, deleteOutingRequest } from "../controller/outing.controller.js";
import { deleteModel } from "mongoose";

const router = express.Router();

Expand All @@ -14,5 +15,5 @@ router.post('/status', getOutingStatus);
// Route to get all outing applications
router.get('/all', getAllOutings); // New route for getting all outings
router.patch('/scan/:applicationId', scanOutingApplication);

router.delete('/delete/:applicationId', deleteOutingRequest);
export default router;
24 changes: 24 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.3.1",
"react-hot-toast": "^2.4.1",
"react-modal": "^3.16.1",
"react-router-dom": "^6.27.0"
},
"devDependencies": {
Expand Down
48 changes: 41 additions & 7 deletions frontend/src/Components/ApplyLeave/ApplyLeave.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import axios from 'axios';
import './ApplyLeave.css';
import toast, { Toaster } from "react-hot-toast"; // Import toast and Toaster
import toast, { Toaster } from "react-hot-toast";

function ApplyLeave() {
const [formData, setFormData] = useState({
Expand All @@ -17,16 +17,36 @@ function ApplyLeave() {
setFormData({ ...formData, [name]: value });
};

// Get today’s date in YYYY-MM-DD format for validation
const today = new Date().toISOString().split('T')[0];

const handleDateValidation = () => {
const { dateOfLeaving, arrivalDate } = formData;

// Validate that dateOfLeaving is not in the past
if (dateOfLeaving && new Date(dateOfLeaving) < new Date(today)) {
toast.error("Date of leaving cannot be in the past.");
setFormData({ ...formData, dateOfLeaving: '' });
return;
}

// Validate that arrivalDate is not before dateOfLeaving
if (arrivalDate && dateOfLeaving && new Date(arrivalDate) < new Date(dateOfLeaving)) {
toast.error("Arrival date cannot be before the date of leaving.");
setFormData({ ...formData, arrivalDate: '' });
}
};

const handleSubmit = async (e) => {
e.preventDefault();
const token = localStorage.getItem('token');
const userID = localStorage.getItem('userID'); // Get userID from local storage
const userID = localStorage.getItem('userID');
try {
await axios.post('http://localhost:4001/leave/apply', { ...formData, userID }, { // Include userID in the request body
await axios.post('http://localhost:4001/leave/apply', { ...formData, userID }, {
headers: { Authorization: `Bearer ${token}` },
});
toast.success('Leave application submitted!'); // Use toast for success notification
setFormData({ // Reset form data after submission
toast.success('Leave application submitted!');
setFormData({
placeOfVisit: '',
reason: '',
dateOfLeaving: '',
Expand All @@ -35,47 +55,61 @@ function ApplyLeave() {
});
} catch (error) {
console.error(error);
// Use toast for error notification
toast.error(error.response?.data?.message || 'Error applying for leave.');
}
};

return (
<div className="leave-container">
<Toaster /> {/* Add the Toaster component here */}
<Toaster />
<form onSubmit={handleSubmit} className="leave-form">
<h2 className="form-title">Apply for Leave</h2>
<input
name="placeOfVisit"
onChange={handleChange}
value={formData.placeOfVisit}
placeholder="Place of Visit"
required
className="form-input"
/>
<input
name="reason"
onChange={handleChange}
value={formData.reason}
placeholder="Reason"
required
className="form-input"
/>

{/* Label and Date Input for Date of Leaving with Minimum Date */}
<label className="form-label">Date of Leave</label>
<input
type="date"
name="dateOfLeaving"
onChange={handleChange}
onBlur={handleDateValidation}
value={formData.dateOfLeaving}
min={today} // Prevents selecting a past date
required
className="form-input"
/>

{/* Label and Date Input for Arrival Date with Validation */}
<label className="form-label">Arrival Date</label>
<input
type="date"
name="arrivalDate"
onChange={handleChange}
onBlur={handleDateValidation} // Validate on blur
value={formData.arrivalDate}
required
className="form-input"
/>

<input
name="emergencyContact"
onChange={handleChange}
value={formData.emergencyContact}
placeholder="Emergency Contact"
required
className="form-input"
Expand Down
Loading

0 comments on commit e1d9a7c

Please sign in to comment.