Skip to content

Commit

Permalink
Merge branch 'main' into HamburgerMenu
Browse files Browse the repository at this point in the history
  • Loading branch information
TanmayKalra09 authored Oct 28, 2024
2 parents 4ad1276 + 886315f commit 8557a47
Show file tree
Hide file tree
Showing 29 changed files with 2,725 additions and 1,071 deletions.
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
<div align="center">

# 🎨 STATION GUIDE 🖌️

<img src="https://readme-typing-svg.herokuapp.com?color=45ffaa&center=true&vCenter=true&size=40&width=900&height=80&lines=Welcome+to+Station+Guide!"/>
</div>

<div align = "center">
<br>

<table align="center">
<thead align="center">
<tr border: 1px;>
<td><b>🌟 Stars</b></td>
<td><b>🍴 Forks</b></td>
<td><b>🐛 Issues</b></td>
<td><b>🔔 Open PRs</b></td>
<td><b>🔕 Close PRs</b></td>
<td><b>🛠️ Languages</b></td>
<td><b>👥 Contributors</b></td>
</tr>
</thead>
<tbody>
<tr>
<td><img alt="Stars" src="https://img.shields.io/github/stars/dhairyagothi/StationGuide?style=flat&logo=github"/></td>
<td><img alt="Forks" src="https://img.shields.io/github/forks/dhairyagothi/StationGuide?style=flat&logo=github"/></td>
<td><img alt="Issues" src="https://img.shields.io/github/issues/dhairyagothi/StationGuide?style=flat&logo=github"/></td>
<td><img alt="Open Pull Requests" src="https://img.shields.io/github/issues-pr/dhairyagothi/StationGuide?style=flat&logo=github"/></td>
<td><img alt="Close Pull Requests" src="https://img.shields.io/github/issues-pr-closed/dhairyagothi/StationGuide?style=flat&color=critical&logo=github"/></td>
<td><img alt="GitHub language count" src="https://img.shields.io/github/languages/count/dhairyagothi/StationGuide?style=flat&color=green&logo=github"></td>
<td><img alt="GitHub Contributors count" src="https://img.shields.io/github/contributors/dhairyagothi/StationGuide?style=flat&color=blue&logo=github"/></td>
</tr>
</tbody>
</table>
</div>
<br>

<!--Line-->
<img src="https://user-images.githubusercontent.com/74038190/212284100-561aa473-3905-4a80-b561-0d28506553ee.gif" width="900">

# STATION GUIDE : YOUR PLATFORM GUIDE
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

Expand Down
9 changes: 9 additions & 0 deletions backend/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
EMAIL_USER=your_gmail
#your email
EMAIL_USER=your_gmail

# To create a passkey on the phone or computer you’re on:

# 1. Go to https://myaccount.google.com/signinoptions/passkeys.
# 2. Tap Create a passkey and then Continue.(You'll be required to unlock your device.)
# 3. A 16 character passkey is generated which you can use in below.
49 changes: 49 additions & 0 deletions backend/controllers/contactusController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import nodemailer from "nodemailer";
import "dotenv/config";

export const createContactUs = async (req, res) => {
const { mail, subject, message } = req.body;

try {
const transporter = nodemailer.createTransport({
service: "gmail",
host: "smtp.gmail.com",
port: 587,
secure: false,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
tls: {
rejectUnauthorized: false, // Disable strict SSL verification
},
});

const mailOptions = {
from: mail,
to: process.env.EMAIL_USER,
subject: subject,
text: message,
};

// Send mail with defined transport object
transporter.sendMail(mailOptions, (error, mailOptions) => {
if (error) {
console.error("Error occurred: " + error.message);
return;
}
});

res.status(200).json({
status: "success",
message: "Your contact request has been successfully received.",
});
} catch (err) {
console.error(`Error at transport : ${err}`);
res.status(500).json({
status: "error",
message:
"There was an error sending your message. Please try again later.",
});
}
};
106 changes: 106 additions & 0 deletions backend/controllers/submitFeedback.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import nodemailer from 'nodemailer';
import User from '../models/User.js';
import { generateOTP , verifyOTP} from '../utils/otputils.js'; // Import the OTP generation function
import { sendOTPEmail } from '../utils/emailUtils.js'; // Import the email sender utility if separated into a different file

import { hashPassword } from '../utils/authFunctions.js';

// Controller to handle user feedback submission
export const submitFeedback = async (req, res) => {
Expand All @@ -21,3 +26,104 @@ export const submitFeedback = async (req, res) => {
return res.status(error.statusCode || 500).json({ message: error.message || 'An error occurred while submitting feedback' });
}
};

export const sendOTPToEmail = async (req, res) => {
try {
const { email } = req.body;

// Check if email is provided
if (!email) {
return res.status(400).json({ error: 'Email is required' });
}

// Find user by email
const user = await User.findOne({ email });

if (!user) {
return res.status(404).json({ error: 'User does not exist' });
}

// Generate OTP and set expiry (10 minutes from now)
const otp = generateOTP();
const otpExpiry = new Date(Date.now() + 10 * 60 * 1000); // OTP expires in 10 minutes

// Store the OTP and expiry in the user's document
user.otp = otp;
user.otpExpiry = otpExpiry;
await user.save();

// Send OTP to user's email using the utility
await sendOTPEmail(email, otp);

res.status(200).json({ message: 'OTP sent to email' });
} catch (error) {
console.error('Error sending OTP:', error);
return res.status(500).json({ error: error.message || 'Internal Server Error' });
}
};

