├── app ├── (frontend) │ ├── favicon.ico │ ├── page.jsx │ ├── layout.jsx │ ├── register │ │ └── page.jsx │ ├── login │ │ └── page.jsx │ ├── forgot-password │ │ └── page.jsx │ ├── reset-password │ │ └── page.jsx │ └── verify-account │ │ └── [id] │ │ └── page.jsx ├── globals.css ├── (backoffice) │ ├── dashboard │ │ ├── page.jsx │ │ └── profile │ │ │ └── page.jsx │ └── layout.jsx ├── api │ ├── uploadthing │ │ ├── route.js │ │ └── core.js │ └── users │ │ ├── [id] │ │ └── route.js │ │ └── route.js └── layout.jsx ├── jsconfig.json ├── postcss.config.js ├── .env ├── lib └── uploadthing.js ├── next.config.js ├── .gitignore ├── public ├── vercel.svg └── next.svg ├── tailwind.config.js ├── package.json ├── components ├── backoffice │ ├── Navbar.jsx │ ├── Sidebar.jsx │ └── ProfileForm.jsx ├── FormInputs │ └── ImageInput.jsx ├── FooterSection.jsx ├── NavbarSection.jsx ├── HeroSection.jsx ├── ResetPasswordForm.jsx ├── ForgotPasswordForm.jsx ├── LoginForm.jsx └── RegisterForm.jsx └── README.md /app/(frontend)/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MUKE-coder/auth-system-starter/HEAD/app/(frontend)/favicon.ico -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": { 4 | "@/*": ["./*"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | UPLOADTHING_SECRET=sk_live_162e91451573e8f5733561171853fdaa8bc82a0da5cb6c955d9b35b743dc79c9 2 | UPLOADTHING_APP_ID=w0xo10mntp -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | min-height: 100vh; 7 | } 8 | -------------------------------------------------------------------------------- /lib/uploadthing.js: -------------------------------------------------------------------------------- 1 | import { generateComponents } from "@uploadthing/react"; 2 | 3 | export const { UploadButton, UploadDropzone, Uploader } = generateComponents(); 4 | -------------------------------------------------------------------------------- /app/(backoffice)/dashboard/page.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function page() { 4 | return ( 5 |
6 |

Dashboard

7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /app/(frontend)/page.jsx: -------------------------------------------------------------------------------- 1 | import HeroSection from "@/components/HeroSection"; 2 | import Image from "next/image"; 3 | 4 | export default function Home() { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /app/api/uploadthing/route.js: -------------------------------------------------------------------------------- 1 | import { createNextRouteHandler } from "uploadthing/next"; 2 | 3 | import { ourFileRouter } from "./core"; 4 | 5 | // Export routes for Next App Router 6 | export const { GET, POST } = createNextRouteHandler({ 7 | router: ourFileRouter, 8 | }); 9 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | images: { 4 | remotePatterns: [ 5 | { 6 | protocol: "https", 7 | hostname: "utfs.io", 8 | }, 9 | ], 10 | }, 11 | }; 12 | 13 | module.exports = nextConfig; 14 | -------------------------------------------------------------------------------- /app/(frontend)/layout.jsx: -------------------------------------------------------------------------------- 1 | import FooterSection from "@/components/FooterSection"; 2 | import NavbarSection from "@/components/NavbarSection"; 3 | import React from "react"; 4 | 5 | export default function Layout({ children }) { 6 | return ( 7 |
8 | 9 | {children} 10 | 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /app/(backoffice)/layout.jsx: -------------------------------------------------------------------------------- 1 | import Navbar from "@/components/backoffice/Navbar"; 2 | import Sidebar from "@/components/backoffice/Sidebar"; 3 | import React from "react"; 4 | 5 | export default function Layout({ children }) { 6 | return ( 7 |
8 | 9 |
10 | 11 |
{children}
12 |
13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /app/api/users/[id]/route.js: -------------------------------------------------------------------------------- 1 | import db from "@/lib/db"; 2 | import { NextResponse } from "next/server"; 3 | 4 | export async function GET(request, { params: { id } }) { 5 | try { 6 | const user = await db.user.findUnique({ 7 | where: { 8 | id, 9 | }, 10 | }); 11 | return NextResponse.json(user); 12 | } catch (error) { 13 | console.log(error); 14 | return NextResponse.json( 15 | { 16 | message: "Failed to Fetch User", 17 | error, 18 | }, 19 | { status: 500 } 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/api/uploadthing/core.js: -------------------------------------------------------------------------------- 1 | import { createUploadthing } from "uploadthing/next"; 2 | 3 | const f = createUploadthing(); 4 | 5 | // FileRouter for your app, can contain multiple FileRoutes 6 | export const ourFileRouter = { 7 | // Define as many FileRoutes as you like, each with a unique routeSlug 8 | profileImageUploader: f({ image: { maxFileSize: "1MB" } }) 9 | // Set permissions and file types for this FileRoute 10 | .onUploadComplete(async ({ metadata, file }) => { 11 | console.log("file url", file.url, metadata); 12 | return { uploadedBy: "JB" }; 13 | }), 14 | }; 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | 39 | # Contentlayer 40 | .contentlayer 41 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | import { withUt } from "uploadthing/tw"; 3 | 4 | export default withUt({ 5 | content: [ 6 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 8 | "node_modules/flowbite-react/lib/esm/**/*.js", 9 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 10 | ], 11 | theme: { 12 | extend: { 13 | backgroundImage: { 14 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 15 | "gradient-conic": 16 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 17 | }, 18 | }, 19 | }, 20 | plugins: [require("flowbite/plugin")], 21 | }); 22 | -------------------------------------------------------------------------------- /app/(frontend)/register/page.jsx: -------------------------------------------------------------------------------- 1 | import RegisterForm from "@/components/RegisterForm"; 2 | 3 | export default function Register() { 4 | return ( 5 |
6 |
7 |
8 |
9 |

