From 336abfbf8e4c9c489386fb975551ab46b6afd084 Mon Sep 17 00:00:00 2001 From: MAMUNdevBD Date: Wed, 5 Jul 2023 20:33:04 +0600 Subject: [PATCH] Admin Authentication --- components/Layout/DefaultLayout.tsx | 7 + components/RecentSection.tsx | 1 - controllers/AuthController.ts | 12 + pages/admin/index.tsx | 1444 +-------------------------- pages/admin/login.tsx | 86 ++ pages/api/v1/login.ts | 29 + store/index.ts | 2 + store/userSlice.ts | 21 + 8 files changed, 167 insertions(+), 1435 deletions(-) create mode 100644 controllers/AuthController.ts create mode 100644 pages/admin/login.tsx create mode 100644 pages/api/v1/login.ts create mode 100644 store/userSlice.ts diff --git a/components/Layout/DefaultLayout.tsx b/components/Layout/DefaultLayout.tsx index 5ab3250..fb9ef77 100644 --- a/components/Layout/DefaultLayout.tsx +++ b/components/Layout/DefaultLayout.tsx @@ -16,6 +16,13 @@ const DefaultLayout = ({ children }: PropsWithChildren) => { const [animation, setAnimation] = useState(themeConfig.animation); const dispatch = useDispatch(); + const user = useSelector((state: any) => state.user?.user); + useEffect(() => { + if (!user || user.length == 0) { + router.push("/admin/login"); + } + }, [router, user]); + const goToTop = () => { document.body.scrollTop = 0; document.documentElement.scrollTop = 0; diff --git a/components/RecentSection.tsx b/components/RecentSection.tsx index 9efe814..3cd71e9 100644 --- a/components/RecentSection.tsx +++ b/components/RecentSection.tsx @@ -4,7 +4,6 @@ import RecentCard from "./RecentCard"; const RecentSection = () => { const histories = useSelector((state: any) => state.history?.recentSurahs); - console.log("h", histories); return (
diff --git a/controllers/AuthController.ts b/controllers/AuthController.ts new file mode 100644 index 0000000..ff7c61e --- /dev/null +++ b/controllers/AuthController.ts @@ -0,0 +1,12 @@ +import { db } from "@/database"; + +export class AuthController { + static login = async (data: { email: string; password: string }) => { + return await db("users") + .where({ + mail: data.email, + password: data.password, + }) + .first(); + }; +} diff --git a/pages/admin/index.tsx b/pages/admin/index.tsx index e832259..cf11767 100644 --- a/pages/admin/index.tsx +++ b/pages/admin/index.tsx @@ -75,286 +75,7 @@ const AdminDashboard = () => { }, }, }; - // paidVisitOptions - const paidVisit: any = { - series: [{ data: [22, 19, 30, 47, 32, 44, 34, 55, 41, 69] }], - options: { - chart: { - height: 58, - type: "line", - fontFamily: "Nunito, sans-serif", - sparkline: { - enabled: true, - }, - dropShadow: { - enabled: true, - blur: 3, - color: "#e2a03f", - opacity: 0.4, - }, - }, - stroke: { - curve: "smooth", - width: 2, - }, - colors: ["#e2a03f"], - grid: { - padding: { - top: 5, - bottom: 5, - left: 5, - right: 5, - }, - }, - tooltip: { - x: { - show: false, - }, - y: { - title: { - formatter: () => { - return ""; - }, - }, - }, - }, - }, - }; - // uniqueVisitorSeriesOptions - const uniqueVisitorSeries: any = { - series: [ - { - name: "Direct", - data: [58, 44, 55, 57, 56, 61, 58, 63, 60, 66, 56, 63], - }, - { - name: "Organic", - data: [91, 76, 85, 101, 98, 87, 105, 91, 114, 94, 66, 70], - }, - ], - options: { - chart: { - height: 360, - type: "bar", - fontFamily: "Nunito, sans-serif", - toolbar: { - show: false, - }, - }, - dataLabels: { - enabled: false, - }, - stroke: { - width: 2, - colors: ["transparent"], - }, - colors: ["#5c1ac3", "#ffbb44"], - dropShadow: { - enabled: true, - blur: 3, - color: "#515365", - opacity: 0.4, - }, - plotOptions: { - bar: { - horizontal: false, - columnWidth: "55%", - borderRadius: 8, - borderRadiusApplication: "end", - }, - }, - legend: { - position: "bottom", - horizontalAlign: "center", - fontSize: "14px", - itemMargin: { - horizontal: 8, - vertical: 8, - }, - }, - grid: { - borderColor: isDark ? "#191e3a" : "#e0e6ed", - padding: { - left: 20, - right: 20, - }, - }, - xaxis: { - categories: [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ], - axisBorder: { - show: true, - color: isDark ? "#3b3f5c" : "#e0e6ed", - }, - }, - yaxis: { - tickAmount: 6, - opposite: isRtl ? true : false, - labels: { - offsetX: isRtl ? -10 : 0, - }, - }, - fill: { - type: "gradient", - gradient: { - shade: isDark ? "dark" : "light", - type: "vertical", - shadeIntensity: 0.3, - inverseColors: false, - opacityFrom: 1, - opacityTo: 0.8, - stops: [0, 100], - }, - }, - tooltip: { - marker: { - show: true, - }, - }, - }, - }; - // followersOptions - const followers: any = { - series: [ - { - data: [38, 60, 38, 52, 36, 40, 28], - }, - ], - options: { - chart: { - height: 160, - type: "area", - fontFamily: "Nunito, sans-serif", - sparkline: { - enabled: true, - }, - }, - stroke: { - curve: "smooth", - width: 2, - }, - colors: ["#4361ee"], - grid: { - padding: { - top: 5, - }, - }, - yaxis: { - show: false, - }, - tooltip: { - x: { - show: false, - }, - y: { - title: { - formatter: () => { - return ""; - }, - }, - }, - }, - }, - }; - // referralOptions - const referral: any = { - series: [ - { - data: [60, 28, 52, 38, 40, 36, 38], - }, - ], - options: { - chart: { - height: 160, - type: "area", - fontFamily: "Nunito, sans-serif", - sparkline: { - enabled: true, - }, - }, - stroke: { - curve: "smooth", - width: 2, - }, - colors: ["#e7515a"], - grid: { - padding: { - top: 5, - }, - }, - yaxis: { - show: false, - }, - tooltip: { - x: { - show: false, - }, - y: { - title: { - formatter: () => { - return ""; - }, - }, - }, - }, - }, - }; - // engagementOptions - const engagement: any = { - series: [ - { - name: "Sales", - data: [28, 50, 36, 60, 38, 52, 38], - }, - ], - options: { - chart: { - height: 160, - type: "area", - fontFamily: "Nunito, sans-serif", - sparkline: { - enabled: true, - }, - }, - stroke: { - curve: "smooth", - width: 2, - }, - colors: ["#1abc9c"], - grid: { - padding: { - top: 5, - }, - }, - yaxis: { - show: false, - }, - tooltip: { - x: { - show: false, - }, - y: { - title: { - formatter: () => { - return ""; - }, - }, - }, - }, - }, - }; + return (
@@ -425,7 +146,7 @@ const AdminDashboard = () => {
-
+
Total Visits
@@ -441,1168 +162,23 @@ const AdminDashboard = () => { /> )}
- -
-
-
Paid Visits
-
7,929
-
- - {isMounted && ( - - )} -
-
Expenses
- -
- - - - - - } - > -
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
-
+
Total Courses
-
- $ 45,141 - - this week - - - - - -
-
-
-
-
- - 57% - +
+ 100
- -
-
-
Total Balance
- -
- $ 41,741.42 - - + 2453 - -
-
-
-
- - -
- +
+
+
Total Students
-
-
- -
-
-
-
Unique Visitors
-
- - - - - - } - > -
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
-
-
- - {isMounted && ( - - )} -
- -
-
-
Activity Log
-
- - - - - - } - > -
    -
  • - -
  • -
  • - -
  • -
