diff --git a/components/admins/components/__tests__/adminOptions.test.tsx b/components/admins/components/__tests__/adminOptions.test.tsx deleted file mode 100644 index a1b754a..0000000 --- a/components/admins/components/__tests__/adminOptions.test.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { afterEach, describe, expect, test } from 'bun:test'; -import React from 'react'; -import { screen, cleanup, within, fireEvent } from '@testing-library/react'; -import AdminOptions from '@/components/admins/components/adminOptions'; -import matchers from '@testing-library/jest-dom/matchers'; -import { renderWithChainProvider } from '@/tests/render'; -import { mockPoaParams, mockGroup } from '@/tests/mock'; - -expect.extend(matchers); - -const renderWithProps = (props = {}) => { - const defaultProps = { - poaParams: mockPoaParams, - group: mockGroup, - isLoading: false, - address: 'test_address', - admin: 'admin1', - }; - return renderWithChainProvider(); -}; - -describe('AdminOptions', () => { - afterEach(cleanup); - - test('renders loading state correctly', () => { - renderWithProps({ isLoading: true }); - expect(screen.getByText('Admin')).toBeInTheDocument(); - }); - - test('renders admin details correctly when not loading', () => { - renderWithProps(); - expect(screen.getByText('Admin')).toBeInTheDocument(); - expect(screen.getByAltText('Profile Avatar')).toBeInTheDocument(); - const titleContainer = screen.getByLabelText('title'); - expect(within(titleContainer).getByText('title1')).toBeInTheDocument(); - const detailsContainer = screen.getByLabelText('details'); - expect(within(detailsContainer).getByText('details1')).toBeInTheDocument(); - }); - - test('opens description modal on button click', () => { - renderWithProps(); - fireEvent.click(screen.getByLabelText('three-dots')); - const modal = document.getElementById('description-modal') as HTMLDialogElement; - expect(modal).toBeInTheDocument(); - expect(modal.open).toBe(true); - }); -}); diff --git a/components/admins/components/adminOptions.tsx b/components/admins/components/adminOptions.tsx deleted file mode 100644 index a8a5e46..0000000 --- a/components/admins/components/adminOptions.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react'; -import { ExtendedGroupType } from '@/hooks'; - -import { BsThreeDots } from 'react-icons/bs'; -import { DescriptionModal } from '../modals/descriptionModal'; -import ProfileAvatar from '@/utils/identicon'; - -interface AdminOptionsProps { - group: ExtendedGroupType; - isLoading: boolean; - address: string; - admin: string; -} - -export default function AdminOptions({ group, isLoading }: Readonly) { - const handleOpen = () => { - const modal = document.getElementById(`update-admin-modal`) as HTMLDialogElement; - modal?.showModal(); - }; - - const handleDescription = () => { - const modal = document.getElementById(`description-modal`) as HTMLDialogElement; - modal?.showModal(); - }; - - return ( -
-
-

Admin

