Skip to content

Commit 70d2a87

Browse files
Merge pull request #26 from akirachix/develop
Develop
2 parents e2164e8 + 0e4ee24 commit 70d2a87

File tree

10 files changed

+174
-65
lines changed

10 files changed

+174
-65
lines changed

tesfa/src/app/admin/performance/page.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export default function PerformancePage() {
9494
<h2 className="text-lg font-semibold text-gray-800">
9595
Number of Queries
9696
</h2>
97-
<button className="px-5 py-2 border cursor-pointer border-gray-400 rounded-full text-sm bg-white hover:bg-gray-100">
97+
<button className="px-5 py-2 border border-gray-400 rounded-full text-sm bg-white hover:bg-gray-100">
9898
Monthly View
9999
</button>
100100
</div>
@@ -120,7 +120,6 @@ export default function PerformancePage() {
120120
</div>
121121
)}
122122
</div>
123-
124123
<div>
125124
<ApiUsageChart />
126125
</div>

tesfa/src/app/admin/sharedcomponent/Sidebar/index.tsx

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
11
"use client";
22
import Link from "next/link";
33
import Image from "next/image";
4-
import { usePathname } from "next/navigation";
5-
import { LayoutDashboard, ClipboardList, Users, Bot, User } from "lucide-react";
4+
import { usePathname, useRouter } from "next/navigation";
5+
import { useState } from "react";
6+
import { LayoutDashboard, ClipboardList, Users, Bot, User, LogOut } from "lucide-react";
7+
68
const menuItems = [
79
{ id: 1, href: "/admin/dashboard", icon: LayoutDashboard, name: "Dashboard" },
8-
{ id: 2, href: "/admin/task-tracking", icon: ClipboardList , name: "Tasks"},
10+
{ id: 2, href: "/admin/task-tracking", icon: ClipboardList, name: "Tasks" },
911
{ id: 3, href: "/admin/organizations", icon: Users, name: "Organizations" },
1012
{ id: 4, href: "/admin/performance", icon: Bot, name: "Performance" },
1113
];
14+
1215
export default function Sidebar() {
1316
const pathname = usePathname();
17+
const router = useRouter();
18+
const [showLogoutConfirm, setShowLogoutConfirm] = useState(false);
19+
20+
const handleLogoutClick = () => setShowLogoutConfirm(true);
21+
22+
const handleLogoutConfirm = () => {
23+
localStorage.removeItem("authToken");
24+
router.push("/onboarding/login");
25+
setShowLogoutConfirm(false);
26+
};
27+
28+
const handleLogoutCancel = () => setShowLogoutConfirm(false);
29+
1430
return (
1531
<div className="w-64 h-screen bg-teal-900 flex flex-col justify-between text-white">
1632
<div className="px-1 bg-teal-900 flex flex-col justify-between text-white">
@@ -41,6 +57,16 @@ export default function Sidebar() {
4157
</Link>
4258
);
4359
})}
60+
61+
<button
62+
onClick={handleLogoutClick}
63+
className={
64+
`cursor-pointer px-6 py-3 mt-4 rounded-l-4xl gap-8 transition-colors flex items-center hover:bg-teal-700 w-63`
65+
}
66+
>
67+
<LogOut size={28} />
68+
<label className="text-md cursor-pointer">Logout</label>
69+
</button>
4470
</div>
4571
</div>
4672
<div className="flex items-center gap-5 px-6 py-4 bg-teal-800">
@@ -49,6 +75,29 @@ export default function Sidebar() {
4975
</div>
5076
<p className="items-center font-medium">Tesfa admin</p>
5177
</div>
78+
79+
{showLogoutConfirm && (
80+
<div className="fixed inset-0 bg-black opacity-90 flex items-center justify-center z-50">
81+
<div className="bg-white p-6 rounded-lg shadow-lg max-w-xs w-full">
82+
<h2 className="text-lg font-bold mb-2 text-[#00363E]">Confirm Logout</h2>
83+
<p className="mb-4 text-gray-700">Are you sure you want to logout?</p>
84+
<div className="flex justify-end gap-4">
85+
<button
86+
onClick={handleLogoutCancel}
87+
className="px-4 py-2 rounded-2xl cursor-pointer bg-gray-200 hover:bg-gray-300 text-gray-800"
88+
>
89+
Cancel
90+
</button>
91+
<button
92+
onClick={handleLogoutConfirm}
93+
className="px-4 py-2 cursor-pointer rounded-2xl bg-red-600 hover:bg-red-700 text-white"
94+
>
95+
Logout
96+
</button>
97+
</div>
98+
</div>
99+
</div>
100+
)}
52101
</div>
53102
);
54-
}
103+
}

