Skip to content

Commit 169142f

Browse files
Merge pull request #27 from akirachix/feature/admin-dashboard
Updated loader and logout
2 parents 0e4ee24 + 1442cbd commit 169142f

File tree

4 files changed

+69
-70
lines changed

4 files changed

+69
-70
lines changed

tesfa/src/app/favicon.ico

-21.3 KB
Binary file not shown.

tesfa/src/app/globals.css

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -93,35 +93,25 @@ input:focus {
9393
transform: rotate(360deg);
9494
}
9595
}
96+
.container {
97+
position: relative;
98+
display: flex;
99+
justify-content: center;
100+
align-items: center;
101+
height: 100vh;
102+
width: 100%;
103+
}
96104
.dashed-spinner {
97105
position: absolute;
98106
width: 120px;
99107
height: 120px;
100108
border: 4px dashed #FFC321;
101109
border-radius: 50%;
102110
animation: dashed-spin 3s linear infinite;
103-
top: 45%;
104-
left: 46.8%;
105-
transform: translate(-50%, -50%);
111+
margin-top: 27px;
106112
}
107113
.svg-logo {
108-
transform-origin: center;
109114
position: absolute;
110-
top: 50%;
111-
left: 50%;
112-
transform: translate(-50%, -50%);
113-
}
114-
@media screen and (min-width: 1025px) and (max-width: 1400px) {
115-
.dashed-spinner {
116-
top: 44%;
117-
left: 45.5%;
118-
transform: translate(-50%, -50%);
119-
}
120-
}
121-
@media screen and (width: 1024px) {
122-
.dashed-spinner {
123-
top: 42%;
124-
left: 44%;
125-
transform: translate(-50%, -50%);
126-
}
115+
transform-origin: center;
116+
animation: rotate-logo 5s linear infinite, neon-glow 2s infinite alternate;
127117
}