-
-
-
- -
-
-
-
- - - - -
-
-
-
- New project created :{" "} - -
-

27 Feb, 2020

-
-
-
-
-
- - - - -
-
-
-
- Mail sent to{" "} - {" "} - and{" "} - -
-

28 Feb, 2020

-
-
-
-
-
- - - - -
-
-
-
- Server Logs Updated -
-

27 Feb, 2020

-
-
-
-
-
- - - - -
-
-
-
- Task Completed : - -
-

01 Mar, 2020

-
-
-
-
-
- - - - -
-
-
-
- Documents Submitted from{" "} - -
-

10 Mar, 2020

-
-
-
-
-
- - - - - - - - -
-
-
-
- Server rebooted successfully -
-

06 Apr, 2020

-
-
-
-
-
-
- -
-
-
-
- Visitors by Browser -
-
-
-
-
-
- - - - - - - -
-
-
-
-
Chrome
-

65%

-
-
-
-
-
-
-
-
-
-
-
- - - - -
-
-
-
-
Safari
-

40%

-
-
-
-
-
-
-
-
-
-
-
- - - - -
-
-
-
-
Others
-

25%

-
-
-
-
-
-
-
-
-
-
- -
-
-
- - - - - - - - -
-
-

31.6K

-
Followers
-
-
-
- {isMounted && ( - - )} -
-
- -
-
-
- - - - -
-
-

1,900

-
Referral
-
-
-
- {isMounted && ( - - )} -
-
- -
-
-
- - - - - - - - - -
-
-

18.2%

