Skip to content

Commit

Permalink
add:feat all charts
Browse files Browse the repository at this point in the history
  • Loading branch information
Just-a-Pirate committed Apr 26, 2024
1 parent 44e0264 commit c3ade95
Show file tree
Hide file tree
Showing 2 changed files with 259 additions and 46 deletions.
182 changes: 137 additions & 45 deletions frontend/app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { HttpCodes } from "@/types/HttpCodes";
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, useDisclosure } from "@nextui-org/modal";
import { set } from "react-hook-form";
import { Input } from "@nextui-org/input";
import { DonutChart } from "@tremor/react";
import { DonutChart, Legend, CustomTooltipProps } from "@tremor/react";


axios.defaults.withCredentials = true;
Expand Down Expand Up @@ -175,6 +175,95 @@ const AdminHomepage = () => {
}
}

var dataPostsDonut = [{
Status: "Pending ",
Posts: posts.filter(post => post.status == "open").length
},
{
Status: "Closed ",
Posts: posts.filter(post => post.status == "closed").length
},
{
Status: "Completed ",
Posts: posts.filter(post => post.status == "completed").length
}];

var dataReportsDonut = [{
Status: "Open ",
Reports: reports.filter(reports => reports.status == "open").length
},
{
Status: "Closed ",
Reports: reports.filter(reports => reports.status == "closed").length
}];

//Donut chart colors
const reportsDonutCol = ['orange-500', 'blue-600']
const postsDonutCol = ['teal-500', 'blue-600', 'orange-500']
const usersDonutCol = ['lime-500', 'violet-600', 'orange-500']

var dataUsersDonut = [{
Role: "Default",
Users: users.filter(user => user.role == "user").length
},
{
Role: "Admin",
Users: users.filter(user => user.role == "admin").length
},
{
Role: "Banned",
Users: users.filter(user => user.role == "banned").length
}]


const valueFormatterPosts = (number: number,) => {
const total = dataPostsDonut.reduce(
(accumulator, currentValue) => accumulator + currentValue.Posts,
0,
)
const percentage = Math.round((number / total) * 100)
return `\n${percentage}% Posts`
}

const valueFormatterReports = (number: number,) => {
const total = dataReportsDonut.reduce(
(accumulator, currentValue) => accumulator + currentValue.Reports,
0,
)
const percentage = Math.round((number / total) * 100)
return `\n${percentage}% Posts`
}

const valueFormatterUsers = (number: number,) => {
const total = dataUsersDonut.reduce(
(accumulator, currentValue) => accumulator + currentValue.Users,
0,
)
const percentage = Math.round((number / total) * 100)
return `\n${percentage}% Users`
}

const customTooltip = (props: CustomTooltipProps) => {
const { payload, active } = props;
if (!active || !payload) return null;
const categoryPayload = payload?.[0]; if (!categoryPayload) return null;
return (<div
className="dark:invert w-56 rounded-tremor-default border border-tremor-border dark:border-dark-tremor-border bg-tremor-background dark:bg-dark-tremor-background p-2 text-tremor-default shadow-tremor-dropdown">
<div className="flex flex-1 space-x-2.5">
<div className={`flex w-1.5 flex-col bg-${categoryPayload?.color}-500 rounded`} />
<div className="w-full">
<div className="flex items-center justify-between space-x-8">
<p className="whitespace-nowrap text-right text-tremor-content dark:text-dark-tremor-brand-emphasis">
{categoryPayload.name} </p>
<p className="whitespace-nowrap text-right font-medium text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis">
{categoryPayload.value}
</p>
</div>
</div>
</div>
</div>);
};

