Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lecture-pulse/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
VITE_EMAILJS_SERVICE_ID=your_emailjs_service_id
VITE_EMAILJS_TEMPLATE_ID=your_emailjs_template_id
VITE_EMAILJS_PUBLIC_KEY=your_emailjs_public_key
10 changes: 10 additions & 0 deletions lecture-pulse/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 lecture-pulse/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@emailjs/browser": "^4.4.1",
"@radix-ui/react-slot": "^1.2.4",
"@tailwindcss/vite": "^4.1.18",
"class-variance-authority": "^0.7.1",
Expand Down
45 changes: 39 additions & 6 deletions lecture-pulse/src/context/AuthContext.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createContext, useContext, useState } from "react";
import emailjs from "@emailjs/browser";
import { getCurrentTeacher } from "@/utils/storage";

const AuthContext = createContext();
Expand Down Expand Up @@ -95,20 +96,52 @@ export function AuthProvider({ children }) {

const OTP_EXPIRY_TIME = 5 * 60 * 1000; // 5 minutes

const sendOTP = (email) => {
const sendOTP = async (email) => {
const emailJsServiceId = import.meta.env.VITE_EMAILJS_SERVICE_ID;
const emailJsTemplateId = import.meta.env.VITE_EMAILJS_TEMPLATE_ID;
const emailJsPublicKey = import.meta.env.VITE_EMAILJS_PUBLIC_KEY;

if (!emailJsServiceId || !emailJsTemplateId || !emailJsPublicKey) {
return {
success: false,
message: "Email service is not configured. Please add the EmailJS environment variables.",
};
}

const otp = Math.floor(100000 + Math.random() * 900000).toString();

const otpData = {
otp,
timestamp: Date.now(),
};

localStorage.setItem(
`lecturePulse_otp_${email}`,
JSON.stringify(otpData)
);
try {
await emailjs.send(
emailJsServiceId,
emailJsTemplateId,
{
to_email: email,
otp_code: otp,
app_name: "LecturePulse",
},
{
publicKey: emailJsPublicKey,
}
);

localStorage.setItem(
`lecturePulse_otp_${email}`,
JSON.stringify(otpData)
);

return otp;
return { success: true };
} catch (error) {
console.error("Failed to send OTP email:", error);
return {
success: false,
message: "Could not send the verification code. Please try again.",
};
}
};

const verifyOTP = (email, otp) => {
Expand Down
27 changes: 17 additions & 10 deletions lecture-pulse/src/pages/Profile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,32 @@ export default function Profile() {
const [otp, setOtp] = useState("");
const [step, setStep] = useState(1); // 1: Enter Email, 2: Enter OTP
const [isEditing, setIsEditing] = useState(false);
const [isSendingOtp, setIsSendingOtp] = useState(false);

if (!teacher) {
navigate("/login");
return null;
}

const handleSendOTP = (e) => {
const handleSendOTP = async (e) => {
e.preventDefault();
if (!email) {
toast.error("Please enter an email address");
return;
}
const generatedOtp = sendOTP(email);
setStep(2);
// Simulating sending email
toast.success("Verification code sent!", {
description: `For hackathon demo, your code is: ${generatedOtp}`,
duration: 10000,
});

setIsSendingOtp(true);
const result = await sendOTP(email);
setIsSendingOtp(false);

if (result.success) {
setStep(2);
toast.success("Verification code sent!", {
description: "Please check your inbox for the 6-digit code.",
});
} else {
toast.error(result.message);
}
};

const handleVerifyOTP = (e) => {
Expand Down Expand Up @@ -165,8 +172,8 @@ export default function Profile() {
</div>
</div>
<div className="flex gap-3">
<Button type="submit" className="flex-1 sm:flex-none">
Send Verification Code
<Button type="submit" className="flex-1 sm:flex-none" disabled={isSendingOtp}>
{isSendingOtp ? "Sending..." : "Send Verification Code"}
</Button>
{isEditing && (
<Button
Expand Down