-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* main admin dashboard * new piechart and stats updated * new piechart and stats updated * new piechart and stats updated * ft-admin-dashboard-can-vieww-table-teams * new piechart and stats updated * Bar Chart changes according to teams workrate * user Growth overtime chart * user Growth overtime chart * ft main admin dashboared * ft(626): Admin Dashboard * ft(626): testing Admin Dashboard --------- Co-authored-by: Tuyisenge2 <[email protected]> Co-authored-by: Bananayosostene <[email protected]> Co-authored-by: shebz2023 <[email protected]> Co-authored-by: JacquelineTuyisenge <[email protected]>
- Loading branch information
1 parent
0c9f0df
commit 0cd551b
Showing
74 changed files
with
3,231 additions
and
1,204 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -473,4 +473,4 @@ | |
"Director": "Directeur", | ||
"Andela": "Andela", | ||
"University of Rwanda": "Université du Rwanda" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -462,4 +462,4 @@ | |
"Director": "Umuyobozi mukuru", | ||
"Andela": "Andela", | ||
"University of Rwanda": "Kaminuza y' u Rwanda" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import React from 'react'; | ||
import { Bar } from 'react-chartjs-2'; | ||
import { | ||
Chart as ChartJS, | ||
CategoryScale, | ||
LinearScale, | ||
BarElement, | ||
Title, | ||
Tooltip, | ||
Legend, | ||
} from 'chart.js'; | ||
import { useQuery } from '@apollo/client'; | ||
import { GET_ALL_TEAMS } from '../queries/team.queries'; | ||
import { FETCH_ALL_RATINGS } from '../queries/ratings.queries'; | ||
|
||
ChartJS.register( | ||
CategoryScale, | ||
LinearScale, | ||
BarElement, | ||
Title, | ||
Tooltip, | ||
Legend, | ||
); | ||
|
||
interface Props {} | ||
|
||
// eslint-disable-next-line react/function-component-definition | ||
const BarChart: React.FC<Props> = () => { | ||
const orgToken = localStorage.getItem('orgToken'); | ||
const { data, loading, error } = useQuery(GET_ALL_TEAMS, { | ||
variables: { | ||
orgToken, | ||
}, | ||
fetchPolicy: 'network-only', | ||
}); | ||
|
||
const { | ||
data: ratingsData, | ||
loading: ratingsLoading, | ||
error: ratingsError, | ||
} = useQuery(FETCH_ALL_RATINGS, { | ||
variables: { | ||
orgToken, | ||
}, | ||
fetchPolicy: 'network-only', | ||
}); | ||
|
||
if (loading) return <p>Loading...</p>; | ||
if (error) return <p>Error: {error.message}</p>; | ||
|
||
if (ratingsLoading) return <p>Loading ratings...</p>; | ||
if (ratingsError) return <p>Error loading ratings: {ratingsError.message}</p>; | ||
|
||
const teamNames = data?.getAllTeams?.map( | ||
(team: { name: string }) => team.name, | ||
); | ||
const ratingsArray = ratingsData?.fetchAllRatings || []; | ||
|
||
const professionalismData = ratingsArray.map( | ||
(rating: { professional_Skills: string }) => | ||
parseFloat(rating.professional_Skills), | ||
); | ||
const qualityData = ratingsArray.map((rating: { quality: string }) => | ||
parseFloat(rating.quality), | ||
); | ||
const quantityData = ratingsArray.map((rating: { quantity: string }) => | ||
parseFloat(rating.quantity), | ||
); | ||
if (!teamNames || teamNames.length === 0) { | ||
return <p>No team data available.</p>; | ||
} | ||
|
||
const datas = { | ||
labels: teamNames, | ||
datasets: [ | ||
{ | ||
label: 'Professionalism', | ||
data: professionalismData, | ||
backgroundColor: '#5A6ACF', | ||
borderRadius: 20, | ||
barThickness: 14, | ||
}, | ||
{ | ||
label: 'Quality', | ||
data: qualityData, | ||
backgroundColor: '#fcffa4', | ||
borderRadius: 20, | ||
barThickness: 14, | ||
}, | ||
{ | ||
label: 'Quantity', | ||
data: quantityData, | ||
backgroundColor: '#9f5233', | ||
borderRadius: 20, | ||
barThickness: 14, | ||
}, | ||
], | ||
}; | ||
|
||
return ( | ||
<div className="w-full h-[300px]"> | ||
<Bar data={datas} options={{ responsive: true }} className="-ml-2" /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default BarChart; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
import { useQuery } from '@apollo/client'; | ||
import React, { useEffect, useState } from 'react'; | ||
import { | ||
LineChart, | ||
Line, | ||
CartesianGrid, | ||
XAxis, | ||
YAxis, | ||
Tooltip, | ||
Legend, | ||
ResponsiveContainer, | ||
} from 'recharts'; | ||
import dayjs from 'dayjs'; | ||
import isoWeek from 'dayjs/plugin/isoWeek'; | ||
import GET_ROLE_QUERY from '../containers/admin-dashBoard/GetRolesQuery'; | ||
|
||
dayjs.extend(isoWeek); | ||
|
||
function UserGrowth() { | ||
const [orgToken, setOrgToken] = useState<string | null>(null); | ||
const [period, setPeriod] = useState<'daily' | 'weekly' | 'monthly'>('daily'); | ||
const [selectedYear, setSelectedYear] = useState<string>( | ||
dayjs().year().toString(), | ||
); | ||
|
||
useEffect(() => { | ||
const token = localStorage.getItem('orgToken'); | ||
setOrgToken(token); | ||
}, []); | ||
|
||
const { data, loading, error } = useQuery(GET_ROLE_QUERY, { | ||
variables: { orgToken }, | ||
skip: !orgToken, | ||
}); | ||
|
||
if (loading) { | ||
return <p>Loading...</p>; | ||
} | ||
|
||
if (error) { | ||
return <p>Error: {error.message}</p>; | ||
} | ||
|
||
const users = data?.getAllUsers || []; | ||
|
||
const userGrowth = (users: any[]) => { | ||
const growthData: { [key: string]: number } = {}; | ||
|
||
users.forEach((user: any) => { | ||
const timestamp = user.createdAt || user.updatedAt; | ||
if (timestamp) { | ||
const date = dayjs(parseInt(timestamp, 10)); | ||
const year = date.year().toString(); | ||
|
||
if (year === selectedYear) { | ||
let periodKey = ''; | ||
if (period === 'daily') { | ||
periodKey = date.format('YYYY-MM-DD'); | ||
} else if (period === 'weekly') { | ||
periodKey = `${date.year()}-W${date.isoWeek()}`; | ||
} else if (period === 'monthly') { | ||
periodKey = date.format('YYYY-MM'); | ||
} | ||
|
||
growthData[periodKey] = (growthData[periodKey] || 0) + 1; | ||
} | ||
} | ||
}); | ||
|
||
const allMonths = Array.from({ length: 12 }, (_, i) => | ||
dayjs().month(i).format('YYYY-MM'), | ||
); | ||
allMonths.forEach((month) => { | ||
if (!growthData[month]) { | ||
growthData[month] = 0; | ||
} | ||
}); | ||
|
||
return Object.entries(growthData).map(([date, count]) => ({ date, count })); | ||
}; | ||
|
||
const growthData = userGrowth(users); | ||
|
||
return ( | ||
<div className="px-9 py-10 bg-tertiary dark:bg-dark-bg"> | ||
<h3 className="text-3xl text-center text-grey-600 font-bold"> | ||
User Growth | ||
</h3> | ||
|
||
<div className="flex flex-wrap flex-row justify-between"> | ||
<div> | ||
<label | ||
htmlFor="year" | ||
style={{ color: '#bdbdbd', marginRight: '10px' }} | ||
> | ||
Year: | ||
</label> | ||
<select | ||
id="year" | ||
value={selectedYear} | ||
onChange={(e) => setSelectedYear(e.target.value)} | ||
style={{ | ||
padding: '5px 10px', | ||
borderColor: '#ccc', | ||
borderRadius: '4px', | ||
color: '#bdbdbd', | ||
}} | ||
> | ||
{Array.from({ length: 5 }).map((_, index) => { | ||
const year = dayjs().year() - index; | ||
return ( | ||
<option key={year} value={year.toString()}> | ||
{year} | ||
</option> | ||
); | ||
})} | ||
</select> | ||
</div> | ||
|
||
<div> | ||
<label | ||
htmlFor="period" | ||
style={{ color: '#bdbdbd', marginRight: '10px' }} | ||
> | ||
Period: | ||
</label> | ||
<select | ||
id="period" | ||
value={period} | ||
onChange={(e) => | ||
setPeriod(e.target.value as 'daily' | 'weekly' | 'monthly') | ||
} | ||
style={{ | ||
padding: '5px 10px', | ||
borderColor: '#ccc', | ||
borderRadius: '4px', | ||
color: '#bdbdbd', | ||
}} | ||
> | ||
<option value="daily">Daily</option> | ||
<option value="weekly">Weekly</option> | ||
<option value="monthly">Monthly</option> | ||
</select> | ||
</div> | ||
</div> | ||
|
||
{growthData.length === 0 ? ( | ||
<p>No data available</p> | ||
) : ( | ||
<div> | ||
<ResponsiveContainer width="100%" height={400}> | ||
<LineChart | ||
data={growthData} | ||
margin={{ top: 20, right: 30, left: 20, bottom: 20 }} | ||
> | ||
<CartesianGrid strokeDasharray="3 3" /> | ||
<XAxis | ||
dataKey="date" | ||
tickFormatter={(str) => { | ||
if (period === 'daily') { | ||
return dayjs(str).format('MMM DD'); | ||
} | ||
if (period === 'weekly') { | ||
return str.split('-')[1]; | ||
} | ||
if (period === 'monthly') { | ||
return dayjs(str).format('MMM YYYY'); | ||
} | ||
return str; | ||
}} | ||
/> | ||
<YAxis | ||
label={{ | ||
value: 'USERS', | ||
angle: -90, | ||
position: 'insideLeft', | ||
style: { fontSize: 14, fill: '#bdbdbd' }, | ||
}} | ||
/> | ||
<Tooltip /> | ||
<Legend /> | ||
<Line | ||
type="monotone" | ||
dataKey="count" | ||
stroke="#8884d8" | ||
name="User(s)" | ||
dot={false} | ||
/> | ||
</LineChart> | ||
</ResponsiveContainer> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
export default UserGrowth; |
Oops, something went wrong.