Skip to content

Commit

Permalink
Merge branch 'ft-main-admin-dashboard' of https://github.com/atlp-rwa…
Browse files Browse the repository at this point in the history
…nda/atlp-pulse-fn into ft-main-admin-dashboard
  • Loading branch information
JacquelineTuyisenge committed Nov 21, 2024
2 parents 559a8bb + fdc13ed commit 2ac898e
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 88 deletions.
105 changes: 97 additions & 8 deletions src/Chart/TeamChart.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/* eslint-disable no-console */
/* eslint-disable no-restricted-syntax */
/* eslint-disable no-plusplus */
import React from 'react';
import { Line } from 'react-chartjs-2';
import {
Expand All @@ -23,16 +26,102 @@ ChartJS.register(

interface TeamChartProps {
timeframe?: 'daily' | 'weekly' | 'monthly';
CurrentTeam: any[];
loginsbyDate: any[];
}

function TeamChart({ timeframe = 'daily' }: TeamChartProps) {
function TeamChart({
timeframe = 'daily',
CurrentTeam,
loginsbyDate,
}: TeamChartProps) {
function organizeLoginData(loginData: any) {
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
function getWeekNumber(date: any) {
const tempDate: any = new Date(date);
tempDate.setUTCDate(
tempDate.getUTCDate() + 4 - (tempDate.getUTCDay() || 7),
);
const yearStart: any = new Date(
Date.UTC(tempDate.getUTCFullYear(), 0, 1),
);
return Math.ceil(((tempDate - yearStart) / 86400000 + 1) / 7);
}
// Initialize result arrays
const weeklyData = Array(54)
.fill(0)
.map((_, i) => ({ week: i + 1, success: 0, failed: 0 }));
const monthlyData = Array(12)
.fill(0)
.map((_, i) => ({ month: i + 1, success: 0, failed: 0 }));
const dailyData = Array(7)
.fill(0)
.map((_, i) => ({ day: i, success: 0, failed: 0 }));
for (const [dateString, { success, failed }] of Object.entries(
loginData,
) as any) {
const date = new Date(dateString);
const isoWeekNumber = getWeekNumber(date);
const month = date.getUTCMonth();
const dayOfWeek = (date.getUTCDay() + 6) % 7;
const weekStart = new Date(currentDate);
weekStart.setUTCDate(
currentDate.getUTCDate() - currentDate.getUTCDay() + 1,
);
const weekEnd = new Date(weekStart);
weekEnd.setUTCDate(weekStart.getUTCDate() + 6);
if (date >= weekStart && date <= weekEnd) {
dailyData[dayOfWeek].success += success;
dailyData[dayOfWeek].failed += failed;
}
// Weekly data
if (isoWeekNumber <= 54) {
weeklyData[isoWeekNumber - 1].success += success;
weeklyData[isoWeekNumber - 1].failed += failed;
}
// Monthly data
monthlyData[month].success += success;
monthlyData[month].failed += failed;
}
const weekDays = [
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday',
];
const currentWeekData = dailyData.map((data, index) => ({
day: weekDays[index],
success: data.success,
failed: data.failed,
}));
return {
currentWeek: currentWeekData,
weekly: weeklyData,
monthly: monthlyData.map((data, index) => ({
month: new Date(0, index).toLocaleString('en', { month: 'long' }),
success: data.success,
failed: data.failed,
})),
};
}

const organizedData = organizeLoginData(loginsbyDate);

const weeklyDataset = organizedData.weekly
.filter((_, index) => index % 3 === 0)
.map((item) => item.success);

const chartData = {
daily: {
labels: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
datasets: [
{
label: 'Andela',
data: [1, 3, 0, 2, 1, 3, 2],
label: CurrentTeam[0].name,
data: organizedData.currentWeek.map((item: any) => item.success),
fill: false,
borderColor: '#4F46E5',
tension: 0.4,
Expand Down Expand Up @@ -62,22 +151,22 @@ function TeamChart({ timeframe = 'daily' }: TeamChartProps) {
],
datasets: [
{
label: 'Andela',
data: [1, 3, 0, 2, 1, 3, 2, 0, 2, 1, 3, 0, 2, 1, 4, 1, 2, 4],
label: CurrentTeam[0].name,
data: weeklyDataset,
fill: false,
borderColor: '#4F46E5',
tension: 0.4,
},
],
},
monthly: {
labels: Array.from({ length: 31 }, (_, i) =>
labels: Array.from({ length: 12 }, (_, i) =>
String(i + 1).padStart(2, '0'),
),
datasets: [
{
label: 'Andela',
data: Array.from({ length: 31 }, () => Math.floor(Math.random() * 8)),
label: CurrentTeam[0].name,
data: organizedData.monthly.map((item: any) => item.success),
fill: false,
borderColor: '#4F46E5',
tension: 0.4,
Expand Down
3 changes: 2 additions & 1 deletion src/components/AdminDashboardTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ function DashboardTableDesign() {
<TeamDetailsModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
teamData={selectedTeam}
selectedteam={selectedTeam}
Teams={TeamsData?.getAllTeams}
/>
</div>
);
Expand Down
126 changes: 106 additions & 20 deletions src/components/AdminTeamDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import React, { useState } from 'react';
import { FaAngleDown } from 'react-icons/fa6';
import TeamChart from '../Chart/TeamChart';
import ProgressBar from '../Chart/ProgressBar';
import UsersChart from '../Chart/usersChart';

interface TeamData {
ttlName?: string;
team?: string;
teams?: string;
organization?: string;
program?: string;
phase?: string;
Expand All @@ -18,7 +19,8 @@ interface TeamData {
interface TeamDetailsModalProps {
isOpen: boolean;
onClose: () => void;
teamData: TeamData | null;
selectedteam: TeamData | null;
Teams?: any;
}

// Add this near the top of your TeamDetailsModal component
Expand All @@ -43,7 +45,8 @@ const loginStats = {
function TeamDetailsModal({
isOpen,
onClose,
teamData,
selectedteam,
Teams,
}: TeamDetailsModalProps) {
const [activeTab, setActiveTab] = useState<'overview' | 'logins'>('overview');
const [timeframe, setTimeframe] = useState<'daily' | 'weekly' | 'monthly'>(
Expand All @@ -56,6 +59,75 @@ function TeamDetailsModal({

if (!isOpen) return null;

const CurrentTeam = Teams?.filter(
(items: any) => items?.name === selectedteam?.teams,
);

const average =
(parseInt(CurrentTeam[0]?.avgRatings?.quality, 2) +
parseInt(CurrentTeam[0]?.avgRatings?.quantity, 2) +
parseInt(CurrentTeam[0]?.avgRatings?.professional_Skills, 2)) /
3;

const activeMembers = CurrentTeam[0]?.members.filter(
(item: any) => item.status.status !== 'suspended',
);
const droppedMembers = CurrentTeam[0]?.members.filter(
(item: any) => item.status.status === 'suspended',
);
function mapLoginsByDate(team: any) {
if (!team || !Array.isArray(team[0].members)) {
throw new Error('Invalid team object');
}
const loginCounts: any = {};
team[0].members.forEach((member: any) => {
const activities = member.profile?.activity;

if (Array.isArray(activities)) {
activities.forEach((activity) => {
const rawDate = activity.date;
const timestamp = parseInt(rawDate, 10);
if (!Number.isNaN(timestamp)) {
const loginDate = new Date(timestamp).toISOString().split('T')[0];
if (!loginCounts[loginDate]) {
loginCounts[loginDate] = { success: 0, failed: 0 };
}
if (activity.failed === 1) {
loginCounts[loginDate].failed += 1;
} else {
loginCounts[loginDate].success += 1;
}
}
});
}
});
return loginCounts;
}
const loginsbyDate = mapLoginsByDate(CurrentTeam);
const orgName = localStorage.getItem('orgName');

function calculateLoginPercentages(data: any) {
let totalSuccess = 0;
let totalFailed = 0;

// Sum up all successes and failures
Object.values(data).forEach(({ success, failed }: any) => {
totalSuccess += success;
totalFailed += failed;
});

// Calculate percentages
const total = totalSuccess + totalFailed;
const successPercentage = total > 0 ? (totalSuccess / total) * 100 : 0;
const failedPercentage = total > 0 ? (totalFailed / total) * 100 : 0;

return {
successPercentage: successPercentage.toFixed(2),
failedPercentage: failedPercentage.toFixed(2),
totalLogins: total,
};
}

return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 backdrop-blur-sm">
<div
Expand Down Expand Up @@ -101,15 +173,18 @@ function TeamDetailsModal({
<div>
<div className="grid grid-cols-2 gap-4">
{[
['TTL Name', teamData?.ttlName || 'Sostene'],
['Team Name', teamData?.team || 'Team Name'],
['TTL Name', CurrentTeam[0]?.ttl?.profile?.name || 'Sostene'],
['Team Name', selectedteam?.teams || 'Team Name'],
['Organization', selectedteam?.organization || orgName],
[
'Program',
CurrentTeam[0]?.cohort?.program?.name || 'Program Name',
],
[
'Organization',
teamData?.organization || 'Organization Name',
'Phase',
CurrentTeam[0]?.cohort?.phase?.name || 'Current Phase',
],
['Program', teamData?.program || 'Program Name'],
['Phase', teamData?.phase || 'Current Phase'],
['Cohort', teamData?.cohort || 'Current Cohort'],
['Cohort', CurrentTeam[0]?.cohort.name || 'Current Cohort'],
].map(([label, value], idx) => (
// eslint-disable-next-line react/no-array-index-key
<div key={idx} className="space-y-2">
Expand All @@ -132,15 +207,15 @@ function TeamDetailsModal({
Active Members
</p>
<p className="text-xl font-semibold text-green-600 dark:text-green-400">
{teamData?.activeUsers || '0'}
{activeMembers?.length || '0'}
</p>
</div>
<div className="p-4 bg-red-50 dark:bg-red-900/20 rounded-lg">
<p className="text-sm text-gray-600 dark:text-gray-400">
Dropped Members
</p>
<p className="text-xl font-semibold text-red-600 dark:text-red-400">
{teamData?.droppedUsers || '0'}
{droppedMembers?.length || '0'}
</p>
</div>
</div>
Expand All @@ -162,13 +237,14 @@ function TeamDetailsModal({
{showAttendanceSummary && (
<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">
<p className="text-gray-800 dark:text-gray-200">
Quality: 1.5
Quality: {CurrentTeam[0]?.avgRatings?.quality || 0}
</p>
<p className="text-gray-800 dark:text-gray-200">
Quantity: 2.3
Quantity: {CurrentTeam[0]?.avgRatings?.quality || 0}
</p>
<p className="text-gray-800 dark:text-gray-200">
Professionalism: 3.1
Professionalism:{' '}
{CurrentTeam[0]?.avgRatings?.professional_Skills || 0}
</p>
</div>
)}
Expand All @@ -180,7 +256,7 @@ function TeamDetailsModal({
</label>
<div className="p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
<p className="text-lg font-semibold text-blue-600 dark:text-blue-400">
{teamData?.rating || '4.5'} / 5.0
{average || '0'} / 5.0
</p>
</div>
</div>
Expand Down Expand Up @@ -231,20 +307,30 @@ function TeamDetailsModal({
Logins Attempt Status
</h3>
<ProgressBar
passedPercentage={loginStats[timeframe].passed}
failedPercentage={loginStats[timeframe].failed}
passedPercentage={parseInt(
calculateLoginPercentages(loginsbyDate).successPercentage,
10,
)}
failedPercentage={parseInt(
calculateLoginPercentages(loginsbyDate).failedPercentage,
10,
)}
/>
</div>
<p className="mt-4 ml-[12%]">
Total Logins:{' '}
<span className="font-bold text-primary">
{' '}
{loginStats[timeframe].total}
{calculateLoginPercentages(loginsbyDate).totalLogins}
</span>
</p>
</div>

<TeamChart timeframe={timeframe} />
<TeamChart
timeframe={timeframe}
CurrentTeam={CurrentTeam}
loginsbyDate={loginsbyDate}
/>
</div>
)}
</div>
Expand Down
Loading

0 comments on commit 2ac898e

Please sign in to comment.