From f5b7cb2098bf4983d8302ddd20f53fc829ded6a5 Mon Sep 17 00:00:00 2001 From: pryingmoth Date: Fri, 2 May 2025 14:29:30 +0300 Subject: [PATCH 01/11] disconnect button, tp donut --- src/assets/styles/components/_chart.css | 1 + src/assets/styles/components/index.css | 1 + .../CustomRainbowKit/UserDisconnect.tsx | 28 ++++ .../layouts/AuthLayout/AuthLayout.tsx | 10 ++ src/components/layouts/ModernLayout.tsx | 1 - src/components/ui/Button/Button.tsx | 27 +++- src/constants/chart.constant.ts | 23 +++ src/views/main/Scores/Scores.tsx | 4 +- src/views/main/Team/OrganizationCard.tsx | 2 +- src/views/main/Team/Team.tsx | 152 +++++++++++++++--- 10 files changed, 223 insertions(+), 26 deletions(-) create mode 100644 src/assets/styles/components/_chart.css create mode 100644 src/components/collabberry/custom-components/CustomRainbowKit/UserDisconnect.tsx diff --git a/src/assets/styles/components/_chart.css b/src/assets/styles/components/_chart.css new file mode 100644 index 0000000..d67191d --- /dev/null +++ b/src/assets/styles/components/_chart.css @@ -0,0 +1 @@ +.apexcharts-canvas { margin-left: 0 !important; margin-right: 0 !important; } diff --git a/src/assets/styles/components/index.css b/src/assets/styles/components/index.css index 9383980..a69f033 100644 --- a/src/assets/styles/components/index.css +++ b/src/assets/styles/components/index.css @@ -1,4 +1,5 @@ @import "./_alert.css"; +@import "./_chart.css"; @import "./_avatar.css"; @import "./_badge.css"; @import "./_button.css"; diff --git a/src/components/collabberry/custom-components/CustomRainbowKit/UserDisconnect.tsx b/src/components/collabberry/custom-components/CustomRainbowKit/UserDisconnect.tsx new file mode 100644 index 0000000..f44d411 --- /dev/null +++ b/src/components/collabberry/custom-components/CustomRainbowKit/UserDisconnect.tsx @@ -0,0 +1,28 @@ +import Button from "@/components/ui/Button"; +import useAuth from "@/utils/hooks/useAuth"; +import { useAccount } from "wagmi"; + +export const DisconnectButton = () => { + const { signOut } = useAuth(); + const { isConnected } = useAccount(); + + + if (!isConnected) { + return null; + } + + const handleDisconnect = async () => { + try { + await signOut(); + } catch (error) { + console.error("Error disconnecting:", error); + } + }; + + return ( + + ); +}; \ No newline at end of file diff --git a/src/components/layouts/AuthLayout/AuthLayout.tsx b/src/components/layouts/AuthLayout/AuthLayout.tsx index 4403ca3..1a365d6 100644 --- a/src/components/layouts/AuthLayout/AuthLayout.tsx +++ b/src/components/layouts/AuthLayout/AuthLayout.tsx @@ -7,6 +7,15 @@ import { LAYOUT_TYPE_BLANK } from "@/constants/theme.constant"; import Header from "@/components/template/Header"; import CollabberyLogoFull from "@/assets/svg/CollabberryLogoFull"; import { SvgIcon } from "@/components/shared"; +import { DisconnectButton } from "@/components/collabberry/custom-components/CustomRainbowKit/UserDisconnect"; + +const AuthHeaderActionEnd = () => { + return ( + <> + + + ); +}; const AuthLayout = () => { const layoutType = useAppSelector((state) => state.theme.layout.type); @@ -16,6 +25,7 @@ const AuthLayout = () => {
} + headerEnd={} />
diff --git a/src/components/layouts/ModernLayout.tsx b/src/components/layouts/ModernLayout.tsx index d1cecf8..e0c2de1 100644 --- a/src/components/layouts/ModernLayout.tsx +++ b/src/components/layouts/ModernLayout.tsx @@ -20,7 +20,6 @@ const HeaderActionsStart = () => { const HeaderActionsEnd = () => { return ( <> - ); diff --git a/src/components/ui/Button/Button.tsx b/src/components/ui/Button/Button.tsx index 03b5f0a..81d4b0f 100644 --- a/src/components/ui/Button/Button.tsx +++ b/src/components/ui/Button/Button.tsx @@ -11,7 +11,7 @@ import type { ReactNode, ComponentPropsWithRef, MouseEvent } from 'react' export interface ButtonProps extends CommonProps, - Omit, 'onClick'> { + Omit, 'onClick'> { active?: boolean block?: boolean color?: string @@ -21,7 +21,7 @@ export interface ButtonProps onClick?: (e: MouseEvent) => void shape?: TypeAttributes.Shape size?: TypeAttributes.Size - variant?: 'solid' | 'twoTone' | 'plain' | 'default' + variant?: 'solid' | 'twoTone' | 'plain' | 'default' | 'transparent' } type ButtonColor = { @@ -155,15 +155,30 @@ const Button = forwardRef((props, ref) => { return getBtnColor(btn) } + const transparentColor = () => { + const btn = { + bgColor: active + ? `bg-gray-200 dark:bg-gray-700` + : "bg-transparent border border-transparent", + + textColor: `text-gray-300 dark:text-gray-100`, + hoverColor: active + ? "" + : `hover:bg-gray-100/20 dark:hover:bg-gray-700/20`, + + activeColor: `active:bg-gray-100/40 dark:active:bg-gray-700/40`, + }; return getBtnColor(btn); + }; + + const getBtnColor = ({ bgColor, hoverColor, activeColor, textColor, }: ButtonColor) => { - return `${bgColor} ${ - disabled || loading ? disabledClass : hoverColor + ' ' + activeColor - } ${textColor}` + return `${bgColor} ${disabled || loading ? disabledClass : hoverColor + ' ' + activeColor + } ${textColor}` } const btnColor = () => { @@ -174,6 +189,8 @@ const Button = forwardRef((props, ref) => { return twoToneColor() case 'plain': return plainColor() + case 'transparent': + return transparentColor() case 'default': return defaultColor() default: diff --git a/src/constants/chart.constant.ts b/src/constants/chart.constant.ts index d61ac6d..7b8a0fe 100644 --- a/src/constants/chart.constant.ts +++ b/src/constants/chart.constant.ts @@ -37,3 +37,26 @@ export const COLORS_LIGHT = [ COLOR_6_LIGHT, COLOR_7_LIGHT, ] + +export const CUSTOM_COLORS = [ + "#6B7AC7", // Blue Yonder + "#B14D57", // Rose Taupe + "#4A90E2", // Dodger Blue + "#50C878", // Emerald + "#FFA726", // Carrot Orange + "#FDD835", // Dandelion + "#EC407A", // Cerise + "#9575CD", // Amethyst + "#26A69A", // Teal + "#FF7043", // Coral + "#BA68C8", // Wisteria + "#283593", // Dark Blue + "#4DD0E1", // Turquoise + "#AEEA00", // Lime + "#D81B60", // Raspberry + "#00ACC1", // Cyan + "#FFD54F", // Maize + "#5E35B1", // Violet + "#9E9D24", // Olive + "#90A4AE", // Slate Gray + ] \ No newline at end of file diff --git a/src/views/main/Scores/Scores.tsx b/src/views/main/Scores/Scores.tsx index b5a2f58..4ca538e 100644 --- a/src/views/main/Scores/Scores.tsx +++ b/src/views/main/Scores/Scores.tsx @@ -11,17 +11,19 @@ import { HiInformationCircle } from "react-icons/hi"; import { refreshAllRounds } from "@/services/LoadAndDispatchService"; import { MdOutlineAssessment } from "react-icons/md"; import { BsListStars } from "react-icons/bs"; +import { useHandleError } from "@/services/HandleError"; const Scores: React.FC = () => { const dispatch = useDispatch(); const navigate = useNavigate(); + const handleError = useHandleError(); const { allRounds } = useSelector( (state: RootState) => state.auth.rounds ); React.useEffect(() => { - refreshAllRounds(dispatch); + refreshAllRounds(dispatch, handleError); }, [dispatch]); diff --git a/src/views/main/Team/OrganizationCard.tsx b/src/views/main/Team/OrganizationCard.tsx index b016ceb..6f58fbb 100644 --- a/src/views/main/Team/OrganizationCard.tsx +++ b/src/views/main/Team/OrganizationCard.tsx @@ -40,7 +40,7 @@ const OrganizationCard: React.FC = ({ ) } -
+
{organization.name}
diff --git a/src/views/main/Team/Team.tsx b/src/views/main/Team/Team.tsx index 5d96227..bc5a0a5 100644 --- a/src/views/main/Team/Team.tsx +++ b/src/views/main/Team/Team.tsx @@ -23,6 +23,14 @@ import { refreshOrganizationData } from "@/services/LoadAndDispatchService"; import { useHandleError } from "@/services/HandleError"; import { RiMoneyDollarCircleLine } from "react-icons/ri"; import { ethers } from "ethers"; +import { Chart } from "@/components/shared"; +import { COLORS, CUSTOM_COLORS } from "@/constants/chart.constant"; +import { useContractService } from "@/services/ContractsService"; + +interface ChartData { + labels: string[]; + series: number[]; +} const Team: React.FC = () => { const organization = useSelector((state: RootState) => state.auth.org); @@ -41,10 +49,17 @@ const Team: React.FC = () => { const { isOpen: isAgreementDialogOpen, openDialog: openAgreementDialog, closeDialog: closeAgreementDialog } = useDialog(); const { isOpen: isViewAgreementDialogOpen, openDialog: openViewAgreementDialog, closeDialog: closeViewAgreementDialog } = useDialog(); const { isOpen: isEditAgreementDialogOpen, openDialog: openEditAgreementDialog, closeDialog: closeEditAgreementDialog } = useDialog(); + const [totalSupply, setTotalSupply] = useState(0); + const [chartData, setChartData] = useState({ + labels: [], + series: [], + }); const fromDashboard = location.state && location.state.from === "dashboard"; const [loading, setLoading] = useState(false); const [selectedContributor, setSelectedContributor] = useState(null); const [contributorsWithAdminFlag, setContributorsWithAdminFlag] = useState([]); + const { fetchTotalSupply, ethersSigner } = useContractService(); + useEffect(() => { @@ -55,8 +70,17 @@ const Team: React.FC = () => { const response = await checkAdminContributors(organization?.teamPointsContractAddress, organization?.contributors || []); const admins = response.data.adminContributors; const contributorsWithBalance = response.data.contributorsStatusAndBalance; - if (response.status === 'success') { + const labels = contributorsWithBalance.map((contributor: any) => contributor.username); + const series = contributorsWithBalance.map((contributor: any) => + Math.floor(Number(ethers.formatUnits(contributor.balance, 'ether'))) || 0 + ); + const seriesPercentage = contributorsWithBalance.map((contributor: any) => + (((Math.floor(Number(ethers.formatUnits(contributor.balance, 'ether'))) || 0) / totalSupply) * 100) || 0 + ); + setChartData({ labels, series: seriesPercentage }); + // setChartData({ labels, series }); + if (response.status === 'success') { const adminContributorsWithBalance = organization?.contributors.map((contributor) => { const isContractAdmin = admins.some((admin: Contributor) => admin.walletAddress === contributor.walletAddress); const contributorWithBalance = contributorsWithBalance.find((c: Contributor) => c.walletAddress === contributor.walletAddress); @@ -113,6 +137,26 @@ const Team: React.FC = () => { fetchOrganization(); }, []) + + useEffect(() => { + const fetchSupply = async () => { + if (organization?.teamPointsContractAddress && ethersSigner) { + setLoading(true); + const response = await fetchTotalSupply(organization?.teamPointsContractAddress); + if (response.status === 'success' && response.data) { + const { totalSupply } = response.data; + const formattedTotalSupply = Math.floor(Number(ethers.formatUnits(totalSupply, 'ether'))); + setTotalSupply(formattedTotalSupply); + setLoading(false); + } else { + setLoading(false); + + } + } + } + fetchSupply(); + }, [organization.teamPointsContractAddress, ethersSigner]); + const viewAgreement = (contributor: Contributor) => { if (contributor && Object.keys(contributor).length > 0) { setSelectedContributor(contributor); @@ -200,20 +244,37 @@ const Team: React.FC = () => { }, { header: "TP Balance", + cell: (props) => { + const data = props.row.original as any; + const value = data.balance; + + return ( + + {`${Number(value).toLocaleString("en-US", { + minimumFractionDigits: 0, + maximumFractionDigits: 0, + })}`} + + + ); + + }, + }, + { + header: "TP Percentage", accessorKey: "balance", cell: (props) => { const value = props.getValue() as number; - if (value) { - return ( - - {`${Number(value).toLocaleString("en-US", { - minimumFractionDigits: 0, - maximumFractionDigits: 0, - })}`} - - ); - } + return ( + + + {`${((value / totalSupply) * 100).toFixed(2)}%`} + + + + ); + }, }, { @@ -362,14 +423,69 @@ const Team: React.FC = () => {
- +
+ + {chartData.labels.length && chartData.series.length && ( + `${value.toFixed(2)}%` + } + }, + dataLabels: { + formatter: (val: number) => `${val.toFixed(2)}%` + }, + responsive: [ + { + breakpoint: 480, + options: { + chart: { + width: 150, + height: 150, + }, + legend: { + position: 'bottom', + }, + }, + }, + ], + }} + series={chartData.series} + height={125} + width={125} + type="donut" + donutText="TP" /> + )} +
{isAdmin && ( -
+
+//
+// ) : ( +//
+// {/* Conversation History */} +//
+// {conversationHistory.map((message, index) => ( +//
+// {message.type === "assistant" && ( +// // +//
+// )} +//
"), +// }} +// /> +//
+// ))} +//
+ +// {summaryPresented && !finalizeSummary && ( +//
+// +// +//
+// )} + +// {/* Input Area */} +// {(!summaryPresented || +// (summaryPresented && !finalizeSummary)) && ( +//
+//