import React, { useState } from 'react'; import EmptyState from '../agent-analytics/EmptyState'; import type { ArticleDetailResponse, ArticleSummary, } from '../../service/visibility/visibility.interface'; import ArticleModal from './ArticleModal'; import { toIsoWeek, toneToBadgeClass } from './helpers'; interface PublishedArticlesListProps { /** All articles for the brand; this component filters down to ``published``. */ articles: ArticleSummary[]; /** Recomaze client id. */ clientId: string; /** Recomaze JWT. */ token: string; /** * Invoked after the merchant flips an article between ``ready`` and * ``published`` from inside the modal. Forwarded straight from the parent. */ onArticlePublishedChanged?: (article: ArticleDetailResponse) => void; } interface WeekBucket { weekIso: string; articles: ArticleSummary[]; } /** * Bucket published articles by ISO week (derived from ``published_at``) * and return the most-recent week first. Articles without a * ``published_at`` should not appear here - they're filtered out before * this function runs. * * @param publishedArticles {ArticleSummary[]} Articles already filtered to ``status === 'published'``. * @returns {WeekBucket[]} Per-week buckets sorted most-recent week first; within each bucket, articles are sorted by ``published_at`` descending. */ const groupPublishedByWeek = ( publishedArticles: ArticleSummary[] ): WeekBucket[] => { const buckets = new Map(); for (const article of publishedArticles) { if (!article.published_at) continue; const weekIso = toIsoWeek(new Date(article.published_at)); const existing = buckets.get(weekIso); if (existing) { existing.push(article); } else { buckets.set(weekIso, [article]); } } return Array.from(buckets.entries()) .map(([weekIso, weekArticles]) => ({ weekIso, articles: weekArticles .slice() .sort((a, b) => (b.published_at ?? '').localeCompare(a.published_at ?? '') ), })) .sort((a, b) => a.weekIso < b.weekIso ? 1 : a.weekIso > b.weekIso ? -1 : 0 ); }; /** * "Published articles" tab - every article whose status is ``"published"``, * grouped by the ISO week of ``published_at``. Clicking a row opens it in * {@link ArticleModal}; from there the merchant can Unpublish, which lifts * the row back to the Recommended tab. */ const PublishedArticlesList = ({ articles, clientId, token, onArticlePublishedChanged, }: PublishedArticlesListProps): JSX.Element => { const [openArticleId, setOpenArticleId] = useState(null); const publishedArticles = articles.filter( article => article.status === 'published' ); if (publishedArticles.length === 0) { return ( ); } const weekBuckets = groupPublishedByWeek(publishedArticles); return ( <>
{weekBuckets.map(bucket => (

{bucket.weekIso}

{bucket.articles.map(article => (

{article.title || '(untitled)'}

Published {article.published_at && ( {new Date(article.published_at).toLocaleDateString()} )}
))}
))}
setOpenArticleId(null)} clientId={clientId} token={token} onPublishedChanged={onArticlePublishedChanged} /> ); }; export default PublishedArticlesList;