diff --git a/alimento-nextjs/app/admin/[adminId]/page.tsx b/alimento-nextjs/app/admin/[adminId]/page.tsx new file mode 100644 index 0000000..4c21631 --- /dev/null +++ b/alimento-nextjs/app/admin/[adminId]/page.tsx @@ -0,0 +1,7 @@ +const AdminPage = () => { + return ( +
hi from admin
+ ); +} + +export default AdminPage; \ No newline at end of file diff --git a/alimento-nextjs/app/admin/auth/components/login-form.tsx b/alimento-nextjs/app/admin/auth/components/login-form.tsx new file mode 100644 index 0000000..0dd9209 --- /dev/null +++ b/alimento-nextjs/app/admin/auth/components/login-form.tsx @@ -0,0 +1,69 @@ +"use client"; + +import * as React from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Spinner } from "@/components/ui/spinner"; +import { cn } from "@/lib/utils"; +import toast, { Toaster } from "react-hot-toast"; + +interface AdminAuthFormProps extends React.HTMLAttributes { + authType: "signup" | "login"; +} + +export function AdminLoginForm({ + className, + authType, + ...props +}: AdminAuthFormProps) { + const [isLoading, setIsLoading] = React.useState(false); + const [email, setEmail] = React.useState(""); + + async function onSubmit(event: React.SyntheticEvent) { + event.preventDefault(); + setIsLoading(true); + + setIsLoading(false); + } + + return ( +
+ + +
+
+
+ + setEmail(e.target.value)} + /> +
+ +
+
+
+ ); +} diff --git a/alimento-nextjs/app/admin/auth/page.tsx b/alimento-nextjs/app/admin/auth/page.tsx new file mode 100644 index 0000000..d49a5d6 --- /dev/null +++ b/alimento-nextjs/app/admin/auth/page.tsx @@ -0,0 +1,45 @@ +import { Metadata } from 'next'; +import Image from 'next/image'; +import { AdminLoginForm } from '@/app/admin/auth/components/login-form'; + +export const metadata: Metadata = { + title: 'Authentication', + description: 'Authentication forms built using the components.', +}; + +export default function AuthenticationPage() { + return ( + <> +
+ {/* Background Image Section for larger screens */} + + Authentication + + + {/* Main Content Section */} +
+
+ {/* Title and Description */} +
+

Welcome Back, Admin!

+

Enter your credentials to access your admin panel.

+
+ + {/* Admin Login Form */} + + + {/* Alternative Links +
+
*/} +
+
+
+ + ); +} diff --git a/alimento-nextjs/lib/auth.ts b/alimento-nextjs/lib/auth.ts index 1da5cb3..c24cc9d 100644 --- a/alimento-nextjs/lib/auth.ts +++ b/alimento-nextjs/lib/auth.ts @@ -1,35 +1,51 @@ -import CredentialsProvider from 'next-auth/providers/credentials'; -import { NextAuthOptions } from 'next-auth'; -import prismadb from './prismadb'; -import sendEmail from './sendEmail'; + +import CredentialsProvider from "next-auth/providers/credentials"; +import { NextAuthOptions } from "next-auth"; +import sendEmail from "@/lib/sendEmail"; // Ensure this points to your sendEmail function +import prismadb from "./prismadb"; // const prisma = new PrismaClient(); export const NEXT_AUTH_CONFIG: NextAuthOptions = { providers: [ CredentialsProvider({ - name: 'Credentials', + name: "Credentials", credentials: { - email: { label: 'Email', type: 'text' }, - otp: { label: 'OTP', type: 'text' }, - role: { label: 'Role', type: 'text' }, + email: { label: "Email", type: "text" }, + otp: { label: "OTP", type: "text" }, + role: { label: "Role", type: "text" }, }, async authorize(credentials) { + + console.log(credentials+"controlp0") + if (!credentials?.email || !credentials?.otp || !credentials?.role) { - throw new Error('Invalid credentials'); + throw new Error("Invalid credentials"); } + console.log(credentials) + + console.log(credentials+"control1") let account; - if (credentials.role === 'customer') { + if (credentials.role === "customer") { account = await prismadb.customer.findUnique({ where: { email: credentials.email }, }); - } else { + } else if (credentials.role === "vendor"){ account = await prismadb.vendor.findUnique({ where: { email: credentials.email }, }); + }else if (credentials.role === "admin"){ + account = await prismadb.admin.findUnique({ + where: { email: credentials.email }, + }); + } + else{ + return null } + console.log(account+"control2") + if (!account) { return null; } @@ -42,23 +58,33 @@ export const NEXT_AUTH_CONFIG: NextAuthOptions = { const updateData = { otp: null }; // Clear OTP after successful login - if (credentials.role === 'customer') { + if (credentials.role === "customer") { await prismadb.customer.update({ where: { email: credentials.email }, data: updateData, // Reset OTP or delete it after use }); - } else { + } else if(credentials.role === "vendor"){ await prismadb.vendor.update({ where: { email: credentials.email }, data: updateData, // Reset OTP or delete it after use }); + }else if (credentials.role === "admin"){ + await prismadb.admin.update({ + where: { email: credentials.email }, + data: updateData, // Reset OTP or delete it after use + }); } + else{ + return null + } + + const role = account.role == "customer" ? "customer" : account.role == "vendor"? "vendor" : "admin" return { id: account.id, name: account.name, email: account.email, - role: account.role == 'customer' ? 'customer' : 'vendor', + role: role }; }, }), @@ -82,37 +108,52 @@ export const NEXT_AUTH_CONFIG: NextAuthOptions = { }, }; - +// Function to generate and send OTP export const generateAndSendOTP = async ( email: string, - role: 'vendor' | 'customer' + role: string ) => { const otp = Math.floor(100000 + Math.random() * 900000).toString(); // Generate 6-digit OTP - // Store OTP in the customer or vendor record + // Store OTP in the user or vendor record - if (role === 'customer') { + if (role === "user") { try { await prismadb.customer.update({ where: { email }, - data: { otp }, // Ensure 'otp' field exists in your customer model + data: { otp }, // Ensure 'otp' field exists in your User model }); } catch (err) { console.error( - 'DB Error sending OTP for customer:', + "DB Error sending OTP for user:", err instanceof Error ? err.message : err ); return false; } - } else if (role === 'vendor') { + } else if (role === "vendor") { try { await prismadb.vendor.update({ where: { email }, - data: { otp }, + data: { otp }, // Ensure 'otp' field exists in your User model }); } catch (err) { console.error( - 'DB Error sending OTP for vendor:', + "DB Error sending OTP for vendor:", + err instanceof Error ? err.message : err + ); + return false; + } + } + + else if (role === "admin") { + try { + await prismadb.admin.update({ + where: { email }, + data: { otp }, // Ensure 'otp' field exists in your User model + }); + } catch (err) { + console.error( + "DB Error sending OTP for admin:", err instanceof Error ? err.message : err ); return false; @@ -122,18 +163,21 @@ export const generateAndSendOTP = async ( try { const response = await sendEmail({ to: email, - subject: 'Your OTP Code', + subject: "Your OTP Code", text: `Your OTP code is ${otp}`, html: `Your OTP code is ${otp}`, }); - console.log('OTP email sent successfully:', response); + console.log("OTP email sent successfully:", response); return true; + // Handle success response if needed (e.g., logging messageId) } catch (err) { console.error( - 'Error sending OTP:', + "Error sending OTP:", err instanceof Error ? err.message : err ); return false; } -}; \ No newline at end of file +}; + +// Call generateAndSendOTP(email) before redirecting to the login page to send OTP to the user diff --git a/alimento-nextjs/prisma/schema.prisma b/alimento-nextjs/prisma/schema.prisma index bb798f6..76370ba 100644 --- a/alimento-nextjs/prisma/schema.prisma +++ b/alimento-nextjs/prisma/schema.prisma @@ -7,6 +7,18 @@ datasource db { url = env("DATABASE_URL") } +model Admin { + id String @id @default(uuid()) @map("_id") + name String? + + email String? @unique + otp String? + role String @default("admin") + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + model Customer { id String @id @default(uuid()) @map("_id") name String diff --git a/alimento-nextjs/public/adminLogin.png b/alimento-nextjs/public/adminLogin.png new file mode 100644 index 0000000..52bef72 Binary files /dev/null and b/alimento-nextjs/public/adminLogin.png differ diff --git a/alimento-nextjs/types/next-auth.d.ts b/alimento-nextjs/types/next-auth.d.ts index 5a93b4f..e1e9ed5 100644 --- a/alimento-nextjs/types/next-auth.d.ts +++ b/alimento-nextjs/types/next-auth.d.ts @@ -8,19 +8,19 @@ declare module 'next-auth' { id: string; name?: string; email?: string; - role: 'customer' | 'vendor'; // Extend with the role property + role: 'customer' | 'vendor' | 'admin'; // Extend with the role property }; } interface User extends DefaultUser { - role: 'customer' | 'vendor'; // Add role to User object + role: 'customer' | 'vendor' | 'admin'; // Add role to User object } } declare module 'next-auth/jwt' { interface JWT { uid: string; - role: 'customer' | 'vendor'; // Add role to JWT token + role: 'customer' | 'vendor' | 'admin'; // Add role to JWT token } }