tesfa/src/app/edit-profile/page.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default function EditProfilePage() {
2323
const [updateStatus, setUpdateStatus] = useState<"" | "error">("");
2424
const [updateMessage, setUpdateMessage] = useState<string>("");
2525
const [submitting, setSubmitting] = useState(false);
26+
const [imageError, setImageError] = useState("");
2627

2728
useEffect(() => {
2829
if (profile) {
@@ -38,15 +39,26 @@ export default function EditProfilePage() {
3839
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
3940
const { name, value, type, files } = e.target;
4041
if (type === "file" && files && files[0]) {
41-
setLogoImage(files[0]);
42-
setFormData((prev) => ({ ...prev, logo_image: files[0] }));
42+
const file = files[0];
43+
// PNG only
44+
if (file.type !== "image/png") {
45+
setImageError("PNG format is preferable. Please upload a PNG image.");
46+
setLogoImage(null);
47+
setFormData((prev) => ({ ...prev, logo_image: null }));
48+
return;
49+
} else {
50+
setImageError("");
51+
setLogoImage(file);
52+
setFormData((prev) => ({ ...prev, logo_image: file }));
53+
}
4354
} else {
4455
setFormData((prev) => ({ ...prev, [name]: value }));
4556
}
4657
};
4758

4859
const handleSubmit = async (e: React.FormEvent) => {
4960
e.preventDefault();
61+
if (imageError) return;
5062
setSubmitting(true);
5163
const email = formData.email.trim();
5264
const org_name = (formData.org_name || "NGO").trim();
@@ -132,18 +144,23 @@ export default function EditProfilePage() {
132144
<button
133145
type="button"
134146
onClick={() => document.getElementById("logoInput")?.click()}
135-
className="absolute top-40 right-5 bg-white border-2 border-[#C3A041] text-[#C3A041] w-10 h-10 rounded-full flex items-center justify-center shadow hover:bg-[#F3FBFD] transition"
147+
className="absolute top-40 cursor-pointer right-5 bg-white border-2 border-[#C3A041] text-[#C3A041] w-10 h-10 rounded-full flex items-center justify-center shadow hover:bg-[#F3FBFD] transition"
136148
aria-label="Upload logo"
137149
>
138150
<CameraIcon className="w-5 h-5 cursor-pointer" />
139151
</button>
140152
<input
141153
id="logoInput"
142154
type="file"
143-
accept="image/*"
155+
accept="image/png"
144156
onChange={handleChange}
145157
className="hidden"
146158
/>
159+
{imageError && (
160+
<div className="mt-2 text-red-600 font-semibold text-center">
161+
{imageError}
162+
</div>
163+
)}
147164
<div className="mt-4 font-bold text-3xl text-[#C3A041] text-center">
148165
{formData.org_name}
149166
</div>
@@ -198,7 +215,7 @@ export default function EditProfilePage() {
198215
<button
199216
type="button"
200217
onClick={() => setShowPassword(!showPassword)}
201-
className="absolute right-4 top-1/2 transform -translate-y-1/2 text-[#C3A041] hover:text-[#00353D]"
218+
className="absolute right-4 top-1/2 cursor-pointer transform -translate-y-1/2 text-[#C3A041] hover:text-[#00353D]"
202219
aria-label={showPassword ? "Hide password" : "Show password"}
203220
>
204221
{showPassword ? <Eye className="w-5 h-5" /> : <EyeOff className="w-5 h-5" />}
@@ -209,14 +226,14 @@ export default function EditProfilePage() {
209226
<button
210227
type="button"
211228
onClick={() => router.push("/profile")}
212-
className="px-5 py-2 border-2 border-[#03363D] text-[#03363D] rounded-full text-lg font-medium shadow hover:bg-[#F3FBFD] transition"
229+
className="px-5 py-2 border-2 border-[#03363D] cursor-pointer text-[#03363D] rounded-full text-lg font-medium shadow hover:bg-[#F3FBFD] transition"
213230
>
214231
Cancel
215232
</button>
216233
<button
217234
type="submit"
218-
disabled={submitting}
219-
className="px-7 py-2 bg-[#03363D] text-white rounded-full text-lg font-medium shadow hover:bg-[#065A60] transition"
235+
disabled={submitting || !!imageError}
236+
className="px-7 py-2 bg-[#03363D] text-white cursor-pointer rounded-full text-lg font-medium shadow hover:bg-[#065A60] transition"
220237
>
221238
{submitting ? "Saving..." : "Save"}
222239
</button>

tesfa/src/app/globals.css

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,38 @@
55
--font-sans: var(--font-geist-sans);
66
--font-mono: var(--font-geist-mono);
77
}
8-
98
@media (prefers-color-scheme: dark) {
109
}
11-
1210
body {
1311
background: var(--background);
1412
color: var(--foreground);
1513
font-family: var(--font-josefin-sans),sans-serif;
1614
overflow-y: hidden;
17-
1815
}
1916
input:focus {
2017
outline: none;
2118
}
2219
.bg-active-gradient {
23-
background: linear-gradient(to right, #e6c362, #d3ac45);
20+
background: linear-gradient(to right, #E6C362, #D3AC45);
2421
}
25-
2622
*::-webkit-scrollbar {
2723
width: 12px;
2824
height: 12px;
2925
margin-left: 5px;
3026
}
31-
3227
*::-webkit-scrollbar-track {
33-
background: #f1f1f1;
28+
background: #F1F1F1;
3429
border-radius: 10px;
3530
margin-left: 5px;
3631
}
37-
3832
*::-webkit-scrollbar-thumb {
39-
background-color: #d3ac45;
33+
background-color: #D3AC45;
4034
border-radius: 10px;
41-
border: 3px solid #f1f1f1;
35+
border: 3px solid #F1F1F1;
4236
}
43-
4437
*::-webkit-scrollbar-thumb:hover {
45-
background-color: #d3ac45;
38+
background-color: #D3AC45;
4639
}
47-
4840
.animate-fade-in {
4941
animation: fadeInScale 0.4s;
5042
}
@@ -58,17 +50,12 @@ input:focus {
5850
transform: scale(1);
5951
}
6052
}
61-
62-
6353
.recharts-wrapper:focus,
6454
.recharts-surface:focus,
6555
.recharts-wrapper:focus-visible,
6656
.recharts-surface:focus-visible {
6757
outline: none !important;
6858
}
69-
70-
71-
7259
@keyframes move-rays {
7360
0% {
7461
transform: translateX(0);
@@ -124,3 +111,17 @@ input:focus {
124111
left: 50%;
125112
transform: translate(-50%, -50%);
126113
}
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+
}
127+
}

tesfa/src/app/kanban/components/Taskcard/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export function TaskCard({ task, index, onDelete }: TaskCardProps) {
6767
<LuTrash2 size={16}/>
6868
</button>
6969

70-
<div className={`${getCardColor(task.status)} border-none rounded-2xl h-[20vh] sm:h-[18vh] md:h-[20vh] text-white p-3 sm:p-4 mb-3 shadow-lg hover:shadow-xl transition-shadow w-full`}>
70+
<div className={`${getCardColor(task.status)} border-none rounded-2xl h-auto text-white p-3 sm:p-4 mb-3 shadow-lg hover:shadow-xl transition-shadow w-full`}>
7171
<div {...listeners} {...attributes} className="w-full">
7272
<div className="space-y-1 sm:space-y-2">
7373
<h4 className="font-medium text-lg sm:text-base">{task.title}</h4>

0 commit comments

Comments
 (0)