Skip to content

Commit 1027b49

Browse files
add logins modol
2 parents 8db60b5 + 3ebab71 commit 1027b49

File tree

6 files changed

+530
-36
lines changed

6 files changed

+530
-36
lines changed

src/Chart/ProgressBar.tsx

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

src/Chart/TeamChart.tsx

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import React from 'react';
2+
import { Line } from 'react-chartjs-2';
3+
import {
4+
Chart as ChartJS,
5+
CategoryScale,
6+
LinearScale,
7+
PointElement,
8+
LineElement,
9+
Title,
10+
Tooltip,
11+
Legend,
12+
} from 'chart.js';
13+
14+
ChartJS.register(
15+
CategoryScale,
16+
LinearScale,
17+
PointElement,
18+
LineElement,
19+
Title,
20+
Tooltip,
21+
Legend,
22+
);
23+
24+
interface TeamChartProps {
25+
timeframe?: 'daily' | 'weekly' | 'monthly';
26+
}
27+
28+
const TeamChart: React.FC<TeamChartProps> = ({ timeframe = 'daily' }) => {
29+
const chartData = {
30+
daily: {
31+
labels: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
32+
datasets: [
33+
{
34+
label: 'Andela',
35+
data: [1, 3, 0, 2, 1, 3, 2],
36+
fill: false,
37+
borderColor: '#4F46E5',
38+
tension: 0.4,
39+
}
40+
],
41+
},
42+
weekly: {
43+
labels: ['03', '06', '09', '12', '15', '18', '21', '24', '27', '30', '31', '34', '37', '40', '43', '46', '49', '54'],
44+
datasets: [
45+
{
46+
label: 'Andela',
47+
data: [1, 3, 0, 2, 1, 3, 2, 0, 2, 1, 3, 0, 2, 1, 4, 1, 2, 4],
48+
fill: false,
49+
borderColor: '#4F46E5',
50+
tension: 0.4,
51+
},
52+
],
53+
},
54+
monthly: {
55+
labels: Array.from({ length: 31 }, (_, i) => String(i + 1).padStart(2, '0')),
56+
datasets: [
57+
{
58+
label: 'Andela',
59+
data: Array.from({ length: 31 }, () => Math.floor(Math.random() * 8)),
60+
fill: false,
61+
borderColor: '#4F46E5',
62+
tension: 0.4,
63+
},
64+
],
65+
},
66+
};
67+
68+
const options = {
69+
responsive: true,
70+
maintainAspectRatio: false,
71+
plugins: {
72+
legend: {
73+
position: 'bottom' as const,
74+
},
75+
tooltip: {
76+
mode: 'index' as const,
77+
intersect: false,
78+
},
79+
},
80+
scales: {
81+
y: {
82+
beginAtZero: true,
83+
grid: {
84+
color: '#D1D5DB',
85+
},
86+
ticks: {
87+
color: '#6B7280',
88+
},
89+
},
90+
x: {
91+
grid: {
92+
display: false,
93+
},
94+
ticks: {
95+
color: '#6B7280',
96+
},
97+
},
98+
},
99+
};
100+
101+
return (
102+
<div className="w-full max-w-4xl h-[60vh] max-h-[500px] mx-auto p-4 md:p-6 lg:p-8 bg-white dark:bg-gray-800 rounded-md shadow-md">
103+
<Line data={chartData[timeframe]} options={options} />
104+
</div>
105+
);
106+
};
107+
108+
export default TeamChart;

src/Chart/UsersChart.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ ChartJS.register(
2121
Legend,
2222
);
2323

