Skip to content

Commit 260bcca

Browse files
Merge branch 'ft-main-admin-dashboard' of https://github.com/atlp-rwanda/atlp-pulse-fn into ft-main-admin-dashboard
2 parents baff5fa + 2ac898e commit 260bcca

File tree

8 files changed

+226
-220
lines changed

8 files changed

+226
-220
lines changed

src/Chart/PieChart.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const PieChart: React.FC = () => {
6161
return (
6262
<div className="flex flex-col items-center -ml-8 mb-8">
6363
<div className="flex space-x-8">
64-
<div className="relative w-[200px] h-[200px] bg-red-200 p-2 rounded">
64+
<div className="relative w-[200px] h-[200px] bg-red-200 p-2 rounded">
6565
<Doughnut data={data} options={options} />
6666
<div className="absolute inset-0 flex items-center justify-center">
6767
<div className="text-center">

src/Chart/ProgressBar.tsx

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from 'react';
2+
3+
interface ProgressBarProps {
4+
passedPercentage: number; // Percentage of passed logins
5+
failedPercentage: number; // Percentage of failed logins
6+
}
7+
8+
function ProgressBar({ passedPercentage, failedPercentage }: ProgressBarProps) {
9+
return (
10+
<div className="w-1/2 space-y-4">
11+
<div className="relative h-6 rounded-full overflow-hidden bg-gray-200 dark:bg-gray-700">
12+
<div
13+
className="absolute h-full bg-green-500 text-white text-center"
14+
style={{ width: `${passedPercentage}%` }}
15+
>
16+
{passedPercentage}%
17+
</div>
18+
<div
19+
className="absolute h-full bg-red-500 text-white text-center"
20+
style={{
21+
width: `${failedPercentage}%`,
22+
left: `${passedPercentage}%`,
23+
}}
24+
>
25+
{failedPercentage}%
26+
</div>
27+
</div>
28+
<div className="flex justify-between text-sm text-gray-600 dark:text-gray-300">
29+
<p className="text-sm text-gray-600 dark:text-gray-300">
30+
<span className="text-green-500 font-semibold">Green</span>: Passed
31+
Logins
32+
</p>
33+
<p className="text-sm text-gray-600 dark:text-gray-300">
34+
<span className="text-red-500 font-semibold">Red</span>: Failed Logins
35+
</p>
36+
</div>
37+
</div>
38+
);
39+
}
40+
41+
export default ProgressBar;

src/components/AdminDashboardTable.tsx

+21-15
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import { useQuery } from '@apollo/client';
2-
import React from 'react';
2+
import React, { useState } from 'react';
33
import { FaEye } from 'react-icons/fa';
44
import { useTranslation } from 'react-i18next';
55
import DataTable from './DataTable';
66
import { GET_TEAMS_CARDS } from './CoordinatorCard';
7+
import TeamDetailsModal from './AdminTeamDetails';
78

89
function DashboardTableDesign() {
910
const { t } = useTranslation();
11+
const [selectedTeam, setSelectedTeam] = useState<any | null>(null);
12+
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
13+
1014
const {
1115
data: TeamsData,
1216
loading,
@@ -18,6 +22,7 @@ function DashboardTableDesign() {
1822
},
1923
fetchPolicy: 'network-only',
2024
});
25+
2126
const TableData = TeamsData?.getAllTeams.map((items: any) => ({
2227
teams: items.name,
2328
users: items.members.length,
@@ -27,24 +32,28 @@ function DashboardTableDesign() {
2732
),
2833
}));
2934

35+
const handleViewClick = (team: any) => {
36+
setSelectedTeam(team);
37+
setIsModalOpen(true);
38+
};
39+
3040
const organizationColumns = [
3141
{ Header: t('Teams'), accessor: 'teams' },
3242
{ Header: t('Logins'), accessor: 'logins' },
3343
{ Header: t('Users'), accessor: 'users' },
3444
{
3545
Header: t('action'),
3646
accessor: '',
37-
Cell: () => (
38-
<>
39-
<button
40-
type="button"
41-
className="flex items-center space-x-2 text-blue-500 hover:text-blue-700"
42-
aria-label="View"
43-
>
44-
<FaEye className="w-4 h-4" />
45-
<span>{t('View')}</span>
46-
</button>
47-
</>
47+
Cell: ({ row }: any) => (
48+
<button
49+
type="button"
50+
className="flex items-center space-x-2 text-blue-500 hover:text-blue-700"
51+
aria-label="View"
52+
onClick={() => handleViewClick(row.original)}
53+
>
54+
<FaEye className="w-4 h-4" />
55+
<span>{t('View')}</span>
56+
</button>
4857
),
4958
},
5059
];
@@ -54,16 +63,13 @@ function DashboardTableDesign() {
5463
columns={organizationColumns}
5564
data={TableData ? (TableData as any[]) : []}
5665
title={t('Teams metrices')}
57-
<<<<<<< HEAD
58-
=======
5966
loading={loading}
6067
/>
6168
<TeamDetailsModal
6269
isOpen={isModalOpen}
6370
onClose={() => setIsModalOpen(false)}
6471
selectedteam={selectedTeam}
6572
Teams={TeamsData?.getAllTeams}
66-
>>>>>>> fdc13ed (user Growth overtime chart)
6773
/>
6874
</div>
6975
);

src/components/AdminTeamDetails.tsx

+71-123
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import React, { useState } from 'react';
2-
<<<<<<< HEAD
3-
import { FaAngleDown } from "react-icons/fa6";
4-
=======
52
import { FaAngleDown } from 'react-icons/fa6';
63
import TeamChart from '../Chart/TeamChart';
74
import ProgressBar from '../Chart/ProgressBar';
85
import UsersChart from '../Chart/usersChart';
9-
>>>>>>> fdc13ed (user Growth overtime chart)
106

117
interface TeamData {
128
ttlName?: string;
@@ -27,20 +23,6 @@ interface TeamDetailsModalProps {
2723
Teams?: any;
2824
}
2925

30-
<<<<<<< HEAD
31-
const TeamDetailsModal: React.FC<TeamDetailsModalProps> = ({ isOpen, onClose, teamData }) => {
32-
if (!isOpen) return null;
33-
34-
const [showAttendanceSummary, setShowAttendanceSummary] = useState(false);
35-
36-
const handleAttendanceSummaryEnter = () => {
37-
setShowAttendanceSummary(true);
38-
};
39-
40-
const handleAttendanceSummaryLeave = () => {
41-
setShowAttendanceSummary(false);
42-
};
43-
=======
4426
// Add this near the top of your TeamDetailsModal component
4527
const loginStats = {
4628
daily: {
@@ -145,92 +127,51 @@ function TeamDetailsModal({
145127
totalLogins: total,
146128
};
147129
}
148-
>>>>>>> fdc13ed (user Growth overtime chart)
149130

150131
return (
151132
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 backdrop-blur-sm">
152-
<div className="w-full max-w-4xl max-h-[90vh] overflow-y-auto bg-white dark:bg-gray-800 rounded-xl shadow-lg scrollbar-thumb-gray-400 dark:scrollbar-thumb-gray-600" style={{ scrollbarWidth: 'thin' }}>
133+
<div
134+
className="w-full max-w-4xl max-h-[90vh] overflow-y-auto bg-white dark:bg-gray-800 rounded-xl shadow-lg scrollbar-thumb-gray-400 dark:scrollbar-thumb-gray-600"
135+
style={{ scrollbarWidth: 'thin' }}
136+
>
153137
<div className="flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700">
154-
<div className='flex gap-10'>
155-
<h2 className="text-xl font-semibold text-gray-800 dark:text-gray-200">
138+
<div className="flex gap-10">
139+
<button
140+
type="button"
141+
onClick={() => setActiveTab('overview')}
142+
className={`text-xl font-semibold ${
143+
activeTab === 'overview'
144+
? 'text-primary'
145+
: 'text-gray-800 dark:text-gray-200'
146+
}`}
147+
>
156148
Overview
157-
</h2>
158-
<h2 className="text-xl font-semibold text-gray-800 dark:text-gray-200">
149+
</button>
150+
<button
151+
type="button"
152+
onClick={() => setActiveTab('logins')}
153+
className={`text-xl font-semibold ${
154+
activeTab === 'logins'
155+
? 'text-primary'
156+
: 'text-gray-800 dark:text-gray-200'
157+
}`}
158+
>
159159
Logins
160-
</h2>
160+
</button>
161161
</div>
162162
<button
163+
type="button"
163164
onClick={onClose}
164165
className="p-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
165166
>
166-
<p>Close</p>
167+
Close
167168
</button>
168169
</div>
169170

170-
<div className="p-6 space-y-4">
171-
<div className="grid grid-cols-2 gap-4">
172-
<div className="space-y-2">
173-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
174-
TTL Name
175-
</label>
176-
<p className="text-gray-800 dark:text-gray-200">{teamData?.ttlName || 'Sostene'}</p>
177-
</div>
178-
179-
<div className="space-y-2">
180-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
181-
Team Name
182-
</label>
183-
<p className="text-gray-800 dark:text-gray-200">{teamData?.team}</p>
184-
</div>
185-
186-
<div className="space-y-2">
187-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
188-
Organization
189-
</label>
190-
<p className="text-gray-800 dark:text-gray-200">{teamData?.organization || 'Organization Name'}</p>
191-
</div>
192-
193-
<div className="space-y-2">
194-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
195-
Program
196-
</label>
197-
<p className="text-gray-800 dark:text-gray-200">{teamData?.program || 'Program Name'}</p>
198-
</div>
199-
200-
<div className="space-y-2">
201-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
202-
Phase
203-
</label>
204-
<p className="text-gray-800 dark:text-gray-200">{teamData?.phase || 'Current Phase'}</p>
205-
</div>
206-
207-
<div className="space-y-2">
208-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
209-
Cohort
210-
</label>
211-
<p className="text-gray-800 dark:text-gray-200">{teamData?.cohort || 'Current Cohort'}</p>
212-
</div>
213-
</div>
214-
215-
<div className="space-y-4 mt-6">
216-
<div className="space-y-2">
217-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
218-
Users
219-
</label>
171+
<div className="p-6">
172+
{activeTab === 'overview' && (
173+
<div>
220174
<div className="grid grid-cols-2 gap-4">
221-
<<<<<<< HEAD
222-
<div className="p-4 bg-green-50 dark:bg-green-900/20 rounded-lg">
223-
<p className="text-sm text-gray-600 dark:text-gray-400">Active Members</p>
224-
<p className="text-xl font-semibold text-green-600 dark:text-green-400">
225-
{teamData?.activeUsers || '0'}
226-
</p>
227-
</div>
228-
<div className="p-4 bg-red-50 dark:bg-red-900/20 rounded-lg">
229-
<p className="text-sm text-gray-600 dark:text-gray-400">Dropped Members</p>
230-
<p className="text-xl font-semibold text-red-600 dark:text-red-400">
231-
{teamData?.droppedUsers || '0'}
232-
</p>
233-
=======
234175
{[
235176
['TTL Name', CurrentTeam[0]?.ttl?.profile?.name || 'Sostene'],
236177
['Team Name', selectedteam?.teams || 'Team Name'],
@@ -318,40 +259,48 @@ function TeamDetailsModal({
318259
{average || '0'} / 5.0
319260
</p>
320261
</div>
321-
>>>>>>> fdc13ed (user Growth overtime chart)
322262
</div>
323263
</div>
324264
</div>
325-
326-
<div
327-
className="space-y-2 relative"
328-
onMouseEnter={handleAttendanceSummaryEnter}
329-
onMouseLeave={handleAttendanceSummaryLeave}
330-
>
331-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
332-
Attendance Summary
333-
<FaAngleDown className={`ml-2 inline-block ${showAttendanceSummary ? 'rotate-180' : ''}`} />
334-
</label>
335-
{showAttendanceSummary && (
336-
<div className="absolute z-10 bg-white dark:bg-gray-800 p-4 rounded-lg shadow-lg w-[200px]">
337-
<p>Quality: 1.5</p>
338-
<p>Quantity: 2.3</p>
339-
<p>Professionalism: 3.1</p>
340-
</div>
341-
<<<<<<< HEAD
342-
)}
343-
</div>
344-
345-
<div className="space-y-2">
346-
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
347-
Rating Summary
348-
</label>
349-
<div className="p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
350-
<p className="text-lg font-semibold text-blue-600 dark:text-blue-400">
351-
{teamData?.rating || '4.5'} / 5.0
352-
</p>
265+
)}
266+
267+
{activeTab === 'logins' && (
268+
<div className="flex flex-col items-center w-full">
269+
<div className="w-[24rem] py-2 flex justify-center items-center gap-2 rounded-full border border-gray-200 dark:border-gray-700">
270+
<button
271+
type="button"
272+
onClick={() => setTimeframe('daily')}
273+
className={`w-[7rem] px-4 py-1 border border-gray-600 rounded-full transition-colors ${
274+
timeframe === 'daily'
275+
? 'bg-primary text-white'
276+
: 'text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'
277+
}`}
278+
>
279+
Daily
280+
</button>
281+
<button
282+
type="button"
283+
onClick={() => setTimeframe('weekly')}
284+
className={`w-[7rem] px-4 py-1 border border-gray-600 rounded-full transition-colors ${
285+
timeframe === 'weekly'
286+
? 'bg-primary text-white'
287+
: 'text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'
288+
}`}
289+
>
290+
Weekly
291+
</button>
292+
<button
293+
type="button"
294+
onClick={() => setTimeframe('monthly')}
295+
className={`w-[7rem] px-4 py-1 border border-gray-600 rounded-full transition-colors ${
296+
timeframe === 'monthly'
297+
? 'bg-primary text-white'
298+
: 'text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'
299+
}`}
300+
>
301+
Monthly
302+
</button>
353303
</div>
354-
=======
355304
<div className="mt-6 w-full px-4 flex flex-col justify-center">
356305
<div className="flex w-full justify-center gap-5">
357306
<h3 className="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-2">
@@ -382,13 +331,12 @@ function TeamDetailsModal({
382331
CurrentTeam={CurrentTeam}
383332
loginsbyDate={loginsbyDate}
384333
/>
385-
>>>>>>> fdc13ed (user Growth overtime chart)
386334
</div>
387-
</div>
335+
)}
388336
</div>
389337
</div>
390338
</div>
391339
);
392-
};
340+
}
393341

394-
export default TeamDetailsModal;
342+
export default TeamDetailsModal;

0 commit comments

Comments
 (0)