Skip to content

Commit 9cf4407

Browse files
committed
2 parents cdba960 + 8eb9cc6 commit 9cf4407

23 files changed

Lines changed: 2219 additions & 66 deletions

public/message_icon.png

801 Bytes
Loading

public/strk.png.svg

Lines changed: 9 additions & 0 deletions
Loading

src/app/dashboard/admin/components/admin-sidenavbar.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313

1414
import Link from "next/link";
1515
import { usePathname } from "next/navigation";
16+
import { WalletDisplay } from "@/components/blockchain/WalletDisplay";
1617

1718
export function Sidebar() {
1819
const pathname = usePathname();
@@ -70,6 +71,11 @@ export function Sidebar() {
7071
<span className="font-semibold text-[#000b21]">ChainLib</span>
7172
</div>
7273

74+
{/* Wallet Display */}
75+
<div className="p-4 border-b border-[#e7e7e7]">
76+
<WalletDisplay variant="compact" showDropdown={false} />
77+
</div>
78+
7379
<nav className="p-4">
7480
<ul className="space-y-2">
7581
{navItems.map((item) => (
Lines changed: 250 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,260 @@
1-
"use-client";
1+
"use client";
2+
3+
import React from "react";
4+
import { useState } from "react";
25
import { Header } from "@/components/dashboard/header";
6+
import { useRouter } from "next/navigation";
7+
8+
import {
9+
Users,
10+
UserCheck,
11+
BookOpen,
12+
UserPlus,
13+
Search,
14+
Filter,
15+
SortAsc,
16+
} from "lucide-react";
17+
18+
const UserManagment = () => {
19+
const [activeTab, setActiveTab] = useState("Readers");
20+
const [searchTerm, setSearchTerm] = useState("");
21+
const router = useRouter();
22+
23+
const statsCards = [
24+
{ title: "Writers", value: "257", icon: Users, bgColor: "bg-white" },
25+
{
26+
title: "Verified Writers",
27+
value: "83",
28+
icon: UserCheck,
29+
bgColor: "bg-white",
30+
},
31+
{ title: "Readers", value: "1093", icon: BookOpen, bgColor: "bg-white" },
32+
{
33+
title: "Subscribed Readers",
34+
value: "204",
35+
icon: UserPlus,
36+
bgColor: "bg-white",
37+
},
38+
];
39+
40+
const additionalStats = [
41+
{ title: "Total Users", value: "257", icon: Users, bgColor: "bg-white" },
42+
];
343

44+
const readersData = [
45+
{
46+
name: "Jane Doe",
47+
wallet: "0xABC...789",
48+
joinedDate: "27 May, 2025",
49+
booksPurchased: 13,
50+
readingRank: "Bookworm",
51+
},
52+
{
53+
name: "Ole Paul",
54+
wallet: "0xABC...789",
55+
joinedDate: "7 June, 2025",
56+
booksPurchased: 3,
57+
readingRank: "Enthusiast",
58+
},
59+
{
60+
name: "Aminu Sani",
61+
wallet: "0xABC...789",
62+
joinedDate: "27 May, 2025",
63+
booksPurchased: 9,
64+
readingRank: "Scholar",
65+
},
66+
{
67+
name: "Faith Adamu",
68+
wallet: "0xABC...789",
69+
joinedDate: "7 June, 2025",
70+
booksPurchased: 11,
71+
readingRank: "Connoisseur",
72+
},
73+
{
74+
name: "Wood Word",
75+
wallet: "0xABC...789",
76+
joinedDate: "27 May, 2025",
77+
booksPurchased: 4,
78+
readingRank: "Scholar",
79+
},
80+
];
481

5-
export default function UserManagment() {
82+
type StatCardProps = {
83+
title: string;
84+
value: string;
85+
icon: React.ElementType;
86+
bgColor: string;
87+
};
88+
89+
const StatCard: React.FC<StatCardProps> = ({ title, value, icon: Icon, bgColor }) => (
90+
<div
91+
className={`${bgColor} rounded-lg p-6 shadow-sm border border-gray-200`}
92+
>
93+
<div className="flex items-center justify-between">
94+
<div>
95+
<p className="text-sm font-medium text-gray-600">{title}</p>
96+
<p className="text-2xl font-bold text-gray-900 mt-1">{value}</p>
97+
</div>
98+
<div className="p-2 bg-gray-100 rounded-lg">
99+
<Icon className="h-6 w-6 text-gray-600" />
100+
</div>
101+
</div>
102+
</div>
103+
);
6104

7105
return (
8106
<>
9-
<Header title="User Managements" />
10-
<div className="space-y-6">
11-
<div className="flex flex-col items-center justify-center h-screen">
12-
<h1 className="text-2xl font-bold text-gray-800">User Management</h1>
13-
<p className="text-gray-600 mt-2">
14-
Welcome to user management section of the admin dashboard! Here, you can manage all aspects of user accounts, including registration, profiles, and permissions. This space is designed to help you maintain a secure and organized user base, ensuring that users have the appropriate access and capabilities within your platform.
15-
</p>
107+
<Header title="User Managements" />
108+
109+
<div className="min-h-screen bg-gray-50 p-4 md:p-6">
110+
<div className="w-full mx-auto">
111+
{/* Stats Cards Grid */}
112+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
113+
{statsCards.map((card, index) => (
114+
<StatCard key={index} {...card} />
115+
))}
116+
</div>
117+
118+
{/* Additional Stats Row */}
119+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
120+
{additionalStats.map((card, index) => (
121+
<StatCard key={index} {...card} />
122+
))}
123+
{/* Empty placeholders for consistent grid */}
124+
<div className="hidden lg:block"></div>
125+
<div className="hidden lg:block"></div>
126+
<div className="hidden lg:block"></div>
127+
</div>
128+
129+
{/* Main Content Area */}
130+
<div className="bg-white rounded-lg shadow-sm border border-gray-200">
131+
{/* Tab Navigation */}
132+
<div className="border-b border-gray-200">
133+
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between p-4">
134+
<div className="flex space-x-1 mb-4 sm:mb-0">
135+
{["Readers", "Writers"].map((tab) => (
136+
<button
137+
key={tab}
138+
onClick={() => setActiveTab(tab)}
139+
className={`px-4 py-2 text-sm font-medium rounded-md transition-colors ${
140+
activeTab === tab
141+
? "bg-blue-600 text-white"
142+
: "text-gray-500 hover:text-gray-700"
143+
}`}
144+
>
145+
{tab}
146+
</button>
147+
))}
148+
</div>
149+
150+
{/* Search and Filter Controls */}
151+
<div className="flex flex-col sm:flex-row gap-2">
152+
<div className="relative">
153+
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-4 w-4" />
154+
<input
155+
type="text"
156+
placeholder="Search for a Reader"
157+
value={searchTerm}
158+
onChange={(e) => setSearchTerm(e.target.value)}
159+
className="pl-10 pr-4 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent w-full sm:w-64"
160+
/>
161+
</div>
162+
<button className="flex items-center gap-2 px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50">
163+
<SortAsc className="h-4 w-4" />
164+
Sort
165+
</button>
166+
<button className="flex items-center gap-2 px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50">
167+
<Filter className="h-4 w-4" />
168+
Filter
169+
</button>
170+
</div>
171+
</div>
172+
</div>
173+
174+
{/* Table */}
175+
<div className="overflow-x-auto">
176+
<table className="w-full">
177+
<thead className="bg-gray-50">
178+
<tr>
179+
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
180+
Reader Name
181+
</th>
182+
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
183+
Wallet Address
184+
</th>
185+
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
186+
Joined Date
187+
</th>
188+
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
189+
Books Purchased
190+
</th>
191+
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
192+
Reading Rank
193+
</th>
194+
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
195+
Action
196+
</th>
197+
</tr>
198+
</thead>
199+
<tbody className="bg-white divide-y divide-gray-200">
200+
{readersData
201+
.filter((reader) =>
202+
reader.name
203+
.toLowerCase()
204+
.includes(searchTerm.toLowerCase())
205+
)
206+
.map((reader, index) => (
207+
<tr
208+
key={index}
209+
className="hover:bg-gray-50 cursor-pointer"
210+
onClick={() => router.push(`/dashboard/admin/user-management/readers/${encodeURIComponent(reader.name)}`)}
211+
>
212+
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
213+
{reader.name}
214+
</td>
215+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
216+
{reader.wallet}
217+
</td>
218+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
219+
{reader.joinedDate}
220+
</td>
221+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
222+
{reader.booksPurchased}
223+
</td>
224+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
225+
{reader.readingRank}
226+
</td>
227+
<td className="px-6 py-4 whitespace-nowrap text-sm">
228+
<button
229+
className="text-blue-600 hover:text-blue-900 font-medium"
230+
onClick={e => {
231+
e.stopPropagation();
232+
router.push(`/dashboard/admin/user-management/readers/${encodeURIComponent(reader.name)}`);
233+
}}
234+
>
235+
View Profile
236+
</button>
237+
</td>
238+
</tr>
239+
))}
240+
</tbody>
241+
</table>
242+
</div>
243+
244+
{/* Pagination */}
245+
<div className="flex flex-col sm:flex-row items-center justify-between px-6 py-4 border-t border-gray-200">
246+
<div className="text-sm text-gray-500 mb-4 sm:mb-0">
247+
Showing 1 to 5 of 12
248+
</div>
249+
<button className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50">
250+
View All
251+
</button>
252+
</div>
253+
</div>
16254
</div>
17255
</div>
18256
</>
19257
);
20-
}
258+
};
259+
260+
export default UserManagment;

0 commit comments

Comments
 (0)