return (
<div>
<h1 className={title()}>Admin Home</h1>
Expand Down Expand Up @@ -286,57 +375,60 @@ const AdminHomepage = () => {
</CardBody>
</Card>
</div>
<div className="md:flex">
<Card className="dark:bg-slate-700 md:mx-2 my-2 xl:max-w-sm rounded-xl w-full p-3">
<DonutChart
data={
[{
Status: "Pending ",
Posts: posts.filter(post => post.status == "open").length
},
{
Status: "Closed ",
Posts: posts.filter(post => post.status == "closed").length
},
{
Status: "Completed ",
Posts: posts.filter(post => post.status == "completed").length
}]
}
index="Status"
category="Posts"


<div className="md:flex ">

{/* Users Donut chart */}
<Card className="dark:bg-slate-800 md:mx-2 my-2 xl:max-w-sm rounded-xl w-full p-3 content-center">
<DonutChart className="dark:invert"
data={dataUsersDonut}
valueFormatter={valueFormatterUsers} //currently formats total as well
label={(users.length).toString()}
index="Role"
category="Users"
variant="donut"
colors={[
'white', 'black', '#6b7280']}
colors={usersDonutCol}
showAnimation={true}
customTooltip={customTooltip}
/>
<Legend categories={['Default', 'Admins', 'Banned']}
colors={usersDonutCol} className="max-w-xs dark:invert" />
</Card>
<Card className="bg-white md:mx-2 my-2 xl:max-w-sm rounded-xl w-full p-3">
<DonutChart
data={
[{
Role: "Default",
Users: users.filter(user => user.role == "user").length
},
{
Role: "Admin",
Users: users.filter(user => user.role == "admin").length
},
{
Role: "Banned",
Users: users.filter(user => user.role == "banned").length
}]
}
index="Role"
category="Users"

{/* Reports Donut chart */}
<Card className="dark:bg-indigo-950 md:mx-2 my-2 xl:max-w-sm rounded-xl w-full p-3 content-center">
<DonutChart className="dark:invert"
data={dataReportsDonut}
valueFormatter={valueFormatterReports} //currently formats total as well
label={(reports.length).toString()}
index="Status"
category="Reports"
variant="donut"
colors={[
'white',
'slate',
'red'
]}
colors={reportsDonutCol}
showAnimation={true}
customTooltip={customTooltip}
/>
<Legend categories={['Open', 'Closed']}
colors={reportsDonutCol} className="max-w-xs dark:invert" />
</Card>

{/* Posts Donut chart */}
<Card className="dark:bg-yellow-850 md:mx-2 my-2 xl:max-w-sm rounded-xl w-full p-3">
<DonutChart className="dark:invert"
data={dataPostsDonut}
valueFormatter={valueFormatterPosts} //currently formats total as well
label={(posts.length).toString()}
index="Status"
category="Posts"
variant="donut"
colors={postsDonutCol}
showAnimation={true}
customTooltip={customTooltip}
/>
<Legend categories={['Pending', 'Closed', 'Completed']}
colors={postsDonutCol} className="max-w-xs dark:invert" />
</Card>
</div>
{/* User Summary */}
{message && <p className="text-center text-xl m-2">{message}</p>}
Expand Down
123 changes: 122 additions & 1 deletion frontend/tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {nextui} from '@nextui-org/theme'
const colors = require('tailwindcss/colors');

/** @type {import('tailwindcss').Config} */
module.exports = {
Expand All @@ -9,8 +10,128 @@ module.exports = {
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
],
theme: {
extend: {},
transparent: 'transparent',
current: 'currentColor',
extend: {
colors: {
// light mode
tremor: {
brand: {
faint: colors.blue[50],
muted: colors.blue[200],
subtle: colors.blue[400],
DEFAULT: colors.blue[500],
emphasis: colors.blue[700],
inverted: colors.white,
},
background: {
muted: colors.gray[50],
subtle: colors.gray[100],
DEFAULT: colors.white,
emphasis: colors.gray[700],
},
border: {
DEFAULT: colors.gray[200],
},
ring: {
DEFAULT: colors.gray[200],
},
content: {
subtle: colors.gray[400],
DEFAULT: colors.gray[500],
emphasis: colors.gray[700],
strong: colors.gray[900],
inverted: colors.white,
},
},
// dark mode
'dark-tremor': {
brand: {
faint: '#0B1229',
muted: colors.blue[950],
subtle: colors.blue[800],
DEFAULT: colors.blue[500],
emphasis: colors.blue[400],
inverted: colors.blue[950],
},
background: {
muted: '#131A2B',
subtle: colors.gray[800],
DEFAULT: colors.gray[900],
emphasis: colors.gray[300],
},
border: {
DEFAULT: colors.gray[800],
},
ring: {
DEFAULT: colors.gray[800],
},
content: {
subtle: colors.gray[600],
DEFAULT: colors.gray[500],
emphasis: colors.gray[200],
strong: colors.gray[50],
inverted: colors.gray[950],
},
},
},
boxShadow: {
// light
'tremor-input': '0 1px 2px 0 rgb(0 0 0 / 0.05)',
'tremor-card':
'0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
'tremor-dropdown':
'0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
// dark
'dark-tremor-input': '0 1px 2px 0 rgb(0 0 0 / 0.05)',
'dark-tremor-card':
'0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
'dark-tremor-dropdown':
'0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
},
borderRadius: {
'tremor-small': '0.375rem',
'tremor-default': '0.5rem',
'tremor-full': '9999px',
},
fontSize: {
'tremor-label': ['0.75rem', { lineHeight: '1rem' }],
'tremor-default': ['0.875rem', { lineHeight: '1.25rem' }],
'tremor-title': ['1.125rem', { lineHeight: '1.75rem' }],
'tremor-metric': ['1.875rem', { lineHeight: '2.25rem' }],
},
},
},
safelist: [
{
pattern:
/^(bg-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/,
variants: ['hover', 'ui-selected'],
},
{
pattern:
/^(text-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/,
variants: ['hover', 'ui-selected'],
},
{
pattern:
/^(border-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/,
variants: ['hover', 'ui-selected'],
},
{
pattern:
/^(ring-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/,
},
{
pattern:
/^(stroke-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/,
},
{
pattern:
/^(fill-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/,
},
],
plugins: [require('@headlessui/tailwindcss')],
darkMode: "class",
plugins: [nextui()],
}

0 comments on commit c3ade95

Please sign in to comment.