diff --git a/src/app/components/AuthForm.js b/src/app/components/AuthForm.js
index e33555e..9736603 100644
--- a/src/app/components/AuthForm.js
+++ b/src/app/components/AuthForm.js
@@ -1,63 +1,392 @@
'use client';
-import { useState } from "react";
-import { account } from "../lib/appwrite";
import { useRouter } from "next/navigation";
+import { useAuth } from "../context/AuthContext";
+import { useState, useEffect } from "react";
+import Link from "next/link";
+// import { ID } from "../lib/appwrite";
-export default function AuthForm() {
- const [isLogin, setIsLogin] = useState(true);
- const [email, setEmail] = useState("");
- const [password, setPassword] = useState("");
+export default function AuthPage() {
const router = useRouter();
+ const { user, loading: authLoading, isAuthenticated, login, register } = useAuth();
+ const [isLoginForm, setIsLoginForm] = useState(true);
+ const [darkMode, setDarkMode] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [showPassword, setShowPassword] = useState(false);
- const handleSubmit = async (e) => {
- e.preventDefault();
+ // Form states
+ const [loginData, setLoginData] = useState({
+ email: "",
+ password: "",
+ rememberMe: false,
+ });
- try {
- if (isLogin) {
- await account.createEmailPasswordSession(email, password);
- } else {
- await account.create('unique()', email, password);
- await account.createEmailPasswordSession(email, password);
- }
+ const [signupData, setSignupData] = useState({
+ fname: "",
+ lname: "",
+ email: "",
+ password: "",
+ agreeTerms: false,
+ });
+
+ const [errors, setErrors] = useState({
+ agreeTerms: "",
+ general: "",
+ });
+
+ // Redirect if already authenticated
+ useEffect(() => {
+ if (!authLoading && isAuthenticated) {
router.push("/pages/dashboard");
- } catch (err) {
- alert("Authentication error: " + err.message);
+ }
+ }, [isAuthenticated, authLoading, router]);
+
+ const handleLoginChange = (e) => {
+ const { name, value, type, checked } = e.target;
+ setLoginData({
+ ...loginData,
+ [name]: type === "checkbox" ? checked : value,
+ });
+ };
+
+ const handleSignupChange = (e) => {
+ const { name, value, type, checked } = e.target;
+ setSignupData({
+ ...signupData,
+ [name]: type === "checkbox" ? checked : value,
+ });
+ if (name === "agreeTerms") {
+ setErrors({ ...errors, agreeTerms: "" });
}
};
+ const validateSignupForm = () => {
+ let isValid = true;
+ const newErrors = { ...errors };
+
+ if (!signupData.agreeTerms) {
+ newErrors.agreeTerms = "You must agree to the terms and conditions";
+ isValid = false;
+ }
+
+ if (signupData.password.length < 8) {
+ newErrors.general = "Password must be at least 8 characters";
+ isValid = false;
+ }
+
+ setErrors(newErrors);
+ return isValid;
+ };
+
+ const handleLogin = async (e) => {
+ e.preventDefault();
+ setLoading(true);
+ setErrors({ ...errors, general: "" });
+
+ try {
+ await login(loginData.email, loginData.password);
+ router.push("/pages/dashboard");
+ } catch (error) {
+ console.error("Login error:", error);
+ let errorMessage = 'Login failed. Please try again.';
+
+ if (error.type === 'user_invalid_credentials') {
+ errorMessage = 'Invalid email or password';
+ } else if (error.type === 'general_argument_invalid') {
+ errorMessage = 'Invalid email format';
+ } else if (error.code === 401) {
+ errorMessage = 'Authentication failed. Please try again.';
+ }
+
+ setErrors({ ...errors, general: errorMessage });
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleSignup = async (e) => {
+ e.preventDefault();
+ if (!validateSignupForm()) return;
+
+ setLoading(true);
+ setErrors({ ...errors, general: "" });
+
+ try {
+ await register(
+ signupData.email,
+ signupData.password,
+ `${signupData.fname} ${signupData.lname}`
+ );
+ router.push("/pages/dashboard");
+ } catch (error) {
+ console.error("Signup error:", error);
+ let errorMessage = 'Signup failed. Please try again.';
+
+ if (error.type === 'user_already_exists') {
+ errorMessage = 'Email already registered';
+ } else if (error.type === 'general_argument_invalid') {
+ errorMessage = 'Invalid email format';
+ } else if (error.code === 401) {
+ errorMessage = 'Authentication failed. Please try again.';
+ }
+
+ setErrors({ ...errors, general: errorMessage });
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ if (authLoading) {
+ return (
+
+ );
+ }
+
+ if (isAuthenticated) {
+ return null; // Will redirect from useEffect
+ }
+
return (
-
-
{isLogin ? 'Login' : 'Register'}
-
-
- {isLogin ? "New user?" : "Already registered?"}{" "}
-
-
+
+
+
+
+
+ {isLoginForm ? "Sign In" : "Sign Up"}
+
+
+ {isLoginForm
+ ? "Enter your email and password to sign in"
+ : "Create your account to get started"}
+
+
+
+ {errors.general && (
+
+ {errors.general}
+
+ )}
+
+ {isLoginForm ? (
+ // Login Form
+
+ ) : (
+ // Sign Up Form
+
+ )}
+
+
+
+ {isLoginForm ? "Don't have an account?" : "Already have an account?"}
+
+
+
+
+
+
+ {/* Dark mode toggle */}
+
);
-}
+}
\ No newline at end of file
diff --git a/src/app/components/ProtectedRoute.js b/src/app/components/ProtectedRoute.js
new file mode 100644
index 0000000..d4da100
--- /dev/null
+++ b/src/app/components/ProtectedRoute.js
@@ -0,0 +1,26 @@
+// components/ProtectedRoute.js
+"use client";
+import { useRouter } from "next/navigation";
+import { useAuth } from "../context/AuthContext";
+import { useEffect } from "react";
+
+export default function ProtectedRoute({ children }) {
+ const { user, loading } = useAuth();
+ const router = useRouter();
+
+ useEffect(() => {
+ if (!loading && !user) {
+ router.push("/auth");
+ }
+ }, [user, loading, router]);
+
+ if (loading) {
+ return (
+
+ );
+ }
+
+ return user ? children : null;
+}
\ No newline at end of file
diff --git a/src/app/context/AuthContext.js b/src/app/context/AuthContext.js
index e558f07..2a87aea 100644
--- a/src/app/context/AuthContext.js
+++ b/src/app/context/AuthContext.js
@@ -1,37 +1,70 @@
+// context/AuthContext.js
"use client";
-
-import { createContext, useContext, useEffect, useState } from "react";
-import { account } from "../lib/appwrite";
+import { createContext, useContext, useState, useEffect } from "react";
+import { account,ID } from "../lib/appwrite";
const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
- const [isAuthenticated, setIsAuthenticated] = useState(false);
- const [authLoading, setAuthLoading] = useState(true);
+ const [user, setUser] = useState(null);
+ const [loading, setLoading] = useState(true);
- const checkUserSession = async () => {
+ useEffect(() => {
+ checkSession();
+ }, []);
+
+ const checkSession = async () => {
try {
- const user = await account.get();
- if (user) {
- setIsAuthenticated(true);
- }
+ const currentUser = await account.get();
+ setUser(currentUser);
} catch (error) {
- setIsAuthenticated(false);
+ setUser(null);
} finally {
- setAuthLoading(false);
+ setLoading(false);
}
};
- useEffect(() => {
- checkUserSession();
- }, []);
+ const login = async (email, password) => {
+ try {
+ await account.createEmailPasswordSession(email, password);
+ const currentUser = await account.get();
+ setUser(currentUser);
+ return currentUser;
+ } catch (error) {
+ throw error;
+ }
+ };
+
+ const register = async (email, password, name) => {
+ try {
+ await account.create(ID.unique(), email, password, name);
+ await account.createEmailPasswordSession(email, password);
+ const currentUser = await account.get();
+ setUser(currentUser);
+ return currentUser;
+ } catch (error) {
+ throw error;
+ }
+ };
+
+ const logout = async () => {
+ try {
+ await account.deleteSession("current");
+ setUser(null);
+ } catch (error) {
+ throw error;
+ }
+ };
return (
{children}
@@ -39,4 +72,10 @@ export const AuthProvider = ({ children }) => {
);
};
-export const useAuth = () => useContext(AuthContext);
+export const useAuth = () => {
+ const context = useContext(AuthContext);
+ if (!context) {
+ throw new Error("useAuth must be used within an AuthProvider");
+ }
+ return context;
+};
\ No newline at end of file
diff --git a/src/app/layout.js b/src/app/layout.js
index 9ce38c2..0e69e48 100644
--- a/src/app/layout.js
+++ b/src/app/layout.js
@@ -1,16 +1,22 @@
+// app/layout.js or app/page.js if that's where RootLayout is
+"use client";
+
import "./globals.css";
import Navbar from "./components/Navbar";
import Sidebar from "./components/Sidebar";
+import { AuthProvider } from "./context/AuthContext"; // adjust path if needed
export default function RootLayout({ children }) {
return (
-
-
-
- {children}
-
+
+
+
+
+ {children}
+
+
);
diff --git a/src/app/lib/appwrite.js b/src/app/lib/appwrite.js
index 83b099e..1e5666f 100644
--- a/src/app/lib/appwrite.js
+++ b/src/app/lib/appwrite.js
@@ -1,4 +1,4 @@
-import { Client, Account } from "appwrite";
+import { Client, Account,ID } from "appwrite";
const client = new Client();
client
@@ -14,4 +14,4 @@ if (!process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || !process.env.NEXT_PUBLIC_APPWR
}
-export { account,client };
+export { account,client,ID };
diff --git a/src/app/middleware.js b/src/app/middleware.js
index c0de51e..5493fc9 100644
--- a/src/app/middleware.js
+++ b/src/app/middleware.js
@@ -1,16 +1,16 @@
-import { NextResponse } from 'next/server';
+// import { NextResponse } from 'next/server';
-export function middleware(request) {
- const isLoggedIn = request.cookies.get('appwrite-session'); // Set manually if needed
- const url = request.nextUrl;
+// export function middleware(request) {
+// const isLoggedIn = request.cookies.get('appwrite-session'); // Set manually if needed
+// const url = request.nextUrl;
- if (!isLoggedIn && url.pathname.startsWith('/pages')) {
- return NextResponse.redirect(new URL('/login', request.url));
- }
+// if (!isLoggedIn && url.pathname.startsWith('/pages')) {
+// return NextResponse.redirect(new URL('/login', request.url));
+// }
- return NextResponse.next();
-}
+// return NextResponse.next();
+// }
-export const config = {
- matcher: ['/pages/:path*'],
-};
+// export const config = {
+// matcher: ['/pages/:path*'],
+// };
diff --git a/src/app/not-found.js b/src/app/not-found.js
new file mode 100644
index 0000000..3f61aba
--- /dev/null
+++ b/src/app/not-found.js
@@ -0,0 +1,66 @@
+// app/not-found.js (not in a 'page.js' file)
+"use client"; // Add this since you're using client-side features
+
+import Link from "next/link";
+import Image from "next/image";
+import { useEffect } from "react";
+
+export default function NotFound() {
+ useEffect(() => {
+ // Client-side dark mode initialization
+ const darkMode = JSON.parse(localStorage.getItem('darkMode'));
+ if (darkMode) {
+ document.documentElement.classList.add('dark');
+ document.documentElement.classList.add('bg-gray-900');
+ }
+ }, []);
+
+ return (
+
+ {/* Metadata - App Router style */}
+
404 Error Page | TailAdmin
+
+
+ {/* Centered Content */}
+
+
+ ERROR
+
+
+ {/* Optimized Images */}
+
+
+
+
+ We can't seem to find the page you are looking for!
+
+
+
+ Back to Home Page
+
+
+
+ {/* Footer */}
+
+ © {new Date().getFullYear()} - TailAdmin
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/app/pages/dashboard/page.js b/src/app/pages/dashboard/page.js
index 9efb4fc..f0abf16 100644
--- a/src/app/pages/dashboard/page.js
+++ b/src/app/pages/dashboard/page.js
@@ -1,9 +1,33 @@
+// pages/dashboard.js
+'use client';
+import { useEffect, useState } from "react";
+import { account } from "../../lib/appwrite";
+import { useRouter } from "next/navigation";
+
export default function Dashboard() {
+ const [user, setUser] = useState(null);
+ const router = useRouter();
+
+ useEffect(() => {
+ const checkAuth = async () => {
+ try {
+ const currentUser = await account.get();
+ setUser(currentUser);
+ } catch (err) {
+ router.push("/");
+ }
+ };
+ checkAuth();
+ }, [router]);
+
+ if (!user) {
+ return Loading...
;
+ }
+
return (
- <>
-
- Hello World
+
+
Welcome, {user.name}
+
- >
);
-}
+}
\ No newline at end of file