Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/components/Announcements/Announcements.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,38 @@ button.sendButton:hover {
display: block;
}

.tabIconWrapper {
position: relative;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}

.scheduleBadge {
position: absolute;
top: -6px;
right: -10px;
background: #f55151;
color: #fff;
border-radius: 999px;
font-size: 0.65rem;
font-weight: 700;
padding: 2px 6px;
min-width: 22px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 2px solid #fff;
line-height: 1;
}

.tabNavItem.dark .scheduleBadge {
border-color: #14233a;
}

.tabLabel {
font-size: 0.75rem;
text-align: center;
Expand Down Expand Up @@ -446,4 +478,4 @@ button.sendButton:hover {
-2px 0 6px rgba(0,0,0,0.12),
2px 0 6px rgba(0,0,0,0.12),
0 6px 6px rgba(0,0,0,0.20);
}
}
22 changes: 16 additions & 6 deletions src/components/Announcements/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
import { faFacebook, faLinkedin, faMedium } from '@fortawesome/free-brands-svg-icons';
import ReactTooltip from 'react-tooltip';
import EmailPanel from './platforms/email';
import MyspaceAutoPoster from './platforms/myspace';
import PlatformScheduleBadge from './platforms/PlatformScheduleBadge';

function Announcements({ title, email: initialEmail }) {
const [activeTab, setActiveTab] = useState('email');
Expand Down Expand Up @@ -104,15 +106,19 @@ function Announcements({ title, email: initialEmail }) {
onClick={() => setActiveTab(id)}
aria-selected={activeTab === id}
>
<div className={styles.tabIcon}>
<div className={styles.tabIconWrapper}>
{customIconSrc ? (
<img src={customIconSrc} alt={`${label} icon`} className={styles.tabIcon} />
) : (
<FontAwesomeIcon
icon={icon}
className={styles.tabIcon}
style={{ width: '100%', height: '100%', color: getIconColor(id) }}
/>
)}
{id === 'myspace' && (
<PlatformScheduleBadge platform="myspace" className={styles.scheduleBadge} />
)}
</div>
<div className={styles.tabLabel}>{label}</div>
</NavLink>
Expand Down Expand Up @@ -165,11 +171,15 @@ function Announcements({ title, email: initialEmail }) {
'slashdot',
'blogger',
'truthsocial',
].map(platform => (
<TabPane tabId={platform} key={platform}>
<SocialMediaComposer platform={platform} />
</TabPane>
))}
].map(platform => {
const PlatformComposer =
platform === 'myspace' ? MyspaceAutoPoster : SocialMediaComposer;
return (
<TabPane tabId={platform} key={platform}>
<PlatformComposer platform={platform} />
</TabPane>
);
})}
</TabContent>
</div>
</div>
Expand Down
59 changes: 59 additions & 0 deletions src/components/Announcements/platforms/PlatformScheduleBadge.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useEffect, useState } from 'react';

const scheduleCounts = new Map();
const listeners = new Map();

const getScheduleCount = platform => scheduleCounts.get(platform) || 0;

const notify = (platform, count) => {
const platformListeners = listeners.get(platform);
if (!platformListeners) return;
platformListeners.forEach(listener => {
try {
listener(count);
} catch (error) {
// eslint-disable-next-line no-console
console.error('PlatformScheduleBadge listener error', error);
}
});
};

export const setPlatformScheduleCount = (platform, count) => {
if (!platform) return;
const normalizedCount = Math.max(0, Number.isFinite(count) ? count : 0);
const nextCount = Math.round(normalizedCount);
scheduleCounts.set(platform, nextCount);
notify(platform, nextCount);
};

const subscribeToScheduleCount = (platform, listener) => {
if (!listeners.has(platform)) listeners.set(platform, new Set());
const platformListeners = listeners.get(platform);
platformListeners.add(listener);
return () => {
platformListeners.delete(listener);
if (platformListeners.size === 0) {
listeners.delete(platform);
}
};
};

export const usePlatformScheduleCount = platform => {
const [count, setCount] = useState(() => getScheduleCount(platform));

useEffect(() => {
setCount(getScheduleCount(platform));
return subscribeToScheduleCount(platform, setCount);
}, [platform]);

return count;
};

const PlatformScheduleBadge = ({ platform, className }) => {
const count = usePlatformScheduleCount(platform);
if (!count) return null;
const displayValue = count > 99 ? '99+' : count;
return <span className={className}>{displayValue}</span>;
};

export default PlatformScheduleBadge;
Loading
Loading