Skip to content

Commit 7fa0614

Browse files
committed
Refactor: extract PageSelectorModal and helpers to reduce cognitive complexity below 15
1 parent fd30d11 commit 7fa0614

File tree

1 file changed

+112
-91
lines changed

1 file changed

+112
-91
lines changed

src/components/Announcements/FacebookConnection.jsx

Lines changed: 112 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ function applyConnectResult(result, setAvailablePages, setSelectionNonce, setSho
3636
}
3737
}
3838

39+
function isManagerRole(role) {
40+
return role === 'Owner' || role === 'Administrator';
41+
}
42+
43+
function loadInitialConnectionStatus(connectionStatus, dispatch) {
44+
if (connectionStatus === null) {
45+
dispatch(getFacebookConnectionStatus());
46+
}
47+
}
48+
3949
function getStatusBadge(connectionStatus) {
4050
if (!connectionStatus?.connected) {
4151
return { text: 'Not Connected', color: '#dc3545', bg: '#f8d7da' };
@@ -49,6 +59,92 @@ function getStatusBadge(connectionStatus) {
4959
return { text: 'Connected', color: '#155724', bg: '#d4edda' };
5060
}
5161

62+
function PageSelectorModal({ availablePages, onSelectPage, onCancel, darkMode }) {
63+
const panelBg = darkMode ? '#111827' : '#fff';
64+
const textColor = darkMode ? '#e5e7eb' : '#333';
65+
const mutedTextColor = darkMode ? '#cbd5e1' : '#666';
66+
const borderColor = darkMode ? '#1f2937' : '#ddd';
67+
68+
const modalOverlay = {
69+
position: 'fixed',
70+
top: 0,
71+
left: 0,
72+
right: 0,
73+
bottom: 0,
74+
backgroundColor: 'rgba(0,0,0,0.5)',
75+
display: 'flex',
76+
justifyContent: 'center',
77+
alignItems: 'center',
78+
zIndex: 1000,
79+
};
80+
const modalContent = {
81+
backgroundColor: panelBg,
82+
padding: '24px',
83+
borderRadius: '8px',
84+
width: '90%',
85+
maxWidth: '450px',
86+
maxHeight: '80vh',
87+
overflow: 'auto',
88+
color: textColor,
89+
};
90+
const pageItemStyle = {
91+
padding: '12px',
92+
border: `1px solid ${borderColor}`,
93+
borderRadius: '6px',
94+
marginBottom: '8px',
95+
cursor: 'pointer',
96+
transition: 'background-color 0.2s',
97+
backgroundColor: panelBg,
98+
color: textColor,
99+
};
100+
const btnCancel = {
101+
backgroundColor: '#6c757d',
102+
color: 'white',
103+
padding: '8px 16px',
104+
borderRadius: '6px',
105+
border: 'none',
106+
cursor: 'pointer',
107+
fontSize: '14px',
108+
marginTop: '12px',
109+
width: '100%',
110+
};
111+
112+
return (
113+
<div style={modalOverlay}>
114+
<div style={modalContent}>
115+
<h4 style={{ marginTop: 0 }}>Select a Facebook Page</h4>
116+
<p style={{ color: mutedTextColor, fontSize: '14px' }}>
117+
Choose the Page you want to connect for posting:
118+
</p>
119+
{availablePages.map(page => (
120+
<div
121+
key={page.pageId}
122+
style={pageItemStyle}
123+
onClick={() => onSelectPage(page)}
124+
onKeyDown={e => e.key === 'Enter' && onSelectPage(page)}
125+
role="button"
126+
tabIndex={0}
127+
onMouseEnter={e => {
128+
e.currentTarget.style.backgroundColor = darkMode ? '#1f2937' : '#f0f0f0';
129+
}}
130+
onMouseLeave={e => {
131+
e.currentTarget.style.backgroundColor = panelBg;
132+
}}
133+
>
134+
<p style={{ margin: 0, fontWeight: 'bold', color: textColor }}>{page.pageName}</p>
135+
<p style={{ margin: '4px 0 0', fontSize: '12px', color: mutedTextColor }}>
136+
{page.category} • ID: {page.pageId}
137+
</p>
138+
</div>
139+
))}
140+
<button type="button" onClick={onCancel} style={btnCancel}>
141+
Cancel
142+
</button>
143+
</div>
144+
</div>
145+
);
146+
}
147+
52148
export default function FacebookConnection() {
53149
const dispatch = useDispatch();
54150
const authUser = useSelector(state => state.auth?.user);
@@ -72,15 +168,10 @@ export default function FacebookConnection() {
72168
const [selectionNonce, setSelectionNonce] = useState(null);
73169
const [showPageSelector, setShowPageSelector] = useState(false);
74170

75-
const canManageConnection = useMemo(() => {
76-
const role = authUser?.role;
77-
return role === 'Owner' || role === 'Administrator';
78-
}, [authUser?.role]);
171+
const canManageConnection = useMemo(() => isManagerRole(authUser?.role), [authUser?.role]);
79172

80173
useEffect(() => {
81-
if (connectionStatus === null) {
82-
dispatch(getFacebookConnectionStatus());
83-
}
174+
loadInitialConnectionStatus(connectionStatus, dispatch);
84175
}, [dispatch, connectionStatus]);
85176

86177
const handleConnect = async () => {
@@ -140,6 +231,12 @@ export default function FacebookConnection() {
140231
}
141232
};
142233

234+
const handleCancelPageSelect = () => {
235+
setShowPageSelector(false);
236+
setAvailablePages([]);
237+
setSelectionNonce(null);
238+
};
239+
143240
const statusBadge = getStatusBadge(connectionStatus);
144241

145242
// Styles
@@ -198,89 +295,6 @@ export default function FacebookConnection() {
198295
fontSize: '14px',
199296
};
200297

201-
const modalOverlay = {
202-
position: 'fixed',
203-
top: 0,
204-
left: 0,
205-
right: 0,
206-
bottom: 0,
207-
backgroundColor: 'rgba(0,0,0,0.5)',
208-
display: 'flex',
209-
justifyContent: 'center',
210-
alignItems: 'center',
211-
zIndex: 1000,
212-
};
213-
214-
const modalContent = {
215-
backgroundColor: panelBg,
216-
padding: '24px',
217-
borderRadius: '8px',
218-
width: '90%',
219-
maxWidth: '450px',
220-
maxHeight: '80vh',
221-
overflow: 'auto',
222-
color: textColor,
223-
};
224-
225-
const pageItemStyle = {
226-
padding: '12px',
227-
border: `1px solid ${borderColor}`,
228-
borderRadius: '6px',
229-
marginBottom: '8px',
230-
cursor: 'pointer',
231-
transition: 'background-color 0.2s',
232-
backgroundColor: panelBg,
233-
color: textColor,
234-
};
235-
236-
const renderPageSelectorModal = () => {
237-
if (!showPageSelector) return null;
238-
return (
239-
<div style={modalOverlay}>
240-
<div style={modalContent}>
241-
<h4 style={{ marginTop: 0 }}>Select a Facebook Page</h4>
242-
<p style={{ color: mutedTextColor, fontSize: '14px' }}>
243-
Choose the Page you want to connect for posting:
244-
</p>
245-
246-
{availablePages.map(page => (
247-
<div
248-
key={page.pageId}
249-
style={pageItemStyle}
250-
onClick={() => handleSelectPage(page)}
251-
onKeyDown={e => e.key === 'Enter' && handleSelectPage(page)}
252-
role="button"
253-
tabIndex={0}
254-
onMouseEnter={e => {
255-
e.currentTarget.style.backgroundColor = darkMode ? '#1f2937' : '#f0f0f0';
256-
}}
257-
onMouseLeave={e => {
258-
e.currentTarget.style.backgroundColor = panelBg;
259-
}}
260-
>
261-
<p style={{ margin: 0, fontWeight: 'bold', color: textColor }}>{page.pageName}</p>
262-
<p style={{ margin: '4px 0 0', fontSize: '12px', color: mutedTextColor }}>
263-
{page.category} • ID: {page.pageId}
264-
</p>
265-
</div>
266-
))}
267-
268-
<button
269-
type="button"
270-
onClick={() => {
271-
setShowPageSelector(false);
272-
setAvailablePages([]);
273-
setSelectionNonce(null);
274-
}}
275-
style={{ ...btnDanger, backgroundColor: '#6c757d', marginTop: '12px', width: '100%' }}
276-
>
277-
Cancel
278-
</button>
279-
</div>
280-
</div>
281-
);
282-
};
283-
284298
if (loading) {
285299
return (
286300
<div style={containerStyle}>
@@ -389,7 +403,14 @@ export default function FacebookConnection() {
389403
)}
390404

391405
{/* Page Selection Modal */}
392-
{renderPageSelectorModal()}
406+
{showPageSelector && (
407+
<PageSelectorModal
408+
availablePages={availablePages}
409+
onSelectPage={handleSelectPage}
410+
onCancel={handleCancelPageSelect}
411+
darkMode={darkMode}
412+
/>
413+
)}
393414
</div>
394415
);
395416
}

0 commit comments

Comments
 (0)