24-
// eslint-disable-next-line react/function-component-definition
25-
// Rename the function component from usersChart to UsersChart
2624
const UsersChart: React.FC = () => {
2725
const data = {
2826
labels: [
@@ -50,6 +48,7 @@ const UsersChart: React.FC = () => {
5048

5149
const options = {
5250
responsive: true,
51+
maintainAspectRatio: false,
5352
plugins: {
5453
legend: {
5554
position: 'bottom' as const,
@@ -71,8 +70,10 @@ const UsersChart: React.FC = () => {
7170
};
7271

7372
return (
74-
<div className="w-full h-[300px]">
75-
<Line data={data} options={options} className="-ml-8" />
73+
<div
74+
className="w-full max-w-4xl h-[60vh] max-h-[500px] mx-auto p-4 md:p-6 lg:p-8 bg-white dark:bg-gray-800 rounded-md shadow-md"
75+
>
76+
<Line data={data} options={options} />
7677
</div>
7778
);
7879
};

src/components/AdminTeamDetails.tsx

Lines changed: 81 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { useState } from 'react';
22
import { FaAngleDown } from 'react-icons/fa6';
3-
import UsersChart from '../Chart/usersChart';
3+
import TeamChart from '../Chart/TeamChart';
4+
import ProgressBar from '../Chart/ProgressBar';
5+
46
interface TeamData {
57
ttlName?: string;
68
team?: string;
@@ -19,12 +21,32 @@ interface TeamDetailsModalProps {
1921
teamData: TeamData | null;
2022
}
2123

24+
// Add this near the top of your TeamDetailsModal component
25+
const loginStats = {
26+
daily: {
27+
passed: 60,
28+
failed: 40,
29+
total: "200k"
30+
},
31+
weekly: {
32+
passed: 75,
33+
failed: 25,
34+
total: "1.2M"
35+
},
36+
monthly: {
37+
passed: 85,
38+
failed: 15,
39+
total: "5M"
40+
}
41+
};
42+
2243
function TeamDetailsModal({
2344
isOpen,
2445
onClose,
2546
teamData,
2647
}: TeamDetailsModalProps) {
2748
const [activeTab, setActiveTab] = useState<'overview' | 'logins'>('overview');
49+
const [timeframe, setTimeframe] = useState<'daily' | 'weekly' | 'monthly'>('daily');
2850
const [showAttendanceSummary, setShowAttendanceSummary] = useState(false);
2951

3052
const handleAttendanceSummaryEnter = () => setShowAttendanceSummary(true);
@@ -35,17 +57,16 @@ function TeamDetailsModal({
3557
return (
3658
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 backdrop-blur-sm">
3759
<div
38-
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"
60+
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"
3961
style={{ scrollbarWidth: 'thin' }}
4062
>
4163
<div className="flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700">
42-
{/* Tabs for switching */}
4364
<div className="flex gap-10">
4465
<button
4566
onClick={() => setActiveTab('overview')}
4667
className={`text-xl font-semibold ${
4768
activeTab === 'overview'
48-
? 'text-blue-600'
69+
? 'text-primary'
4970
: 'text-gray-800 dark:text-gray-200'
5071
}`}
5172
>
@@ -55,16 +76,14 @@ function TeamDetailsModal({
5576
onClick={() => setActiveTab('logins')}
5677
className={`text-xl font-semibold ${
5778
activeTab === 'logins'
58-
? 'text-blue-600'
79+
? 'text-primary'
5980
: 'text-gray-800 dark:text-gray-200'
6081
}`}
6182
>
6283
Logins
6384
</button>
6485
</div>
6586
<button
66-
type="button"
67-
type="button"
6887
onClick={onClose}
6988
className="p-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
7089
>
@@ -75,9 +94,7 @@ function TeamDetailsModal({
7594
<div className="p-6">
7695
{activeTab === 'overview' && (
7796
<div>
78-
{/* Overview Content */}
7997
<div className="grid grid-cols-2 gap-4">
80-
{/* Display team details */}
8198
{[
8299
['TTL Name', teamData?.ttlName || 'Sostene'],
83100
['Team Name', teamData?.team || 'Team Name'],
@@ -128,16 +145,16 @@ function TeamDetailsModal({
128145
<label className="text-sm font-medium text-gray-500 dark:text-gray-400">
129146
Attendance Summary
130147
<FaAngleDown
131-
className={`ml-2 inline-block ${
148+
className={`ml-2 inline-block transition-transform ${
132149
showAttendanceSummary ? 'rotate-180' : ''
133150
}`}
134151
/>
135152
</label>
136153
{showAttendanceSummary && (
137-
<div className="absolute z-10 bg-white dark:bg-gray-800 p-4 rounded-lg shadow-lg w-[200px]">
138-
<p>Quality: 1.5</p>
139-
<p>Quantity: 2.3</p>
140-
<p>Professionalism: 3.1</p>
154+
<div className="absolute z-10 bg-white dark:bg-gray-800 p-4 rounded-lg shadow-lg w-[200px] border border-gray-200 dark:border-gray-700">
155+
<p className="text-gray-800 dark:text-gray-200">Quality: 1.5</p>
156+
<p className="text-gray-800 dark:text-gray-200">Quantity: 2.3</p>
157+
<p className="text-gray-800 dark:text-gray-200">Professionalism: 3.1</p>
141158
</div>
142159
)}
143160
</div>
@@ -156,25 +173,60 @@ function TeamDetailsModal({
156173
</div>
157174
)}
158175

159-
{activeTab === 'logins' && (
160-
<div className="flex border border-gray-200 dark:border-gray-700 flex-col items-center w-full">
161-
{/* Logins Content */}
162-
<h2 className="text-lg font-semibold mb-4 text-gray-700 dark:text-gray-300">
163-
Logins
164-
</h2>
165-
<p className="text-gray-600 dark:text-gray-400 mb-4">
166-
Daily login statistics.
167-
</p>
168-
{/* Include the chart */}
169-
<UsersChart />
170-
</div>
171-
)}
172-
176+
{activeTab === 'logins' && (
177+
<div className="flex flex-col items-center w-full">
178+
<div className="w-[24rem] py-2 flex justify-center items-center gap-2 rounded-full border border-gray-200 dark:border-gray-700">
179+
<button
180+
onClick={() => setTimeframe('daily')}
181+
className={`w-[7rem] px-4 py-1 border border-gray-600 rounded-full transition-colors ${
182+
timeframe === 'daily'
183+
? 'bg-primary text-white'
184+
: 'text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'
185+
}`}
186+
>
187+
Daily
188+
</button>
189+
<button
190+
onClick={() => setTimeframe('weekly')}
191+
className={`w-[7rem] px-4 py-1 border border-gray-600 rounded-full transition-colors ${
192+
timeframe === 'weekly'
193+
? 'bg-primary text-white'
194+
: 'text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'
195+
}`}
196+
>
197+
Weekly
198+
</button>
199+
<button
200+
onClick={() => setTimeframe('monthly')}
201+
className={`w-[7rem] px-4 py-1 border border-gray-600 rounded-full transition-colors ${
202+
timeframe === 'monthly'
203+
? 'bg-primary text-white'
204+
: 'text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'
205+
}`}
206+
>
207+
Monthly
208+
</button>
209+
</div>
210+
<div className="mt-6 w-full px-4 flex flex-col justify-center">
211+
<div className='flex w-full justify-center gap-5'>
212+
<h3 className="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-2">
213+
Logins Attempt Status
214+
</h3>
215+
<ProgressBar
216+
passedPercentage={loginStats[timeframe].passed}
217+
failedPercentage={loginStats[timeframe].failed}
218+
/>
219+
</div>
220+
<p className="mt-4 ml-[12%]">Total Logins: <span className="font-bold text-primary"> {loginStats[timeframe].total}</span></p>
221+
</div>
173222

223+
<TeamChart timeframe={timeframe} />
224+
</div>
225+
)}
174226
</div>
175227
</div>
176228
</div>
177229
);
178230
}
179231

180-
export default TeamDetailsModal;
232+
export default TeamDetailsModal;

0 commit comments

Comments
 (0)