-
-
- {isLoading &&
} - {!isLoading && ( -
-
- -
- - {group?.ipfsMetadata?.title} - - - - {group?.ipfsMetadata?.details} - - - -
- -
-
- )} - - -
- ); -} diff --git a/components/admins/components/index.tsx b/components/admins/components/index.tsx index c20c7a2..b2a1351 100644 --- a/components/admins/components/index.tsx +++ b/components/admins/components/index.tsx @@ -1,3 +1,2 @@ -export * from './adminOptions'; export * from './stakingParams'; export * from './validatorList'; diff --git a/components/admins/components/validatorList.tsx b/components/admins/components/validatorList.tsx index 6b2cdeb..bf1dba7 100644 --- a/components/admins/components/validatorList.tsx +++ b/components/admins/components/validatorList.tsx @@ -80,7 +80,7 @@ export default function ValidatorList({

Validators @@ -89,7 +89,7 @@ export default function ValidatorList({ setSearchTerm(e.target.value)} /> @@ -97,13 +97,11 @@ export default function ValidatorList({

-
+
-

{groupName}

+

{groupName}

@@ -269,25 +266,25 @@ export default function GroupProposals({
{/* Search and New Proposal section */} -
-

Proposals

+
+

Proposals

setSearchTerm(e.target.value)} /> - +
- - -
+ + +
{/* Table section - will fill remaining space */} @@ -357,25 +354,25 @@ export default function GroupProposals({ handleRowClick(proposal)} - className="hover:bg-base-200 text-black dark:text-white rounded-lg cursor-pointer" + className="group text-black dark:text-white rounded-lg cursor-pointer" > - + {proposal.id.toString()} - + {proposal.title} - + {timeLeft} - + {proposal.messages.length > 0 ? proposal.messages.map((message, index) => (
{getHumanReadableType((message as any)['@type'])}
)) : 'No messages'} - + {isTalliesLoading ? ( ) : ( @@ -388,7 +385,7 @@ export default function GroupProposals({ ) : ( -
No proposals found
+
No proposal was found.
)}
diff --git a/components/groups/components/myGroups.tsx b/components/groups/components/myGroups.tsx index 55e581e..60c0b7d 100644 --- a/components/groups/components/myGroups.tsx +++ b/components/groups/components/myGroups.tsx @@ -83,7 +83,7 @@ export function YourGroups({

My groups @@ -92,7 +92,7 @@ export function YourGroups({ setSearchTerm(e.target.value)} /> @@ -109,71 +109,69 @@ export function YourGroups({

-
- - - - - - - - - - - - - {isLoading - ? // Skeleton - Array(12) - .fill(0) - .map((_, index) => ( - - - - - - - - - )) - : // content - filteredGroups.map((group, index) => ( - 0 - ? proposals[group.policies[0].address] - : [] - } - onSelectGroup={(policyAddress, groupName) => - handleSelectGroup( - policyAddress, - groupName, - (group.policies[0]?.decision_policy as ThresholdDecisionPolicySDKType) - ?.threshold ?? '0' - ) - } - /> - ))} - -
Group NameActive proposalsAuthorsGroup BalanceQualified MajorityGroup address
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ + + + + + + + + + + + + {isLoading + ? // Skeleton + Array(12) + .fill(0) + .map((_, index) => ( + + + + + + + + + )) + : // content + filteredGroups.map((group, index) => ( + 0 + ? proposals[group.policies[0].address] + : [] + } + onSelectGroup={(policyAddress, groupName) => + handleSelectGroup( + policyAddress, + groupName, + (group.policies[0]?.decision_policy as ThresholdDecisionPolicySDKType) + ?.threshold ?? '0' + ) + } + /> + ))} + +
Group NameActive proposalsAuthorsGroup BalanceQualified MajorityGroup address
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -226,7 +224,7 @@ function GroupRow({ return ( { e.stopPropagation(); onSelectGroup( @@ -238,33 +236,35 @@ function GroupRow({ ); }} > - +
{truncateString(groupName, 24)}
- + {activeProposals.length > 0 ? ( - {activeProposals.length} + + {activeProposals.length} + ) : ( '-' )} - + {truncateString( getAuthor(group.ipfsMetadata?.authors) || 'Unknown', getAuthor(group.ipfsMetadata?.authors || '').startsWith('manifest1') ? 6 : 24 )} - + {Number(shiftDigits(balance?.amount ?? '0', -6)).toLocaleString(undefined, { maximumFractionDigits: 6, })}{' '} MFX - {`${(group.policies[0]?.decision_policy as ThresholdDecisionPolicySDKType).threshold ?? '0'} / ${group.total_weight ?? '0'}`} - + {`${(group.policies[0]?.decision_policy as ThresholdDecisionPolicySDKType).threshold ?? '0'} / ${group.total_weight ?? '0'}`} + diff --git a/components/groups/modals/voteDetailsModal.tsx b/components/groups/modals/voteDetailsModal.tsx index 140f409..e6aa8d7 100644 --- a/components/groups/modals/voteDetailsModal.tsx +++ b/components/groups/modals/voteDetailsModal.tsx @@ -66,7 +66,7 @@ function VoteDetailsModal({ const { theme } = useTheme(); - const textColor = theme === 'dark' ? '#E0D1D4' : '#2e2e2e'; + const textColor = theme === 'dark' ? '#FFFFFF' : '#161616'; const normalizedMembers = useMemo( () => @@ -130,6 +130,9 @@ function VoteDetailsModal({ labels: { useSeriesColors: true, }, + markers: { + strokeWidth: 0, + }, }, states: { normal: { @@ -182,7 +185,7 @@ function VoteDetailsModal({ data: chartData, }, ], - colors: ['#00D515', '#F54562', '#FBBD23', '#3B82F6'], + colors: ['#4CAF50', '#E53935', '#FFB300', '#3F51B5'], tooltip: { enabled: false, }, @@ -349,9 +352,9 @@ function VoteDetailsModal({ if (Array.isArray(value)) { return (
-

{key}:

+

{key}:

{value.map((item, index) => ( -
+
{renderMessageField(`Item ${index + 1}`, item, depth + 1)}
))} @@ -360,7 +363,7 @@ function VoteDetailsModal({ } else { return (
-

{key}:

+

{key}:

{Object.entries(value).map(([subKey, subValue]) => renderMessageField(subKey, subValue, depth + 1) )} @@ -370,11 +373,13 @@ function VoteDetailsModal({ } else { return (
-

{key}:

+

{key}:

{typeof value === 'string' && value.match(/^[a-zA-Z0-9]{40,}$/) ? ( ) : ( -

{truncateText(String(value))}

+

+ {truncateText(String(value))} +

)}
); @@ -416,21 +421,25 @@ function VoteDetailsModal({ return ( -
+
- +
-

#{proposal?.id?.toString() ?? '0'}

- +

+ #{proposal?.id?.toString() ?? '0'} +

+ {getStatusLabel(proposal)}
{userHasVoted && (
- Your vote: + Your vote:

TITLE

-

{proposal?.title}

+

+ {proposal?.title} +

SUBMITTED - + {new Date(proposal?.submit_time).toDateString().toLocaleString()}

SUMMARY

-
-

{proposal?.summary}

+
+

{proposal?.summary}

-

MESSAGES

-
+

MESSAGES

+
{proposal?.messages?.map((message: any, index: number) => { const messageType = message['@type']; const fieldsToShow = importantFields[messageType] || defaultFields; return (
-

+

{messageType.split('.').pop().replace('Msg', '')}

@@ -497,24 +508,30 @@ function VoteDetailsModal({

TALLY

-
+

MEMBERS

-
-
+
+
- + - - - @@ -523,12 +540,12 @@ function VoteDetailsModal({ {normalizedMembers?.map((member, index) => { const memberVote = voteMap[member?.address]; return ( - + - - + diff --git a/tailwind.config.js b/tailwind.config.js index c0adb73..2985fff 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -78,50 +78,48 @@ module.exports = { themes: [ { light: { - 'wallet-background': '#1c1c1c1a', - primary: '#A287FF', + primary: '#A087FF', 'primary-content': '#161616', - secondary: '#F0F0FF', + secondary: '#FBFBFF', 'secondary-content': '#161616', accent: '#30DB5B', 'accent-content': '#161616', neutral: '#FFFFFF', 'button-gradient': 'linear-gradient(to right, #A087FF, #380CC5)', - 'neutral-content': '#161616', + 'neutral-content': '#FFFFFF', 'base-100': '#FFFFFF', 'base-200': '#F0F0FF', - 'base-300': '#E1E1F9', + 'base-300': '#F5F5F5', 'base-content': '#161616', 'tooltip-color': '#ffffff', 'background-color': '#F0F0FF', - info: '#3B82F6', - success: '#00D515', - warning: '#FBBD23', - error: '#F54562', + info: '#3F51B5', + success: '#4CAF50', + warning: '#FFB300', + error: '#E53935', }, }, { dark: { - 'wallet-background': '#dcdcdc15', - primary: '#A287FF', + primary: '#A087FF', 'primary-content': '#FFFFFF', secondary: '#1D192D', 'secondary-content': '#FFFFFF', accent: '#30DB5B', 'accent-content': '#FFFFFF', - 'button-gradient': 'linear-gradient(to right, #A087FF, #380CC5)', neutral: '#1D192D', + 'button-gradient': 'linear-gradient(to right, #A087FF, #380CC5)', 'neutral-content': '#FFFFFF', - 'background-color': '#0E0A1F', 'base-100': '#161616', 'base-200': '#1D192D', - 'tooltip-color': '#ffffff', - 'base-300': '#2A2640', + 'base-300': '#272336', 'base-content': '#FFFFFF', - info: '#3B82F6', - success: '#00D515', - warning: '#FBBD23', - error: '#F54562', + 'tooltip-color': '#ffffff', + 'background-color': '#0E0A1F', + info: '#3F51B5', + success: '#4CAF50', + warning: '#FFB300', + error: '#E53935', }, }, ],
+ Address + Weight + Vote
{member?.weight} + {member?.weight} {optionToVote(memberVote?.toString()) || 'N/A'}