-
Engagement
-
-
-
- {isMounted && ( - - )} -
-
-
- -
-
-
-
- profile1 -
-
-
Jimmy Turner
-

Monday, Nov 18

-
-
-
-
- {`"Duis aute irure dolor" in reprehenderit in voluptate velit esse - cillum "dolore eu fugiat" nulla pariatur. Excepteur sint - occaecat cupidatat non proident.`} -
-
-
- - - - - 551 Likes -
- -
-
-
- -
-
-
-
-
- profile2 -
-
-
-
Dev Summit - New York
-

Bronx, NY

-
-
-
-
-
4 Members Going
-
- profile1 - profile2 - profile3 - profile4 -
- -
- -
-
-
- -
-
- - -
- - - - - - } - > -
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
-
-
-
-
- Doloribus nisi vel suscipit modi, optio ex repudiandae - voluptatibus officiis commodi. Nesciunt quas aut neque - incidunt! -
-
-
- - - - -
5 Tasks
-
-

65%

-
-
-
-
-
-
- - - - - 3 Days Left -
-
- - +6 - - profile6 - profile7 - profile8 -
-
+
+ 100
diff --git a/pages/admin/login.tsx b/pages/admin/login.tsx new file mode 100644 index 0000000..6e30316 --- /dev/null +++ b/pages/admin/login.tsx @@ -0,0 +1,86 @@ +import Link from "next/link"; +import { useDispatch, useSelector } from "react-redux"; +import { IRootState } from "../../store"; +import { useEffect, useState } from "react"; +import { setPageTitle } from "../../store/themeConfigSlice"; +import { useRouter } from "next/router"; +import BlankLayout from "@/components/Layout/BlankLayout"; +import { createUser } from "@/store/userSlice"; + +const LoginBoxed = () => { + const dispatch = useDispatch(); + useEffect(() => { + dispatch(setPageTitle("Login Boxed")); + }); + const router = useRouter(); + const isDark = + useSelector((state: IRootState) => state.themeConfig.theme) === "dark" + ? true + : false; + + const [error, setError] = useState(); + + const submitForm = (e: any) => { + e.preventDefault(); + var formdata = new FormData(); + formdata.append("email", e.target.email.value); + formdata.append("password", e.target.password.value); + + fetch("/api/v1/login", { + method: "POST", + body: formdata, + redirect: "follow", + }) + .then((response) => response.json()) + .then(({ success, msg, data }) => { + if (success) { + dispatch(createUser(data)); + router.push("/admin"); + } else { + setError(msg); + } + console.log(msg); + }) + .catch((error) => console.log("error", error)); + }; + + return ( +
+
+

Sign In

+

Enter your email and password to login

+

{error}

+
+
+ + +
+
+ + +
+ + +
+
+
+ ); +}; +LoginBoxed.getLayout = (page: any) => { + return {page}; +}; +export default LoginBoxed; diff --git a/pages/api/v1/login.ts b/pages/api/v1/login.ts new file mode 100644 index 0000000..1d354fa --- /dev/null +++ b/pages/api/v1/login.ts @@ -0,0 +1,29 @@ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction + +import { AuthController } from "@/controllers/AuthController"; +import formData from "@/helpers/formData"; +import type { NextApiRequest, NextApiResponse } from "next"; +export const config = { + api: { + bodyParser: false, + }, +}; +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const data: any = await formData(req); + const user = await AuthController.login(data.fields); + if (user) { + res.status(200).send({ + success: true, + msg: "successfully logged in", + data: user, + }); + } else { + res.status(200).send({ + success: false, + msg: "Wrong credentials", + }); + } +} diff --git a/store/index.ts b/store/index.ts index 961a38f..b7eb851 100644 --- a/store/index.ts +++ b/store/index.ts @@ -4,6 +4,7 @@ import storage from "redux-persist/lib/storage"; import { combineReducers } from "redux"; import { persistReducer } from "redux-persist"; import themeConfigSlice from "./themeConfigSlice"; +import userSlice from "./userSlice"; const persistConfig = { key: "root", @@ -12,6 +13,7 @@ const persistConfig = { const reducers = combineReducers({ history: historySlice.reducer, + user: userSlice.reducer, themeConfig: themeConfigSlice, }); diff --git a/store/userSlice.ts b/store/userSlice.ts new file mode 100644 index 0000000..e60c752 --- /dev/null +++ b/store/userSlice.ts @@ -0,0 +1,21 @@ +import { createSlice } from "@reduxjs/toolkit"; + +export const userSlice = createSlice({ + name: "user", + initialState: { + user: [], + }, + reducers: { + createUser: (state, data) => { + state.user = data.payload; + }, + removeUser: (state) => { + state.user = []; + }, + }, +}); + +// Action creators are generated for each case reducer function +export const { createUser, removeUser } = userSlice.actions; + +export default userSlice;