10 | Create a new account 11 |

12 | 13 |
14 |
15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "auth-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@auth/prisma-adapter": "^1.0.11", 13 | "@prisma/client": "^5.7.1", 14 | "@uploadthing/react": "^6.0.2", 15 | "flowbite-react": "^0.7.2", 16 | "lucide-react": "^0.298.0", 17 | "next": "14.0.4", 18 | "next-auth": "^4.24.5", 19 | "react": "^18", 20 | "react-dom": "^18", 21 | "react-hook-form": "^7.49.2", 22 | "react-hot-toast": "^2.4.1", 23 | "uploadthing": "^6.1.0" 24 | }, 25 | "devDependencies": { 26 | "autoprefixer": "^10.0.1", 27 | "postcss": "^8", 28 | "prisma": "^5.7.1", 29 | "tailwindcss": "^3.3.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/(frontend)/login/page.jsx: -------------------------------------------------------------------------------- 1 | import LoginForm from "@/components/LoginForm"; 2 | import React from "react"; 3 | 4 | export default function Login() { 5 | return ( 6 |
7 |
8 |
9 |
10 |

11 | Sign in to your account 12 |

13 | 14 |
15 |
16 |
17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /app/(backoffice)/dashboard/profile/page.jsx: -------------------------------------------------------------------------------- 1 | import RegisterForm from "@/components/RegisterForm"; 2 | import ProfileForm from "@/components/backoffice/ProfileForm"; 3 | 4 | export default function Profile() { 5 | return ( 6 |
7 |
8 |
9 |
10 |

11 | Update your Profile 12 |

13 | 14 |
15 |
16 |
17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /app/(frontend)/forgot-password/page.jsx: -------------------------------------------------------------------------------- 1 | import ForgotPasswordForm from "@/components/ForgotPasswordForm"; 2 | import RegisterForm from "@/components/RegisterForm"; 3 | 4 | export default function Register() { 5 | return ( 6 |
7 |
8 |
9 |
10 |

11 | Reset Password 12 |

13 | 14 |
15 |
16 |
17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /app/(frontend)/reset-password/page.jsx: -------------------------------------------------------------------------------- 1 | import ForgotPasswordForm from "@/components/ForgotPasswordForm"; 2 | import RegisterForm from "@/components/RegisterForm"; 3 | import ResetPasswordForm from "@/components/ResetPasswordForm"; 4 | 5 | export default function PasswordReset() { 6 | return ( 7 |
8 |
9 |
10 |
11 |

12 | Reset Password 13 |

14 | 15 |
16 |
17 |
18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /app/layout.jsx: -------------------------------------------------------------------------------- 1 | import { Inter } from "next/font/google"; 2 | import "./globals.css"; 3 | import { NextSSRPlugin } from "@uploadthing/react/next-ssr-plugin"; 4 | import { extractRouterConfig } from "uploadthing/server"; 5 | import { ourFileRouter } from "./api/uploadthing/core"; 6 | const inter = Inter({ subsets: ["latin"] }); 7 | 8 | export const metadata = { 9 | title: "Create Next App", 10 | description: "Generated by create next app", 11 | }; 12 | 13 | export default function RootLayout({ children }) { 14 | return ( 15 | 16 | 17 | 26 | {children} 27 | 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/backoffice/Navbar.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { Avatar, Dropdown } from "flowbite-react"; 3 | import { History } from "lucide-react"; 4 | import Link from "next/link"; 5 | import React from "react"; 6 | 7 | export default function Navbar() { 8 | return ( 9 |
10 | 11 | 12 | 13 | 22 | } 23 | > 24 | 25 | Bonnie Green 26 | 27 | name@flowbite.com 28 | 29 | 30 | Dashboard 31 | Settings 32 | 33 | Profile 34 | 35 | 36 | Sign out 37 | 38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /app/(frontend)/verify-account/[id]/page.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { HiInformationCircle } from "react-icons/hi"; 4 | import { Alert } from "flowbite-react"; 5 | 6 | export default function VerifyAccount() { 7 | return ( 8 |
9 |
10 |
11 |
12 |

13 | Verify Account 14 |

15 | 16 | Please Check your Email! We 17 | have sent you a Verification Link and Click on the Link to Verify 18 | your Account. Thank you! 19 | 20 |
21 |

22 | Did not see it?{" "} 23 | 26 |

27 |
28 |
29 |
30 |
31 |
32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /app/api/users/route.js: -------------------------------------------------------------------------------- 1 | import db from "@/lib/db"; 2 | import { NextResponse } from "next/server"; 3 | import bcrypt from "bcrypt"; 4 | export async function POST(request) { 5 | try { 6 | //extract the credentials 7 | const { name, email, password, role } = await request.json(); 8 | //Check if the user Already exists in the db 9 | const existingUser = await db.user.findUnique({ 10 | where: { 11 | email, 12 | }, 13 | }); 14 | if (existingUser) { 15 | return NextResponse.json( 16 | { 17 | data: null, 18 | message: `User with this email ( ${email}) already exists in the Database`, 19 | }, 20 | { status: 409 } 21 | ); 22 | } 23 | // Encrypt the Password =>bcrypt 24 | const hashedPassword = await bcrypt.hash(password, 10); 25 | const newUser = await db.user.create({ 26 | data: { 27 | name, 28 | email, 29 | password: hashedPassword, 30 | role, 31 | }, 32 | }); 33 | console.log(newUser); 34 | return NextResponse.json( 35 | { 36 | data: newUser, 37 | message: "User Created Successfully", 38 | }, 39 | { status: 201 } 40 | ); 41 | } catch (error) { 42 | console.log(error); 43 | return NextResponse.json( 44 | { 45 | error, 46 | message: "Server Error: Something went wrong", 47 | }, 48 | { status: 500 } 49 | ); 50 | } 51 | } 52 | export async function GET(request) { 53 | try { 54 | const users = await db.user.findMany({ 55 | orderBy: { 56 | createdAt: "desc", 57 | }, 58 | }); 59 | return NextResponse.json(users); 60 | } catch (error) { 61 | console.log(error); 62 | return NextResponse.json( 63 | { 64 | message: "Failed to Fetch Users", 65 | error, 66 | }, 67 | { status: 500 } 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /components/FormInputs/ImageInput.jsx: -------------------------------------------------------------------------------- 1 | import { UploadButton, UploadDropzone } from "@/lib/uploadthing"; 2 | import { Pencil } from "lucide-react"; 3 | import Image from "next/image"; 4 | import React from "react"; 5 | import toast from "react-hot-toast"; 6 | 7 | export default function ImageInput({ 8 | label, 9 | imageUrl = "", 10 | setImageUrl, 11 | className = "col-span-full", 12 | endpoint = "", 13 | }) { 14 | return ( 15 |
16 |
17 | 23 | {imageUrl && ( 24 | 32 | )} 33 |
34 | {imageUrl ? ( 35 | Item image 42 | ) : ( 43 |
44 | { 47 | setImageUrl(res[0].url); 48 | // Do something with the response 49 | toast.success("Image Upload complete"); 50 | console.log("Files: ", res); 51 | console.log("Upload Completed"); 52 | }} 53 | onUploadError={(error) => { 54 | toast.error("Image Upload Failed, Try Again"); 55 | // Do something with the error. 56 | console.log(`ERROR! ${error.message}`, error); 57 | }} 58 | /> 59 |
60 | )} 61 |
62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /components/backoffice/Sidebar.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { 3 | Codesandbox, 4 | History, 5 | Home, 6 | Layers3, 7 | LayoutGrid, 8 | Settings, 9 | User2, 10 | } from "lucide-react"; 11 | import Link from "next/link"; 12 | import { usePathname } from "next/navigation"; 13 | import React from "react"; 14 | 15 | export default function Sidebar() { 16 | const pathname = usePathname(); 17 | const navLinks = [ 18 | { 19 | title: "Dashboard", 20 | icon: Home, 21 | href: "/dashboard", 22 | }, 23 | { 24 | title: "Profile", 25 | icon: User2, 26 | href: "/dashboard/profile", 27 | }, 28 | { 29 | title: "Products", 30 | icon: Layers3, 31 | href: "/dashboard/products", 32 | }, 33 | { 34 | title: "Categories", 35 | icon: LayoutGrid, 36 | href: "/dashboard/categories", 37 | }, 38 | { 39 | title: "Settings", 40 | icon: Settings, 41 | href: "/dashboard/settings", 42 | }, 43 | ]; 44 | return ( 45 |
46 | 47 | 48 | {/* Flowbite React Logo */} 53 | 54 | Desishub 55 | 56 | 57 |
58 | {navLinks.map((link, i) => { 59 | const Icon = link.icon; 60 | return ( 61 | 70 | 71 | {link.title} 72 | 73 | ); 74 | })} 75 |
76 |
77 | ); 78 | } 79 | -------------------------------------------------------------------------------- /components/FooterSection.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Footer } from "flowbite-react"; 4 | import { 5 | BsDribbble, 6 | BsFacebook, 7 | BsGithub, 8 | BsInstagram, 9 | BsTwitter, 10 | } from "react-icons/bs"; 11 | 12 | export default function FooterSection() { 13 | return ( 14 | 62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /components/NavbarSection.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import React from "react"; 3 | import { Avatar, Button, Dropdown, Navbar } from "flowbite-react"; 4 | import { Codesandbox } from "lucide-react"; 5 | import Link from "next/link"; 6 | export default function NavbarSection() { 7 | const isLoggedIn = false; 8 | return ( 9 | 10 | 11 | 12 | {/* Flowbite React Logo */} 17 | 18 | Desishub 19 | 20 | 21 |
22 | {isLoggedIn && ( 23 | 32 | } 33 | > 34 | 35 | Bonnie Green 36 | 37 | name@flowbite.com 38 | 39 | 40 | Dashboard 41 | Settings 42 | Earnings 43 | 44 | Sign out 45 | 46 | )} 47 | 51 | Log in 52 | 53 | 57 | Get started 58 | 59 | 60 |
61 | 62 | 63 | Home 64 | 65 | About 66 | Services 67 | Pricing 68 | Contact 69 | 70 |
71 | ); 72 | } 73 | -------------------------------------------------------------------------------- /components/HeroSection.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function HeroSection() { 4 | return ( 5 |
6 |
7 |
8 |

Smart email campaign builder, made for Developers

9 |

10 | Turn your visitors into profitable 11 | 12 | 13 | business 14 | 15 |

16 | 17 | 45 | 46 |

60 Days free trial · No credit card required

47 |
48 |
49 | 50 |
51 |
52 |
53 |
54 |
55 | 56 |
57 |
58 |
59 |
60 |
61 | ) 62 | } 63 | -------------------------------------------------------------------------------- /components/ResetPasswordForm.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { signIn } from "next-auth/react"; 3 | import { useRouter } from "next/navigation"; 4 | import { useState } from "react"; 5 | import { useForm } from "react-hook-form"; 6 | import toast from "react-hot-toast"; 7 | import Link from "next/link"; 8 | import { FaGoogle } from "react-icons/fa"; 9 | import { FaGithub } from "react-icons/fa"; 10 | export default function ResetPasswordForm() { 11 | const router = useRouter(); 12 | const { 13 | register, 14 | handleSubmit, 15 | reset, 16 | formState: { errors }, 17 | } = useForm(); 18 | const [loading, setLoading] = useState(false); 19 | 20 | async function onSubmit(data) { 21 | console.log(data); 22 | try { 23 | setLoading(true); 24 | console.log("Attempting to sign in with credentials:", data); 25 | const loginData = await signIn("credentials", { 26 | ...data, 27 | redirect: false, 28 | }); 29 | console.log("SignIn response:", loginData); 30 | if (loginData?.error) { 31 | setLoading(false); 32 | toast.error("Sign-in error: Check your credentials"); 33 | } else { 34 | // Sign-in was successful 35 | toast.success("Login Successful"); 36 | reset(); 37 | router.push("/"); 38 | } 39 | } catch (error) { 40 | setLoading(false); 41 | console.error("Network Error:", error); 42 | toast.error("Its seems something is wrong with your Network"); 43 | } 44 | } 45 | 46 | return ( 47 |
48 |
49 | 55 | 64 | {errors.password && ( 65 | 66 | This field is required 67 | 68 | )} 69 |
70 | {loading ? ( 71 | 95 | ) : ( 96 | 102 | )} 103 |
104 | ); 105 | } 106 | -------------------------------------------------------------------------------- /components/ForgotPasswordForm.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { signIn } from "next-auth/react"; 3 | import { useRouter } from "next/navigation"; 4 | import { useState } from "react"; 5 | import { useForm } from "react-hook-form"; 6 | import toast from "react-hot-toast"; 7 | import Link from "next/link"; 8 | import { FaGoogle } from "react-icons/fa"; 9 | import { FaGithub } from "react-icons/fa"; 10 | export default function ForgotPasswordForm() { 11 | const router = useRouter(); 12 | const { 13 | register, 14 | handleSubmit, 15 | reset, 16 | formState: { errors }, 17 | } = useForm(); 18 | const [loading, setLoading] = useState(false); 19 | 20 | async function onSubmit(data) { 21 | console.log(data); 22 | try { 23 | setLoading(true); 24 | console.log("Attempting to sign in with credentials:", data); 25 | const loginData = await signIn("credentials", { 26 | ...data, 27 | redirect: false, 28 | }); 29 | console.log("SignIn response:", loginData); 30 | if (loginData?.error) { 31 | setLoading(false); 32 | toast.error("Sign-in error: Check your credentials"); 33 | } else { 34 | // Sign-in was successful 35 | toast.success("Login Successful"); 36 | reset(); 37 | router.push("/"); 38 | } 39 | } catch (error) { 40 | setLoading(false); 41 | console.error("Network Error:", error); 42 | toast.error("Its seems something is wrong with your Network"); 43 | } 44 | } 45 | 46 | return ( 47 |
48 |
49 | 55 | 64 | {errors.email && ( 65 | 66 | This field is required 67 | 68 | )} 69 |
70 | {loading ? ( 71 | 95 | ) : ( 96 | 102 | )} 103 |
104 |

105 | Do remember your Password?{" "} 106 | 110 | Login 111 | 112 |

113 |
114 |
115 | ); 116 | } 117 | -------------------------------------------------------------------------------- /components/backoffice/ProfileForm.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { signIn } from "next-auth/react"; 3 | import Link from "next/link"; 4 | import { useRouter } from "next/navigation"; 5 | import { useState } from "react"; 6 | import { useForm } from "react-hook-form"; 7 | import toast from "react-hot-toast"; 8 | import { FaGithub, FaGoogle } from "react-icons/fa"; 9 | import ImageInput from "../FormInputs/ImageInput"; 10 | 11 | export default function ProfileForm() { 12 | const router = useRouter(); 13 | const { 14 | register, 15 | handleSubmit, 16 | reset, 17 | formState: { errors }, 18 | } = useForm(); 19 | const [imageUrl, setImageUrl] = useState( 20 | "https://utfs.io/f/8b034fb4-1f45-425a-8c57-a7a68835311f-2558r.png" 21 | ); 22 | const [loading, setLoading] = useState(false); 23 | const [emailErr, setEmailErr] = useState(""); 24 | async function onSubmit(data) { 25 | try { 26 | console.log(data); 27 | setLoading(true); 28 | const baseUrl = process.env.NEXT_PUBLIC_BASE_URL; 29 | const response = await fetch(`${baseUrl}/api/user`, { 30 | method: "POST", 31 | headers: { 32 | "Content-Type": "application/json", 33 | }, 34 | body: JSON.stringify(data), 35 | }); 36 | 37 | const responseData = await response.json(); 38 | 39 | if (response.ok) { 40 | setLoading(false); 41 | toast.success("User Created Successfully"); 42 | reset(); 43 | router.push("/login"); 44 | } else { 45 | setLoading(false); 46 | if (response.status === 409) { 47 | setEmailErr("User with this Email already exists"); 48 | toast.error("User with this Email already exists"); 49 | } else { 50 | // Handle other errors 51 | console.error("Server Error:", responseData.message); 52 | toast.error("Oops Something Went wrong"); 53 | } 54 | } 55 | } catch (error) { 56 | setLoading(false); 57 | console.error("Network Error:", error); 58 | toast.error("Something Went wrong, Please Try Again"); 59 | } 60 | } 61 | 62 | return ( 63 |
64 |
65 | 71 |
72 |
73 | 79 | 88 | {errors.name && ( 89 | 90 | This field is required 91 | 92 | )} 93 |
94 |
95 | 101 | 110 | {errors.email && ( 111 | 112 | This field is required 113 | 114 | )} 115 | {emailErr} 116 |
117 | 118 | {loading ? ( 119 | 143 | ) : ( 144 | 150 | )} 151 |
152 | ); 153 | } 154 | -------------------------------------------------------------------------------- /components/LoginForm.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { signIn } from "next-auth/react"; 3 | import { useRouter } from "next/navigation"; 4 | import { useState } from "react"; 5 | import { useForm } from "react-hook-form"; 6 | import toast from "react-hot-toast"; 7 | import Link from "next/link"; 8 | import { FaGoogle } from "react-icons/fa"; 9 | import { FaGithub } from "react-icons/fa"; 10 | export default function LoginForm() { 11 | const router = useRouter(); 12 | const { 13 | register, 14 | handleSubmit, 15 | reset, 16 | formState: { errors }, 17 | } = useForm(); 18 | const [loading, setLoading] = useState(false); 19 | 20 | async function onSubmit(data) { 21 | console.log(data); 22 | try { 23 | setLoading(true); 24 | console.log("Attempting to sign in with credentials:", data); 25 | const loginData = await signIn("credentials", { 26 | ...data, 27 | redirect: false, 28 | }); 29 | console.log("SignIn response:", loginData); 30 | if (loginData?.error) { 31 | setLoading(false); 32 | toast.error("Sign-in error: Check your credentials"); 33 | } else { 34 | // Sign-in was successful 35 | toast.success("Login Successful"); 36 | reset(); 37 | router.push("/"); 38 | } 39 | } catch (error) { 40 | setLoading(false); 41 | console.error("Network Error:", error); 42 | toast.error("Its seems something is wrong with your Network"); 43 | } 44 | } 45 | 46 | return ( 47 |
48 |
49 | 55 | 64 | {errors.email && ( 65 | 66 | This field is required 67 | 68 | )} 69 |
70 |
71 | 77 | 86 | {errors.password && ( 87 | 88 | This field is required 89 | 90 | )} 91 |
92 |
93 | 97 | Forgot Password 98 | 99 | {loading ? ( 100 | 124 | ) : ( 125 | 131 | )} 132 |
133 |
134 |
135 | or 136 |
137 |
138 |
139 | 147 | 156 |
157 | 158 |

159 | Already have an account?{" "} 160 | 164 | Sign Up 165 | 166 |

167 |
168 | ); 169 | } 170 | -------------------------------------------------------------------------------- /components/RegisterForm.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { signIn } from "next-auth/react"; 3 | import Link from "next/link"; 4 | import { useRouter } from "next/navigation"; 5 | import { useState } from "react"; 6 | import { useForm } from "react-hook-form"; 7 | import toast from "react-hot-toast"; 8 | import { FaGithub, FaGoogle } from "react-icons/fa"; 9 | 10 | export default function RegisterForm() { 11 | const router = useRouter(); 12 | const { 13 | register, 14 | handleSubmit, 15 | reset, 16 | formState: { errors }, 17 | } = useForm(); 18 | const [loading, setLoading] = useState(false); 19 | const [emailErr, setEmailErr] = useState(""); 20 | async function onSubmit(data) { 21 | try { 22 | console.log(data); 23 | setLoading(true); 24 | const baseUrl = process.env.NEXT_PUBLIC_BASE_URL; 25 | const response = await fetch(`${baseUrl}/api/user`, { 26 | method: "POST", 27 | headers: { 28 | "Content-Type": "application/json", 29 | }, 30 | body: JSON.stringify(data), 31 | }); 32 | 33 | const responseData = await response.json(); 34 | 35 | if (response.ok) { 36 | setLoading(false); 37 | toast.success("User Created Successfully"); 38 | reset(); 39 | router.push("/login"); 40 | } else { 41 | setLoading(false); 42 | if (response.status === 409) { 43 | setEmailErr("User with this Email already exists"); 44 | toast.error("User with this Email already exists"); 45 | } else { 46 | // Handle other errors 47 | console.error("Server Error:", responseData.message); 48 | toast.error("Oops Something Went wrong"); 49 | } 50 | } 51 | } catch (error) { 52 | setLoading(false); 53 | console.error("Network Error:", error); 54 | toast.error("Something Went wrong, Please Try Again"); 55 | } 56 | } 57 | 58 | return ( 59 |
60 |
61 | 67 | 76 | {errors.name && ( 77 | 78 | This field is required 79 | 80 | )} 81 |
82 |
83 | 89 | 98 | {errors.email && ( 99 | 100 | This field is required 101 | 102 | )} 103 | {emailErr} 104 |
105 |
106 | 112 | 121 | {errors.password && ( 122 | 123 | This field is required 124 | 125 | )} 126 |
127 | {loading ? ( 128 | 152 | ) : ( 153 | 159 | )} 160 |
161 |
162 | or 163 |
164 |
165 |
166 | 174 | 183 |
184 |

185 | Already have an account?{" "} 186 | 190 | Login 191 | 192 |

193 |
194 | ); 195 | } 196 | --------------------------------------------------------------------------------