Skip to content
Closed
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,378 changes: 3,377 additions & 1 deletion backend/stock-prediction.ipynb

Large diffs are not rendered by default.

1,490 changes: 1,075 additions & 415 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "node start-dev.js",
"start": "react-scripts start",
"start:original": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
Expand Down
2 changes: 2 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import AboutComponent from "./components/About";
import ContactForm from "./components/ContactForm";
import Login from "./components/Login";
import Signup from "./components/Signup";
import ForgotPassword from "./components/ForgotPassword";
import Watchlist from "./components/Watchlist";
import { AuthProvider } from "./components/AuthContext";
import ErrorBoundary from "./components/ErrorBoundary";
Expand Down Expand Up @@ -63,6 +64,7 @@ const App = () => {
<Route path="/stock/:ticker" element={<Stockdata />} />
<Route path="/about" element={<AboutComponent />} />
<Route path="/stocks" element={<StocksList />} />
<Route path="/forgot-password" element={<ForgotPassword />} />
<Route path="/watchlist" element={<Watchlist />} />
<Route path="/contact" element={<ContactForm />} />
</Routes>
Expand Down
56 changes: 56 additions & 0 deletions src/components/ForgotPassword.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { useState } from "react";
import { sendPasswordResetEmail } from "firebase/auth";
import { auth } from "./firebase";
import { Link } from "react-router-dom";
import "./Login.css"; // You can reuse the same CSS

const ForgotPassword = () => {
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);

const handleReset = async (e) => {
e.preventDefault();
setError("");
setMessage("");
setLoading(true);

try {
await sendPasswordResetEmail(auth, email);
setMessage("Password reset email sent! Check your inbox.");
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

return (
<div className="login-page">
<div className="login-container">
<h2>Forgot Password</h2>
<form onSubmit={handleReset} className="login-form">
<input
type="email"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
disabled={loading}
/>
{error && <p className="login-error">{error}</p>}
{message && <p style={{ color: "green", fontSize: "14px" }}>{message}</p>}
<button type="submit" disabled={loading}>
{loading ? "Sending..." : "Send Reset Email"}
</button>
</form>
<p style={{ marginTop: "10px", textAlign: "center" }}>
<Link to="/login">Back to Login</Link>
</p>
</div>
</div>
);
};

export default ForgotPassword;
32 changes: 26 additions & 6 deletions src/components/Login.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// src/components/Login.jsx
import React, { useState } from "react";
import {
signInWithEmailAndPassword,
Expand All @@ -13,12 +14,14 @@ const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [success, setSuccess] = useState(false);
const [loading, setLoading] = useState(false);
const navigate = useNavigate();

const handleLogin = async (e) => {
e.preventDefault();
setError("");
setSuccess(false);
setLoading(true);

try {
Expand All @@ -32,7 +35,11 @@ const Login = () => {
// Sync local data to Firebase after login
await syncLocalToFirebase(userCredential.user);

navigate("/"); // redirect to home page
// Show success message
setSuccess(true);

// Redirect after short delay to allow user to see the message
setTimeout(() => navigate("/"), 1500);
} catch (err) {
setError(err.message);
} finally {
Expand All @@ -42,23 +49,26 @@ const Login = () => {

const handleGoogleLogin = async () => {
setError("");
setSuccess(false);
setLoading(true);

try {
const provider = new GoogleAuthProvider();
const result = await signInWithPopup(auth, provider);

// Sync local data to Firebase after Google login
await syncLocalToFirebase(result.user);
navigate("/"); // redirect to home page

setSuccess(true);

// Redirect after short delay
setTimeout(() => navigate("/"), 1500);
} catch (err) {
const errorCode = err.code;

if (errorCode === "auth/popup-closed-by-user") {
setError("Sign-in cancelled by user");
} else if (errorCode === "auth/popup-blocked") {
setError(
"Popup blocked by browser. Please allow popups and try again."
);
setError("Popup blocked by browser. Please allow popups.");
} else {
setError(err.message);
}
Expand Down Expand Up @@ -104,11 +114,21 @@ const Login = () => {
disabled={loading}
/>
{error && <p className="login-error">{error}</p>}
{success && <p className="login-success">Login successful 🎉</p>}
<button type="submit" disabled={loading}>
{loading ? "Logging in..." : "Login"}
</button>
</form>

<p style={{ marginTop: "10px", textAlign: "center" }}>
<Link
to="/forgot-password"
style={{ color: "#007bff", textDecoration: "none" }}
>
Forgot Password?
</Link>
</p>

<p>
Don't have an account? <Link to="/signup">Signup</Link>
</p>
Expand Down
59 changes: 36 additions & 23 deletions src/components/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,63 @@ import { getFirestore } from "firebase/firestore";
// ✅ Use .env variables (set these in your .env file)
// If no Firebase config is provided, use dummy config for development
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY || "demo-api-key",
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN || "demo-project.firebaseapp.com",
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID || "demo-project",
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET || "demo-project.appspot.com",
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID || "123456789",
appId: process.env.REACT_APP_FIREBASE_APP_ID || "1:123456789:web:demo",
// 👇 Only include if you need analytics
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID || "G-DEMO123",
// 👇 Only include if you enable Realtime Database
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL || "https://demo-project.firebaseio.com",
apiKey: process.env.REACT_APP_FIREBASE_API_KEY || "",
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN || "",
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID || "",
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET || "",
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID || "",
appId: process.env.REACT_APP_FIREBASE_APP_ID || "",
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID || "",
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL || "",
};

// Avoid initializing twice
// Check if essential config is present
const isConfigValid = Boolean(
firebaseConfig.apiKey &&
firebaseConfig.authDomain &&
firebaseConfig.projectId
);


let app;
let auth;
let realtimeDb;
let firestoreDb;

try {
app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
auth = getAuth(app);
realtimeDb = getDatabase(app);
firestoreDb = getFirestore(app);
} catch (error) {
console.warn("Firebase initialization failed:", error.message);
console.warn("Firebase features will be disabled. Please configure your .env file with valid Firebase credentials.");

// Create mock objects to prevent app crashes
if (isConfigValid) {
try {
app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
auth = getAuth(app);
realtimeDb = getDatabase(app);
firestoreDb = getFirestore(app);
console.log("Firebase initialized successfully.");
} catch (error) {
console.error("Firebase initialization failed:", error.message);
}
} else {
console.warn(
"Firebase config missing or incomplete! Using mock Firebase. " +
"Please add a valid .env file in the project root and restart the dev server."
);

// Mock objects to prevent app crashes
auth = {
currentUser: null,
onAuthStateChanged: () => () => {},
sendPasswordResetEmail: () => Promise.resolve(), // mock
signInWithEmailAndPassword: () => Promise.reject(new Error("Firebase not configured")),
signInWithPopup: () => Promise.reject(new Error("Firebase not configured")),
createUserWithEmailAndPassword: () => Promise.reject(new Error("Firebase not configured")),
signOut: () => Promise.resolve(),
};

realtimeDb = {
ref: () => ({
set: () => Promise.resolve(),
get: () => Promise.resolve({ val: () => null }),
}),
};

firestoreDb = {
collection: () => ({
doc: () => ({
Expand Down