tesfa/src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export default function RootLayout({
2222
return (
2323
<html lang="en" className={`${josefinSans.variable}`}>
2424
<head>
25-
<link rel="icon" href="/tesfalogo.png" />
25+
<link rel="icon" href="/favicon.ico" />
2626
</head>
2727
<body >
2828
<main >{children}</main>

tesfa/src/app/sharedComponents/SideBar/index.tsx

Lines changed: 57 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
"use client";
2-
import React from 'react';
3-
import { useState } from "react";
2+
import React, { useState, useEffect } from "react";
3+
import ReactDOM from "react-dom";
44
import { useRouter, usePathname } from "next/navigation";
55
import { RiSidebarFoldLine } from "react-icons/ri";
66
import { HiSquares2X2 } from "react-icons/hi2";
77
import { LuClock3, LuClipboardList, LuUser, LuLogOut } from "react-icons/lu";
88

9-
109
interface SidebarItemProps {
1110
icon: React.ReactNode;
1211
label: string;
@@ -34,44 +33,73 @@ const SidebarItem = ({ icon, label, isOpen, active, onClick }: SidebarItemProps)
3433
);
3534
};
3635

36+
const LogoutConfirmModal = ({
37+
onCancel,
38+
onConfirm,
39+
}: {
40+
onCancel: () => void;
41+
onConfirm: () => void;
42+
}) => (
43+
<div className="fixed inset-0 bg-black opacity-85 flex items-center justify-center z-[1000]">
44+
<div className="bg-blue-50 p-10 rounded-lg shadow-lg max-w-xs w-full">
45+
<h2 className="text-lg font-bold mb-2 text-[#00363E]">Confirm Logout</h2>
46+
<p className="mb-4 text-gray-700">Are you sure you want to logout?</p>
47+
<div className="flex justify-end gap-4">
48+
<button
49+
onClick={onCancel}
50+
className="px-6 py-2 cursor-pointer rounded-2xl bg-gray-200 hover:bg-gray-300 text-gray-800"
51+
>
52+
Cancel
53+
</button>
54+
<button
55+
onClick={onConfirm}
56+
className="px-6 py-2 cursor-pointer rounded-2xl bg-red-600 hover:bg-red-700 text-white"
57+
>
58+
Logout
59+
</button>
60+
</div>
61+
</div>
62+
</div>
63+
);
64+
3765
const Sidebar = () => {
38-
const [isOpen, setIsOpen] = useState(false);
39-
const [isMobileOpen, setIsMobileOpen] = useState(false);
66+
const [isOpen, setIsOpen] = useState(false);
67+
const [isMobileOpen, setIsMobileOpen] = useState(false);
4068
const [showLogoutConfirm, setShowLogoutConfirm] = useState(false);
4169
const router = useRouter();
4270
const pathname = usePathname();
4371

44-
React.useEffect(() => {
72+
useEffect(() => {
4573
const handleResize = () => {
46-
if (window.innerWidth < 1024) {
47-
setIsOpen(false);
74+
if (window.innerWidth < 1024) {
75+
setIsOpen(false);
4876
}
4977
};
5078

51-
if (typeof window !== 'undefined') {
79+
if (typeof window !== "undefined") {
5280
if (window.innerWidth >= 1024) {
53-
setIsOpen(false);
81+
setIsOpen(false);
5482
} else {
55-
setIsOpen(false);
83+
setIsOpen(false);
5684
}
5785
}
5886

59-
window.addEventListener('resize', handleResize);
60-
return () => window.removeEventListener('resize', handleResize);
87+
window.addEventListener("resize", handleResize);
88+
return () => window.removeEventListener("resize", handleResize);
6189
}, []);
6290

6391
const handleNavigation = (path: string) => {
6492
router.push(path);
65-
if (window.innerWidth < 1024) {
93+
if (window.innerWidth < 1024) {
6694
setIsMobileOpen(false);
6795
}
6896
};
6997

70-
const handleLogoutClick = () => setShowLogoutConfirm(true);
98+
const handleLogoutClick = () => setShowLogoutConfirm(true);
7199

72100
const handleLogoutConfirm = () => {
73-
localStorage.removeItem("authToken");
74-
router.push("/onboarding/login");
101+
localStorage.removeItem("authToken");
102+
router.push("/onboarding/login");
75103
setShowLogoutConfirm(false);
76104
};
77105

@@ -102,7 +130,6 @@ const handleLogoutClick = () => setShowLogoutConfirm(true);
102130
lg:static lg:flex
103131
${isOpen ? "lg:w-60 lg:py-6 lg:px-4" : "lg:w-16 lg:px-2 lg:py-6"}`}
104132
>
105-
106133
<div>
107134
<div className="flex justify-between mb-20">
108135
<button
@@ -122,36 +149,11 @@ const handleLogoutClick = () => setShowLogoutConfirm(true);
122149
<div
123150
className={`transition-opacity duration-300 ${isOpen || isMobileOpen ? "opacity-100" : "opacity-0"}`}
124151
>
125-
<div
126-
className={`${isOpen || isMobileOpen ? "" : "hidden"}`}
127-
>
128-
<img src={"/Images/tesfaLogo.png"} alt="Tesfa Logo"></img>
152+
<div className={`${isOpen || isMobileOpen ? "" : "hidden"}`}>
153+
<img src={"/Images/tesfaLogo.png"} alt="Tesfa Logo"></img>
129154
</div>
130155
</div>
131156
</div>
132-
{showLogoutConfirm && (
133-
<div className="fixed inset-0 bg-black opacity-85 flex items-center justify-center z-50">
134-
<div className="bg-blue-50 p-10 rounded-lg shadow-lg max-w-xs w-full">
135-
<h2 className="text-lg font-bold mb-2 text-[#00363E]">Confirm Logout</h2>
136-
<p className="mb-4 text-gray-700">Are you sure you want to logout?</p>
137-
<div className="flex justify-end gap-4">
138-
<button
139-
onClick={handleLogoutCancel}
140-
className="px-6 py-2 cursor-pointer rounded-2xl bg-gray-200 hover:bg-gray-300 text-gray-800"
141-
>
142-
Cancel
143-
</button>
144-
<button
145-
onClick={handleLogoutConfirm}
146-
className="px-6 py-2 cursor-pointer rounded-2xl bg-red-600 hover:bg-red-700 text-white"
147-
>
148-
Logout
149-
</button>
150-
</div>
151-
</div>
152-
</div>
153-
)}
154-
155157
<nav className="flex flex-col gap-10">
156158
<SidebarItem
157159
icon={<HiSquares2X2 size={30} />}
@@ -177,7 +179,6 @@ const handleLogoutClick = () => setShowLogoutConfirm(true);
177179
path="/kanban"
178180
onClick={() => handleNavigation("/kanban")}
179181
/>
180-
181182
<SidebarItem
182183
icon={<LuUser size={30} />}
183184
label="Profile"
@@ -188,17 +189,25 @@ const handleLogoutClick = () => setShowLogoutConfirm(true);
188189
/>
189190
</nav>
190191
</div>
191-
192192
<div className="mb-4">
193193
<SidebarItem
194194
icon={<LuLogOut size={30} />}
195195
label="Logout"
196196
isOpen={isOpen || isMobileOpen}
197197
active={pathname === ""}
198-
onClick={handleLogoutClick}
198+
onClick={handleLogoutClick}
199199
/>
200200
</div>
201201
</div>
202+
{showLogoutConfirm &&
203+
typeof window !== "undefined" &&
204+
ReactDOM.createPortal(
205+
<LogoutConfirmModal
206+
onCancel={handleLogoutCancel}
207+
onConfirm={handleLogoutConfirm}
208+
/>,
209+
document.body
210+
)}
202211
</>
203212
);
204213
};

0 commit comments

Comments
 (0)