Skip to content

Commit 3f95cf5

Browse files
committed
Enhance blocked pubkeys UI: add link-based navigation, improve flag count display and add custom block reason modal
1 parent 427886a commit 3f95cf5

4 files changed

Lines changed: 124 additions & 46 deletions

File tree

src/components/blocked-pubkeys/BlockedPubkeys.styles.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,42 @@ export const HeaderWrapper = styled.div`
1515
export const TitleWrapper = styled.div`
1616
flex: 1;
1717
`;
18+
19+
export const NavContainer = styled.div`
20+
display: flex;
21+
margin-bottom: 1rem;
22+
border-bottom: 1px solid var(--border-color);
23+
`;
24+
25+
export const NavLink = styled.div<{ active: boolean }>`
26+
font-size: 16px;
27+
padding: 8px 16px;
28+
cursor: pointer;
29+
color: ${(props) => (props.active ? 'var(--primary-color)' : '#8c8c8c')};
30+
border-bottom: 2px solid ${(props) => (props.active ? 'var(--primary-color)' : 'transparent')};
31+
margin-right: 24px;
32+
transition: all 0.3s;
33+
34+
&:hover {
35+
color: var(--primary-color);
36+
}
37+
`;
38+
39+
export const FlagCountContainer = styled.div`
40+
display: flex;
41+
align-items: center;
42+
justify-content: start;
43+
`;
44+
45+
export const CircularBadge = styled.div<{ color: string }>`
46+
display: flex;
47+
align-items: center;
48+
justify-content: center;
49+
width: 28px;
50+
height: 28px;
51+
background-color: ${(props) => props.color};
52+
color: #fff;
53+
border-radius: 50%;
54+
font-weight: bold;
55+
margin-right: 8px;
56+
`;

src/components/blocked-pubkeys/BlockedPubkeys.tsx

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState } from 'react';
2-
import { Card, Space, Typography, Tabs } from 'antd';
2+
import { Card, Space, Typography } from 'antd';
33
import useBlockedPubkeys from '@app/hooks/useBlockedPubkeys';
44
import { BaseButton } from '@app/components/common/BaseButton/BaseButton';
55
import { ReloadOutlined } from '@ant-design/icons';
@@ -10,10 +10,9 @@ import { useModerationStats } from '@app/hooks/useModerationStats';
1010
import * as S from './BlockedPubkeys.styles';
1111

1212
const { Title, Text } = Typography;
13-
const { TabPane } = Tabs;
1413

1514
export const BlockedPubkeys: React.FC = () => {
16-
const [activeTab, setActiveTab] = useState('1'); // Default to blocked pubkeys tab
15+
const [activeView, setActiveView] = useState<'blocked' | 'flagged'>('blocked');
1716
const {
1817
blockedPubkeys,
1918
count,
@@ -49,26 +48,38 @@ export const BlockedPubkeys: React.FC = () => {
4948
</BaseButton>
5049
</div>
5150

52-
{activeTab === '1' && (
51+
{activeView === 'blocked' && (
5352
<BlockPubkeyForm onSubmit={addBlockedPubkey} disabled={loading} />
5453
)}
5554

56-
<Tabs activeKey={activeTab} onChange={setActiveTab}>
57-
<TabPane tab="Blocked Pubkeys" key="1">
58-
<BlockedPubkeysTable
59-
blockedPubkeys={blockedPubkeys}
60-
loading={loading}
61-
onUnblock={removeBlockedPubkey}
62-
/>
63-
</TabPane>
64-
<TabPane tab="Flagged Pubkeys" key="2">
65-
<FlaggedPubkeysTable
66-
blockedPubkeys={blockedPubkeys}
67-
onBlock={addBlockedPubkey}
68-
disabled={loading}
69-
/>
70-
</TabPane>
71-
</Tabs>
55+
<S.NavContainer>
56+
<S.NavLink
57+
active={activeView === 'blocked'}
58+
onClick={() => setActiveView('blocked')}
59+
>
60+
Blocked Pubkeys
61+
</S.NavLink>
62+
<S.NavLink
63+
active={activeView === 'flagged'}
64+
onClick={() => setActiveView('flagged')}
65+
>
66+
Flagged Pubkeys
67+
</S.NavLink>
68+
</S.NavContainer>
69+
70+
{activeView === 'blocked' ? (
71+
<BlockedPubkeysTable
72+
blockedPubkeys={blockedPubkeys}
73+
loading={loading}
74+
onUnblock={removeBlockedPubkey}
75+
/>
76+
) : (
77+
<FlaggedPubkeysTable
78+
blockedPubkeys={blockedPubkeys}
79+
onBlock={addBlockedPubkey}
80+
disabled={loading}
81+
/>
82+
)}
7283
</Space>
7384
</Card>
7485
);

src/components/blocked-pubkeys/components/BlockedPubkeysTable.tsx

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Table, Input, Button, Modal, Tooltip, Space, Badge, Spin } from 'antd';
33
import { DeleteOutlined, CopyOutlined, SearchOutlined, FlagOutlined } from '@ant-design/icons';
44
import { BlockedPubkey } from '@app/api/blockedPubkeys.api';
55
import { useModerationStats } from '@app/hooks/useModerationStats';
6+
import * as S from '../BlockedPubkeys.styles';
67

78
interface BlockedPubkeysTableProps {
89
blockedPubkeys: BlockedPubkey[];
@@ -91,21 +92,17 @@ export const BlockedPubkeysTable: React.FC<BlockedPubkeysTableProps> = ({
9192
render: (_: any, record: BlockedPubkey) => {
9293
const count = pubkeyFlagCounts[record.pubkey] || 0;
9394
return (
94-
<Space>
95+
<S.FlagCountContainer>
9596
{statsLoading ? (
9697
<Spin size="small" />
9798
) : (
98-
<>
99-
<Badge
100-
count={count}
101-
showZero
102-
color={count > 10 ? 'red' : count > 5 ? 'orange' : 'blue'}
103-
style={{ marginRight: '5px' }}
104-
/>
105-
<FlagOutlined style={{ color: count > 0 ? undefined : '#d9d9d9' }} />
106-
</>
99+
<S.CircularBadge
100+
color={count > 10 ? 'var(--error-color)' : count > 5 ? 'var(--warning-color)' : 'var(--primary-color)'}
101+
>
102+
{count}
103+
</S.CircularBadge>
107104
)}
108-
</Space>
105+
</S.FlagCountContainer>
109106
);
110107
},
111108
sorter: (a: BlockedPubkey, b: BlockedPubkey) =>

src/components/blocked-pubkeys/components/FlaggedPubkeysTable.tsx

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import React, { useState } from 'react';
2-
import { Table, Input, Button, Space, Badge, Spin } from 'antd';
2+
import { Table, Input, Button, Space, Badge, Spin, Modal } from 'antd';
33
import { StopOutlined, SearchOutlined, FlagOutlined } from '@ant-design/icons';
44
import { useModerationStats, UserStat } from '@app/hooks/useModerationStats';
55
import { BlockedPubkey } from '@app/api/blockedPubkeys.api';
6+
import * as S from '../BlockedPubkeys.styles';
67

78
interface FlaggedPubkeysTableProps {
89
blockedPubkeys: BlockedPubkey[]; // Already blocked pubkeys to filter out
@@ -16,6 +17,9 @@ export const FlaggedPubkeysTable: React.FC<FlaggedPubkeysTableProps> = ({
1617
disabled = false,
1718
}) => {
1819
const [searchText, setSearchText] = useState('');
20+
const [blockModalVisible, setBlockModalVisible] = useState(false);
21+
const [currentPubkey, setCurrentPubkey] = useState('');
22+
const [blockReason, setBlockReason] = useState('');
1923
const { stats, loading: statsLoading } = useModerationStats();
2024

2125
// Filter out already blocked pubkeys and return the rest
@@ -40,10 +44,17 @@ export const FlaggedPubkeysTable: React.FC<FlaggedPubkeysTableProps> = ({
4044
item => item.pubkey.toLowerCase().includes(searchText.toLowerCase())
4145
);
4246

43-
const handleBlock = (pubkey: string) => {
44-
// Default reason
45-
const reason = "Blocked due to high flag count";
46-
onBlock(pubkey, reason);
47+
// Show block modal with default reason
48+
const showBlockModal = (pubkey: string, flagCount: number) => {
49+
setCurrentPubkey(pubkey);
50+
setBlockReason(`Blocked due to high flag count (${flagCount} flags)`);
51+
setBlockModalVisible(true);
52+
};
53+
54+
// Handle block confirmation with custom reason
55+
const handleConfirmBlock = async () => {
56+
await onBlock(currentPubkey, blockReason);
57+
setBlockModalVisible(false);
4758
};
4859

4960
const columns = [
@@ -58,15 +69,13 @@ export const FlaggedPubkeysTable: React.FC<FlaggedPubkeysTableProps> = ({
5869
dataIndex: 'count',
5970
key: 'count',
6071
render: (count: number) => (
61-
<Space>
62-
<Badge
63-
count={count}
64-
showZero
65-
color={count > 10 ? 'red' : count > 5 ? 'orange' : 'blue'}
66-
style={{ marginRight: '5px' }}
67-
/>
68-
<FlagOutlined style={{ color: count > 0 ? undefined : '#d9d9d9' }} />
69-
</Space>
72+
<S.FlagCountContainer>
73+
<S.CircularBadge
74+
color={count > 10 ? 'var(--error-color)' : count > 5 ? 'var(--warning-color)' : 'var(--primary-color)'}
75+
>
76+
{count}
77+
</S.CircularBadge>
78+
</S.FlagCountContainer>
7079
),
7180
sorter: (a: UserStat, b: UserStat) => a.count - b.count,
7281
defaultSortOrder: 'descend' as const,
@@ -79,7 +88,7 @@ export const FlaggedPubkeysTable: React.FC<FlaggedPubkeysTableProps> = ({
7988
type="primary"
8089
danger
8190
icon={<StopOutlined />}
82-
onClick={() => handleBlock(record.pubkey)}
91+
onClick={() => showBlockModal(record.pubkey, record.count)}
8392
disabled={disabled}
8493
>
8594
Block
@@ -112,6 +121,28 @@ export const FlaggedPubkeysTable: React.FC<FlaggedPubkeysTableProps> = ({
112121
}}
113122
locale={{ emptyText: statsLoading ? 'Loading...' : 'No flagged pubkeys found' }}
114123
/>
124+
125+
{/* Block Confirmation Modal */}
126+
<Modal
127+
title="Block Pubkey"
128+
open={blockModalVisible}
129+
onOk={handleConfirmBlock}
130+
onCancel={() => setBlockModalVisible(false)}
131+
okText="Block"
132+
okButtonProps={{ danger: true }}
133+
>
134+
<p>Are you sure you want to block this pubkey?</p>
135+
<p><strong>{formatPubkey(currentPubkey)}</strong></p>
136+
<div style={{ marginTop: '16px' }}>
137+
<p>Reason:</p>
138+
<Input.TextArea
139+
value={blockReason}
140+
onChange={(e) => setBlockReason(e.target.value)}
141+
placeholder="Enter reason for blocking"
142+
rows={3}
143+
/>
144+
</div>
145+
</Modal>
115146
</>
116147
);
117148
};

0 commit comments

Comments
 (0)