diff --git a/Readme.md b/Readme.md
index a4d501c..3870a04 100644
--- a/Readme.md
+++ b/Readme.md
@@ -62,24 +62,61 @@ We're excited to be part of **Social Winter of Code 2026**! This is a great oppo
## 🏗️ Architecture
-```
-┌─────────────────────────────────────────────────────────────┐
-│ Frontend (Client) │
-│ React 19 + TypeScript + Tailwind CSS + Vite │
-│ Deployed on Vercel │
-└─────────────────────────────────────────────────────────────┘
- ↓
-┌─────────────────────────────────────────────────────────────┐
-│ Backend (Node.js Server) │
-│ Express.js + Prisma + MongoDB + Socket.io │
-│ Deployed on Fly.io │
-└─────────────────────────────────────────────────────────────┘
- ↓
-┌─────────────────────────────────────────────────────────────┐
-│ AI Backend (Python FastAPI) │
-│ FastAPI + LangChain + Pinecone + Groq │
-│ Deployed on Fly.io │
-└─────────────────────────────────────────────────────────────┘
+```mermaid
+flowchart TD
+ %% Define Styles
+ classDef frontend fill:#e1f5fe,stroke:#01579b,stroke-width:2px;
+ classDef backend fill:#fff3e0,stroke:#e65100,stroke-width:2px;
+ classDef aibackend fill:#f3e5f5,stroke:#4a148c,stroke-width:2px;
+ classDef db fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px;
+ classDef external fill:#eee,stroke:#333,stroke-width:2px;
+
+ subgraph Client ["🖥️ Frontend (Vercel)"]
+ direction TB
+ React["React 19 + Vite + Tailwind CSS"]:::frontend
+ end
+
+ subgraph Server ["⚙️ Node.js Backend (Fly.io)"]
+ direction TB
+ API["Express.js + Socket.io"]:::backend
+ Prisma["Prisma ORM"]:::backend
+ end
+
+ subgraph AI ["🤖 AI Python Backend (Fly.io)"]
+ direction TB
+ FastAPI["FastAPI Server + LangChain"]:::aibackend
+ PyPDF["PDF Processor"]:::aibackend
+ end
+
+ subgraph Data ["💾 Databases & Storage"]
+ direction LR
+ Mongo[("MongoDB Atlas")]:::db
+ Redis[("Redis Cloud")]:::db
+ Pinecone[("Pinecone Vector DB")]:::db
+ Blob["Cloud Storage (R2/Blob)"]:::db
+ end
+
+ subgraph Ext ["☁️ External APIs"]
+ direction LB
+ Groq["Groq LLM API"]:::external
+ SMTP["SMTP (Emails)"]:::external
+ end
+
+ %% Core Connections
+ Client <-->|REST & WebSockets| API
+ Client -.->|Direct Uploads| Blob
+
+ API --- Prisma
+ Prisma <-->|CRUD Operations| Mongo
+ API <-->|Session/Cache| Redis
+ API -->|Dispatch| SMTP
+
+ API <-->|HTTP Queries| FastAPI
+
+ FastAPI --- PyPDF
+ FastAPI <-->|Store/Search Vectors| Pinecone
+ PyPDF -.->|Process Docs| Blob
+ FastAPI <-->|LLM Context/Prompts| Groq
```
---
diff --git a/client/src/App.tsx b/client/src/App.tsx
index 556900e..c975cba 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -223,11 +223,12 @@ const App: React.FC = () => {
gutter={12}
containerStyle={{ top: 40 }}
toastOptions={{
+ duration: 4000,
style: {
fontSize: "14px",
maxWidth: "500px",
padding: "12px 20px",
- backgroundColor: "#1e1e1e",
+ backgroundColor: "#1e1e1e",
color: "#fff",
border: "2px solid #00cc33",
borderRadius: "12px",
diff --git a/client/src/components/auth/AuthForm.tsx b/client/src/components/auth/AuthForm.tsx
index 9e91cfa..a580c8c 100644
--- a/client/src/components/auth/AuthForm.tsx
+++ b/client/src/components/auth/AuthForm.tsx
@@ -2,6 +2,7 @@ import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { User, Lock, UserPlus, LogIn, Mail, Shield } from "lucide-react";
import { login, signup, sendOTP } from "../../utils/api";
+import toast from "react-hot-toast";
interface AuthFormProps {
onAuthChange: () => void;
@@ -18,27 +19,23 @@ const AuthForm: React.FC = ({ onAuthChange }) => {
const [otpSent, setOtpSent] = useState(false);
const [loading, setLoading] = useState(false);
const [otpLoading, setOtpLoading] = useState(false);
- const [error, setError] = useState("");
- const [success, setSuccess] = useState("");
const navigate = useNavigate();
const handleSendOTP = async () => {
if (!email) {
- setError("Please enter your email first");
+ toast.error("Please enter your email first");
return;
}
setOtpLoading(true);
- setError("");
- setSuccess("");
try {
const response = await sendOTP(email, "signup");
- setSuccess(response.message);
+ toast.success(response.message);
setOtpSent(true);
setShowOTPField(true);
} catch (err: any) {
- setError(err.response?.data?.error || "Failed to send OTP");
+ toast.error(err.userMessage || err.response?.data?.error || "Failed to send OTP");
} finally {
setOtpLoading(false);
}
@@ -47,8 +44,6 @@ const AuthForm: React.FC = ({ onAuthChange }) => {
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
- setError("");
- setSuccess("");
try {
const authResponse = isLogin
@@ -59,7 +54,7 @@ const AuthForm: React.FC = ({ onAuthChange }) => {
// Set success message for signup
if (!isLogin) {
- setSuccess("Account created successfully! Welcome to Edulume!");
+ toast.success("Account created successfully! Welcome to Edulume!");
}
// Notify parent component to re-check auth status
@@ -74,7 +69,7 @@ const AuthForm: React.FC = ({ onAuthChange }) => {
); // Shorter delay for signup
} catch (err: any) {
console.error("❌ Authentication failed:", err);
- setError(err.response?.data?.error || err.message || "An error occurred");
+ toast.error(err.userMessage || err.response?.data?.error || err.message || "An error occurred");
} finally {
setLoading(false);
}
@@ -226,18 +221,6 @@ const AuthForm: React.FC = ({ onAuthChange }) => {
- {error && (
-
- {error}
-
- )}
-
- {success && (
-
- {success}
-
- )}
-
- {error && (
-
- {error}
-
- )}
-
- {success && (
-
- {success}
-
- )}
-