import { useEffect, useState } from "react"; import { ExternalLink } from "lucide-react"; import { formatDateTime as formatPlatformDateTime, formatDateTimeFromDate, mergeDeltaRows } from "@govoplan/core-webui"; import { Link } from "react-router-dom"; import type { ApiSettings } from "../../types"; import { Card } from "@govoplan/core-webui"; import { Button } from "@govoplan/core-webui"; import { StatusBadge } from "@govoplan/core-webui"; import { PageTitle } from "@govoplan/core-webui"; import { LoadingFrame } from "@govoplan/core-webui"; import { DismissibleAlert, i18nMessage, useGuardedNavigate } from "@govoplan/core-webui"; import DataGrid, { type DataGridColumn } from "../../components/table/DataGrid"; import { createNewCampaign, listCampaignsDelta, type CampaignDeltaResponse } from "../../api/campaigns"; import type { CampaignListItem } from "../../types"; export default function CampaignListPage({ settings }: {settings: ApiSettings;}) { const navigate = useGuardedNavigate(); const [campaigns, setCampaigns] = useState([]); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [creating, setCreating] = useState(false); const [lastLoadedAt, setLastLoadedAt] = useState(""); const [campaignDeltaWatermark, setCampaignDeltaWatermark] = useState(null); async function load(forcedSince: string | null | undefined = campaignDeltaWatermark) { setLoading(true); setError(""); try { let nextWatermark = forcedSince ?? null; let nextCampaigns = campaigns; let response: CampaignDeltaResponse; do { response = await listCampaignsDelta(settings, { since: nextWatermark }); nextCampaigns = mergeCampaignDelta(nextCampaigns, response); nextWatermark = response.watermark ?? null; } while (response.has_more); setCampaigns(nextCampaigns); setCampaignDeltaWatermark(nextWatermark); setLastLoadedAt(formatLoadedAt(new Date())); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setLoading(false); } } async function create() { setCreating(true); setError(""); try { const created = await createNewCampaign(settings); navigate(`/campaigns/${created.campaign.id}/wizard/create`); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setCreating(false); } } useEffect(() => { setCampaignDeltaWatermark(null); load(null); }, [settings.apiBaseUrl, settings.apiKey, settings.accessToken]); const columns: DataGridColumn[] = [ { id: "campaign", header: "i18n:govoplan-campaign.campaign.69390e16", width: "minmax(260px, 1.8fr)", sortable: true, filterable: true, sticky: "start", render: (campaign) =>
{campaign.name || campaign.external_id || campaign.id}
{campaign.description || campaign.external_id || campaign.id}
, value: (campaign) => `${campaign.name ?? ""} ${campaign.external_id ?? ""} ${campaign.id}` }, { id: "status", header: "i18n:govoplan-campaign.status.bae7d5be", width: 150, sortable: true, filterable: true, columnType: "from-list", list: { options: [ { value: "draft", label: "i18n:govoplan-campaign.draft.23d33e22" }, { value: "active", label: "i18n:govoplan-campaign.active.a733b809" }, { value: "completed", label: "i18n:govoplan-campaign.completed.1798b3ba" }, { value: "archived", label: "i18n:govoplan-campaign.archived.eddc813f" }], display: "pill" }, render: (campaign) => , value: (campaign) => campaign.status || "draft" }, { id: "current_version", header: "i18n:govoplan-campaign.current_version.7be72582", width: 170, sortable: true, filterable: true, className: "version-cell mono-small", render: (campaign) => {campaign.current_version_id ? shortId(campaign.current_version_id) : "—"}, value: (campaign) => campaign.current_version_id ?? "" }, { id: "updated", header: "i18n:govoplan-campaign.updated.f2f8570d", width: 190, sortable: true, filterable: true, filterType: "date", className: "updated-cell", render: (campaign) => formatDateTime(campaign.updated_at ?? campaign.updatedAt ?? campaign.created_at), value: (campaign) => campaign.updated_at ?? campaign.updatedAt ?? campaign.created_at ?? "" }, { id: "actions", header: "i18n:govoplan-campaign.actions.c3cd636a", width: 70, sticky: "end", align: "right", render: (campaign) =>