export const verifyOTPController = async (req, res) => {
try {
const { email, otp } = req.body;

// Check if email and OTP are provided
if (!email || !otp) {
return res.status(400).json({ error: 'Email and OTP are required' });
}

// Find user by email
const user = await User.findOne({ email });

if (!user) {
return res.status(404).json({ error: 'User not found' });
}

// Verify the OTP and check expiration
const isValid = verifyOTP(user, otp);

if (!isValid) {
return res.status(400).json({ error: 'Invalid or expired OTP' });
}

// Clear OTP after successful verification (optional, but recommended)
user.otp = null;
user.otpExpiry = null;
await user.save();

// OTP is valid
res.status(200).json({ message: 'OTP verified successfully' });
} catch (error) {
console.error('Error verifying OTP:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
};

export const resetPassword = async (req, res) => {
try {
const { email, newPassword } = req.body;

// Check if both email and new password are provided
if (!email || !newPassword) {
return res.status(400).json({ error: 'Email and new password are required' });
}

// Find the user by email
const user = await User.findOne({ email });

if (!user) {
return res.status(404).json({ error: 'User not found' });
}

// Hash the new password
const hashedPassword = await hashPassword(newPassword);

// Update the user's password in the database
user.password = hashedPassword;
await user.save();

res.status(200).json({ message: 'Password reset successfully' });
} catch (error) {
console.error('Error resetting password:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
};
62 changes: 62 additions & 0 deletions backend/controllers/trainController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import Train from "../models/Trains.js";


// Create a new train
export const createTrain = async (req, res) => {
try {
const { trainNumber, trainName, nextStation, services, platformDetails, coachDetails } = req.body;


const existingTrain = await Train.findOne({ trainNumber });
if (existingTrain) {
return res.status(400).json({ message: "Train with this number already exists" });
}


const newTrain = new Train({
trainNumber,
trainName,
nextStation,
services,
platformDetails,
coachDetails,
});

const savedTrain = await newTrain.save();

return res.status(201).json({
message: "Train created successfully",
train: savedTrain,
});
} catch (error) {
return res.status(500).json({ message: "Error creating train", error: error.message });
}
};

// Fetch all trains
export const getAllTrains = async (req, res) => {
try {
const trains = await Train.find();
return res.status(200).json(trains);
} catch (error) {
return res.status(500).json({ message: "Error fetching trains", error: error.message });
}
};

// Fetch a single train by train number
export const getTrainByNumber = async (req, res) => {
try {
const { trainNumber } = req.params;

const train = await Train.findOne({ trainNumber });

if (!train) {
return res.status(404).json({ message: "Train not found" });
}

return res.status(200).json(train);
} catch (error) {
return res.status(500).json({ message: "Error fetching train", error: error.message });
}
};

5 changes: 5 additions & 0 deletions backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ connectDB();

import authRoutes from "./routes/authRoutes.js";
import stationRoutes from "./routes/stationRoutes.js";
import trainRoutes from "./routes/trainRoutes.js";
import contactUs from "./routes/contactUsRouter.js";

app.use("/auth", authRoutes);
app.use("/api", authRoutes);
app.use("/station", stationRoutes);
app.use("/train", trainRoutes);
app.use("/contact", contactUs);


app.get("/", (req, res) => {
res.send("Working...");
Expand Down
82 changes: 82 additions & 0 deletions backend/models/Trains.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// train.js
import mongoose from "mongoose";

const Schema = mongoose.Schema;

const trainSchema = new Schema(
{
trainNumber: {
type: Number,
required: true,
unique: true,
trim: true,
},
trainName: {
type: String,
required: true,
trim: true,
},
nextStation: {
type: {
name: {
type: String,
required: true,
trim: true,
},
stationCode: {
type: String,
required: true,
trim: true,
},
arrivalTime: {
type: Date,
required: true,
},
},
required: true,
},
services: {
type: [String], // An array of available services like ["WiFi", "Food", "Lounge"]
required: true,
},
platformDetails: {
platformNumber: {
type: Number,
required: true,
},
boardingTime: {
type: Date,
required: true,
},
},
coachDetails: [
{
coachNumber: {
type: String,
required: true,
trim: true,
},
coachType: {
type: String,
enum: ['Sleeper', 'AC', 'General', 'ChairCar', 'FirstClass'],
required: true,
},
capacity: {
type: Number,
required: true,
},
reservedSeats: {
type: Number,
required: true,
default: 0,
},
},
],
},
{
timestamps: true,
}
);

const Train = mongoose.model("Train", trainSchema);
export default Train;
8 changes: 8 additions & 0 deletions backend/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ const userSchema = new Schema({
type: String,
trim: true,
default: '',
},
otp: {
type: String, // The OTP code
required: false,
},
otpExpiry: {
type: Date, // The OTP expiry timestamp
required: false,
}
}, {
timestamps: true
Expand Down
Loading

0 comments on commit 8557a47

Please sign in to comment.