@aglyn/plugins-outreach 1.0.0-beta.204 → 1.0.0-beta.206

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/plugins-outreach",
3
- "version": "1.0.0-beta.204",
3
+ "version": "1.0.0-beta.206",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,19 +25,19 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/aglyn": "1.0.0-beta.204",
29
- "@aglyn/shared-data-mdi": "1.0.0-beta.204",
30
- "@aglyn/shared-ui-email-campaigns": "1.0.0-beta.204",
31
- "@aglyn/shared-ui-jsx": "1.0.0-beta.204",
32
- "@aglyn/shared-ui-next": "1.0.0-beta.204",
33
- "@aglyn/shared-ui-snackstack": "1.0.0-beta.204",
34
- "@aglyn/shared-util-email": "1.0.0-beta.204",
35
- "@aglyn/shared-util-http": "1.0.0-beta.204",
36
- "@aglyn/shared-util-timestamp": "1.0.0-beta.204",
37
- "@aglyn/shared-util-tools": "1.0.0-beta.204",
38
- "@aglyn/tenant-data-admin": "1.0.0-beta.204",
39
- "@aglyn/tenant-feature-instance": "1.0.0-beta.204",
40
- "@aglyn/tenant-runtime": "1.0.0-beta.204",
28
+ "@aglyn/aglyn": "1.0.0-beta.206",
29
+ "@aglyn/shared-data-mdi": "1.0.0-beta.206",
30
+ "@aglyn/shared-ui-email-campaigns": "1.0.0-beta.206",
31
+ "@aglyn/shared-ui-jsx": "1.0.0-beta.206",
32
+ "@aglyn/shared-ui-next": "1.0.0-beta.206",
33
+ "@aglyn/shared-ui-snackstack": "1.0.0-beta.206",
34
+ "@aglyn/shared-util-email": "1.0.0-beta.206",
35
+ "@aglyn/shared-util-http": "1.0.0-beta.206",
36
+ "@aglyn/shared-util-timestamp": "1.0.0-beta.206",
37
+ "@aglyn/shared-util-tools": "1.0.0-beta.206",
38
+ "@aglyn/tenant-data-admin": "1.0.0-beta.206",
39
+ "@aglyn/tenant-feature-instance": "1.0.0-beta.206",
40
+ "@aglyn/tenant-runtime": "1.0.0-beta.206",
41
41
  "@swc/helpers": "0.5.23"
42
42
  },
43
43
  "peerDependencies": {
@@ -27,12 +27,14 @@ import { useOrgCampaigns, useOrgMemberOptions } from "@aglyn/tenant-feature-inst
27
27
  import { Alert, Box, Button, Card, Chip, Collapse, Divider, IconButton, Link, List, ListItem, ListItemIcon, ListItemText, Stack, Tooltip, Typography } from "@mui/material";
28
28
  import { useCallback, useMemo, useState } from "react";
29
29
  import { OUTREACH_MAIL_GATEWAY_LABELS } from "../engine/mail-gateway.js";
30
+ import { outreachNextSendState } from "../engine/next-send.js";
30
31
  import { outreachClickSummary } from "../model/enrollment-engagement.js";
31
32
  import { outreachEnrollmentFigures, outreachEnrollmentTimeline, outreachStepName } from "../model/enrollment-timeline.js";
32
33
  import { OUTREACH_ATTESTATION_KINDS, OUTREACH_ATTESTATION_LABELS } from "../model/outreach.types.js";
33
34
  import { OUTREACH_ENROLLMENT_ACTION_LABELS, outreachEnrollmentActionsFor, useOutreachEnrollmentActions } from "./enrollment-actions.js";
34
35
  import { outreachCurrentStepLabel, outreachStepIsCurated, outreachStopLabel } from "./enrollments-table.js";
35
36
  import { formatOutreachTime, OutreachEnrollmentStatusChip, OutreachLoading, OutreachLoadProblem } from "./outreach-ui.js";
37
+ import { outreachNextSendDetail, outreachNextSendLabel, useOutreachNowMs } from "./next-send.js";
36
38
  import { OutreachFigure } from "./sequence-report-card.js";
37
39
  import { useOutreachApi } from "./use-outreach-api.js";
38
40
  import { useOutreachSequence } from "./use-outreach-data.js";
@@ -516,6 +518,7 @@ export function OutreachEnrollmentDetail(props) {
516
518
  enabled: true
517
519
  });
518
520
  const [detailsOpen, setDetailsOpen] = useState(false);
521
+ const nowMs = useOutreachNowMs();
519
522
  const enrollment = loaded.data;
520
523
  const sequence = loadedSequence.data;
521
524
  const campaigns = useOrgCampaigns(orgId, {
@@ -623,7 +626,13 @@ export function OutreachEnrollmentDetail(props) {
623
626
  const dash = (value)=>value ? value.toLocaleString() : '—';
624
627
  const notTracked = !trackClicks && !figures.clicks && !figures.scannerClicks ? 'Not tracked' : undefined;
625
628
  const thread = (_ref1 = (_enrollment_gmailThreadId = enrollment.gmailThreadId) != null ? _enrollment_gmailThreadId : enrollment.gmailThreadIds.at(-1)) != null ? _ref1 : null;
626
- const nothingYet = enrollment.status === 'active' && enrollment.nextDueAtMs ? `Nothing yet — step ${enrollment.stepIndex + 1} sends ${time(enrollment.nextDueAtMs)}.` : 'Nothing yet.';
629
+ const nextSend = outreachNextSendState({
630
+ enrollment,
631
+ sequence,
632
+ mailbox: props.mailboxes.status === 'ready' ? mailbox : undefined,
633
+ nowMs
634
+ });
635
+ const nothingYet = enrollment.status === 'active' && enrollment.nextDueAtMs ? nextSend.kind === 'queued' ? `Nothing yet — step ${enrollment.stepIndex + 1} is due and queued to send.` : `Nothing yet — step ${enrollment.stepIndex + 1} sends ${time(enrollment.nextDueAtMs)}.` : 'Nothing yet.';
627
636
  return /*#__PURE__*/ _jsxs(Stack, {
628
637
  spacing: 2,
629
638
  children: [
@@ -713,7 +722,16 @@ export function OutreachEnrollmentDetail(props) {
713
722
  color: "success",
714
723
  label: "Curated"
715
724
  }) : null,
716
- open && enrollment.nextDueAtMs ? /*#__PURE__*/ _jsx(Chip, {
725
+ open && enrollment.nextDueAtMs ? nextSend.kind === 'queued' ? /*#__PURE__*/ _jsx(Tooltip, {
726
+ describeChild: true,
727
+ title: outreachNextSendDetail(nextSend, timeZone),
728
+ children: /*#__PURE__*/ _jsx(Chip, {
729
+ size: "small",
730
+ variant: "outlined",
731
+ color: nextSend.reason === 'mailbox_not_sending' || nextSend.reason === 'sequence_not_active' ? 'warning' : 'default',
732
+ label: `Next send ${outreachNextSendLabel(nextSend, timeZone)}`
733
+ })
734
+ }) : /*#__PURE__*/ _jsx(Chip, {
717
735
  size: "small",
718
736
  variant: "outlined",
719
737
  label: `Next send ${time(enrollment.nextDueAtMs)}`
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/enrollment-detail.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type ConsolePluginOrgMount,\n PageHeaderRecord,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport { crmOrgRecordHref, crmRecordHref } from '@aglyn/aglyn/app-utils/console-record-links'\nimport {\n mdiAccountCancelOutline,\n mdiAccountOutline,\n mdiAccountPlusOutline,\n mdiAlertCircleOutline,\n mdiCheckCircleOutline,\n mdiChevronDown,\n mdiChevronUp,\n mdiClipboardCheckOutline,\n mdiContentCopy,\n mdiCursorDefaultClickOutline,\n mdiEmailAlertOutline,\n mdiEmailOffOutline,\n mdiEmailOutline,\n mdiHandBackLeftOutline,\n mdiPauseCircleOutline,\n mdiPencilOutline,\n mdiPlayCircleOutline,\n mdiReply,\n mdiShieldSearch,\n mdiStopCircleOutline,\n} from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport RowActionsMenu from '@aglyn/shared-ui-jsx/components/row-actions-menu.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useOrgCampaigns, useOrgMemberOptions } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Card,\n Chip,\n Collapse,\n Divider,\n IconButton,\n Link,\n List,\n ListItem,\n ListItemIcon,\n ListItemText,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { type ReactNode, useCallback, useMemo, useState } from 'react'\nimport { OUTREACH_MAIL_GATEWAY_LABELS } from '../engine/mail-gateway'\nimport { outreachClickSummary } from '../model/enrollment-engagement'\nimport {\n outreachEnrollmentFigures,\n outreachEnrollmentTimeline,\n outreachStepName,\n type OutreachTimelineEntry,\n type OutreachTimelineKind,\n type OutreachTimelineTone,\n} from '../model/enrollment-timeline'\nimport {\n OUTREACH_ATTESTATION_KINDS,\n OUTREACH_ATTESTATION_LABELS,\n type OutreachEnrollment,\n type OutreachMailbox,\n type OutreachSequence,\n} from '../model/outreach.types'\nimport {\n OUTREACH_ENROLLMENT_ACTION_LABELS,\n outreachEnrollmentActionsFor,\n type OutreachEnrollmentRowAction,\n useOutreachEnrollmentActions,\n} from './enrollment-actions'\nimport { outreachCurrentStepLabel, outreachStepIsCurated, outreachStopLabel } from './enrollments-table'\nimport {\n formatOutreachTime,\n OutreachEnrollmentStatusChip,\n OutreachLoading,\n OutreachLoadProblem,\n} from './outreach-ui'\nimport { OutreachFigure } from './sequence-report-card'\nimport { useOutreachApi } from './use-outreach-api'\nimport { useOutreachSequence } from './use-outreach-data'\nimport type { OutreachEnrollmentGatewayResponse } from '../model/outreach-api'\nimport {\n useOutreachEnrollment,\n useOutreachEnrollmentGateway,\n useOutreachEnrollmentHistory,\n} from './use-outreach-enrollment'\nimport type { OutreachMailboxesResult } from './use-outreach-mailboxes'\n\n/*==========================================\n * ONE PERSON IN ONE SEQUENCE (AGL-3332):\n * `/[orgSlug]/outreach/sequences/{sequenceId}/enrollments/{enrollmentId}`.\n *\n * A row of the Enrollments tab opens it, and its URL is the person's: a\n * comment or a message can link straight to them.\n *\n * Laid out the way every record page in the console is (the CRM's\n * `CrmRecordHeader` grammar): the page heading names the person; the first\n * card says what the record is, with the way back and the actions in its\n * HEADER — the one that changes things as a button, the rest and the\n * destructive ones behind the menu — and the facts that identify it as\n * chips. Under the chips, five numbers.\n *\n * Then ONE timeline, newest first, which is the page: every send, click,\n * reply, bounce, stop, hold and resume, from `model/enrollment-timeline.ts`.\n * Everything else stored on the enrollment is under Details, closed until\n * asked for — nothing is left out, and nothing is in the way.\n *=========================================*/\n\nexport interface OutreachEnrollmentDetailProps {\n orgId: string\n /** The org the hub is mounted under: its slug and sites, for the CRM record's address. */\n orgMount?: ConsolePluginOrgMount\n /** `/[orgSlug]/outreach/sequences`. */\n sectionPath: string\n sequenceId: string\n enrollmentId: string\n mailboxes: OutreachMailboxesResult\n}\n\n/** Where the CRM record the person is lives — the site's own CRM when the site is known. */\nexport function outreachCrmRecordHref(\n kind: 'lead' | 'contact',\n id: string | null | undefined,\n hostId: string,\n orgMount: Pick<ConsolePluginOrgMount, 'orgSlug' | 'hosts'> | undefined,\n): string | null {\n if (!id || !orgMount?.orgSlug) return null\n const host = orgMount.hosts.find((entry) => entry.id === hostId)?.subdomain\n return host\n ? crmRecordHref({ orgSlug: orgMount.orgSlug, host }, kind, id)\n : crmOrgRecordHref(orgMount.orgSlug, kind, id)\n}\n\n/** A Gmail thread, opened in the mailbox's own account. */\nexport function outreachGmailThreadUrl(threadId: string, mailboxEmail: string | null | undefined): string {\n const account = mailboxEmail ? `?authuser=${encodeURIComponent(mailboxEmail)}` : ''\n return `https://mail.google.com/mail/${account}#all/${encodeURIComponent(threadId)}`\n}\n\nconst KIND_ICONS: Record<OutreachTimelineKind, { path: string }> = {\n enrolled: mdiAccountPlusOutline,\n curated: mdiPencilOutline,\n sent: mdiEmailOutline,\n task: mdiClipboardCheckOutline,\n click: mdiCursorDefaultClickOutline,\n scanner: mdiShieldSearch,\n 'earlier-clicks': mdiCursorDefaultClickOutline,\n paused: mdiPauseCircleOutline,\n resumed: mdiPlayCircleOutline,\n stopped: mdiStopCircleOutline,\n 'do-not-contact': mdiAccountCancelOutline,\n replied: mdiReply,\n bounced: mdiEmailAlertOutline,\n 'opted-out': mdiEmailOffOutline,\n held: mdiHandBackLeftOutline,\n released: mdiPlayCircleOutline,\n failed: mdiAlertCircleOutline,\n finished: mdiCheckCircleOutline,\n}\n\nconst TONE_COLORS: Record<OutreachTimelineTone, string> = {\n default: 'text.secondary',\n success: 'success.main',\n info: 'info.main',\n warning: 'warning.main',\n error: 'error.main',\n}\n\n/** A destination, whole, opening in a new tab. */\nfunction Destination(props: { url: string; label?: string }) {\n return (\n <Typography variant=\"body2\" component=\"span\" sx={{ display: 'block', wordBreak: 'break-all' }}>\n {props.label ? `${props.label}: ` : null}\n <Link href={props.url} target=\"_blank\" rel=\"noopener noreferrer\" underline=\"hover\">\n {props.url}\n </Link>\n </Typography>\n )\n}\n\n/** One line of the timeline. */\nfunction TimelineRow(props: {\n entry: OutreachTimelineEntry\n timeZone: string | null\n mailboxEmail: string | null\n divider: boolean\n}) {\n const { entry } = props\n return (\n <ListItem alignItems=\"flex-start\" divider={props.divider} disableGutters data-kind={entry.kind}>\n <ListItemIcon sx={{ minWidth: 36, mt: 0.75, color: TONE_COLORS[entry.tone] }}>\n <MdiIcon path={KIND_ICONS[entry.kind].path} fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n disableTypography\n primary={\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={{ xs: 0, sm: 1 }}\n sx={{ justifyContent: 'space-between', alignItems: { sm: 'baseline' } }}\n >\n <Typography variant=\"body2\" sx={{ fontWeight: 500 }}>\n {entry.title}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ whiteSpace: 'nowrap' }}>\n {formatOutreachTime(entry.atMs, props.timeZone)}\n </Typography>\n </Stack>\n }\n secondary={\n <Stack spacing={0.25} sx={{ mt: 0.25 }}>\n {entry.url ? <Destination url={entry.url} label={entry.urlLabel} /> : null}\n {entry.detail ? (\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>\n {entry.detail}\n </Typography>\n ) : null}\n {entry.facts.length || entry.gmailThreadId ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {entry.facts.join(' · ')}\n {entry.gmailThreadId ? (\n <>\n {entry.facts.length ? ' · ' : null}\n <Link\n href={outreachGmailThreadUrl(entry.gmailThreadId, props.mailboxEmail)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n underline=\"hover\"\n >\n Open thread in Gmail\n </Link>\n </>\n ) : null}\n </Typography>\n ) : null}\n </Stack>\n }\n />\n </ListItem>\n )\n}\n\n/** One fact of the Details list. */\nfunction Fact(props: { label: string; children: ReactNode }) {\n return (\n <>\n <Typography component=\"dt\" variant=\"body2\" color=\"text.secondary\">\n {props.label}\n </Typography>\n <Box component=\"dd\" sx={{ m: 0, minWidth: 0, typography: 'body2', wordBreak: 'break-word' }}>\n {props.children}\n </Box>\n </>\n )\n}\n\n/** What mail from the sequence's sending domain met at the person's domain, in a line. */\nfunction gatewaySentence(answer: OutreachEnrollmentGatewayResponse, timeZone: string | null): string {\n const { intel, standing } = answer\n if (!intel) return 'Could not be looked up'\n if (intel.status === 'no_mx' || intel.status === 'null_mx') {\n return `${answer.domain ?? 'The domain'} takes no mail · looked up ${formatOutreachTime(intel.resolvedAtMs, timeZone)}`\n }\n const from = answer.sendingDomain ? ` from ${answer.sendingDomain}` : ''\n const parts = [\n OUTREACH_MAIL_GATEWAY_LABELS[intel.gateway],\n intel.mx.length ? `MX ${intel.mx.join(', ')}` : 'no MX; delivered to its address record',\n standing\n ? `${standing.delivered30} delivered, ${standing.blocked30} refused${from} in the last 30 days`\n : null,\n `looked up ${formatOutreachTime(intel.resolvedAtMs, timeZone)}`,\n ]\n return parts.filter(Boolean).join(' · ')\n}\n\n/**\n * Everything else the enrollment holds, all of it, behind one toggle.\n */\nfunction EnrollmentDetails(props: {\n enrollment: OutreachEnrollment\n sequence: OutreachSequence\n mailbox: OutreachMailbox | null\n gateway: OutreachEnrollmentGatewayResponse | null\n /** What the Mail gateway line says while there is no answer to show. */\n gatewayUnread: string\n campaignName: (id: string) => string\n memberName: (uid: string) => string\n orgMount?: ConsolePluginOrgMount\n timeZone: string | null\n}) {\n const { enrollment, sequence, memberName, timeZone } = props\n const { enqueueSnackbar } = useSnackbar()\n const time = (ms: number | null | undefined) => formatOutreachTime(ms, timeZone)\n const leadHref = outreachCrmRecordHref('lead', enrollment.leadId, enrollment.hostId, props.orgMount)\n const contactHref = outreachCrmRecordHref('contact', enrollment.contactId, enrollment.hostId, props.orgMount)\n const clicks = outreachClickSummary(enrollment.engagement)\n const overrides = Object.entries(enrollment.stepOverrides ?? {}).sort(\n ([a], [b]) => Number(a) - Number(b),\n )\n const attested = OUTREACH_ATTESTATION_KINDS.filter((kind) => enrollment.attestations?.[kind])\n const threads = enrollment.gmailThreadIds.length\n ? enrollment.gmailThreadIds\n : enrollment.gmailThreadId\n ? [enrollment.gmailThreadId]\n : []\n const copyId = () => {\n void navigator.clipboard\n ?.writeText(enrollment.id)\n .then(() => enqueueSnackbar('Enrollment id copied.', { variant: 'success' }))\n .catch(() => enqueueSnackbar('The id could not be copied.', { variant: 'error' }))\n }\n const link = (href: string | null, label: string) =>\n href ? (\n <Link {...({ component: AppLink, componentVariant: 'naked' } as object)} href={href} underline=\"hover\">\n {label}\n </Link>\n ) : (\n label\n )\n\n return (\n <Box\n component=\"dl\"\n sx={{\n m: 0,\n display: 'grid',\n gridTemplateColumns: { xs: '1fr', sm: 'minmax(160px, 220px) 1fr' },\n columnGap: 2,\n rowGap: 1.25,\n }}\n >\n <Fact label=\"Personal line\">\n {enrollment.personalLine ? (\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap' }}>\n {enrollment.personalLine}\n </Typography>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Enrolled as\">\n {enrollment.target === 'lead' ? (\n link(leadHref, 'Lead')\n ) : enrollment.leadId ? (\n <>\n {link(contactHref, 'Contact')}\n {', converted from a '}\n {link(leadHref, 'lead')}\n </>\n ) : (\n link(contactHref, 'Contact')\n )}\n </Fact>\n <Fact label=\"Enrolled\">\n {`${time(enrollment.createdAtMs)}${enrollment.enrolledByUid ? ` by ${memberName(enrollment.enrolledByUid)}` : ''}`}\n </Fact>\n <Fact label=\"Cold contact\">\n {enrollment.cold\n ? 'Yes — no inbound capture behind them, so the member confirmed the address before enrolling'\n : 'No'}\n </Fact>\n <Fact label=\"Attestations\">\n {attested.length ? (\n <Stack component=\"ul\" spacing={0.25} sx={{ m: 0, pl: 2.5 }}>\n {attested.map((kind) => {\n const entry = enrollment.attestations?.[kind]\n return (\n <li key={kind}>\n {`${OUTREACH_ATTESTATION_LABELS[kind]} — ${memberName(entry?.uid ?? '')}, ${time(entry?.atMs)}`}\n </li>\n )\n })}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Mailbox\">\n {props.mailbox\n ? `${props.mailbox.sendAs || props.mailbox.email}${props.mailbox.sendAs && props.mailbox.sendAs !== props.mailbox.email ? ` (${props.mailbox.email})` : ''}`\n : enrollment.mailboxId\n ? 'No longer connected'\n : '—'}\n </Fact>\n <Fact label=\"Campaigns\">\n {enrollment.campaignIds?.length\n ? enrollment.campaignIds.map(props.campaignName).join(', ')\n : '—'}\n </Fact>\n <Fact label=\"Mail gateway\">\n {props.gateway ? gatewaySentence(props.gateway, timeZone) : props.gatewayUnread}\n </Fact>\n <Fact label=\"Gateway hold\">\n {enrollment.gatewayHold\n ? [\n OUTREACH_MAIL_GATEWAY_LABELS[enrollment.gatewayHold.gateway],\n enrollment.gatewayHold.heldAtMs ? `held ${time(enrollment.gatewayHold.heldAtMs)}` : 'never held',\n enrollment.gatewayHold.releasedAtMs\n ? `released ${time(enrollment.gatewayHold.releasedAtMs)}${enrollment.gatewayHold.releasedByUid ? ` by ${memberName(enrollment.gatewayHold.releasedByUid)}` : ''}`\n : 'not released',\n ].join(' · ')\n : '—'}\n {enrollment.gatewayDeliveredSteps\n ? ` (${enrollment.gatewayDeliveredSteps} of their emails counted as delivered on the gateway ledger)`\n : null}\n </Fact>\n <Fact label=\"Clicks\">\n {clicks.clicks || clicks.machineClicks\n ? [\n `${clicks.clicks} by the person`,\n `${clicks.machineClicks} by scanners, not counted`,\n `${clicks.clicks - clicks.unloggedClicks + clicks.machineClicks - clicks.unloggedMachineClicks} listed one by one`,\n enrollment.engagement?.firstClickAtMs ? `first ${time(enrollment.engagement.firstClickAtMs)}` : null,\n enrollment.engagement?.lastClickAtMs ? `last ${time(enrollment.engagement.lastClickAtMs)}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n : '—'}\n {clicks.followed.length ? (\n <Box sx={{ mt: 0.5 }}>\n {clicks.followed.map((url) => (\n <Destination key={url} url={url} />\n ))}\n </Box>\n ) : null}\n </Fact>\n <Fact label=\"Curated steps\">\n {overrides.length ? (\n <Stack spacing={1.5}>\n {overrides.map(([key, override]) => (\n <Box key={key}>\n <Typography variant=\"body2\" sx={{ fontWeight: 500 }}>\n {outreachStepName(sequence.steps, Number(key))}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {[\n override.source === 'ai' ? (override.edited ? 'AI draft, edited' : 'AI draft') : 'Written by a member',\n override.draftedByUid ? `confirmed by ${memberName(override.draftedByUid)}` : null,\n override.draftedAtMs ? time(override.draftedAtMs) : null,\n override.model ? `model ${override.model}` : null,\n ]\n .filter(Boolean)\n .join(' · ')}\n </Typography>\n {override.subject !== undefined ? (\n <Typography variant=\"body2\">{`Subject: ${override.subject}`}</Typography>\n ) : null}\n {override.body !== undefined ? (\n <Typography\n variant=\"body2\"\n sx={{ whiteSpace: 'pre-wrap', mt: 0.5, pl: 1.5, borderLeft: 2, borderColor: 'divider' }}\n >\n {override.body}\n </Typography>\n ) : null}\n {override.prompt ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ whiteSpace: 'pre-wrap', mt: 0.5 }}>\n {`Prompt: ${override.prompt}`}\n </Typography>\n ) : null}\n </Box>\n ))}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Gmail threads\">\n {threads.length ? (\n <Stack spacing={0.25}>\n {threads.map((thread) => (\n <span key={thread}>\n <Link\n href={outreachGmailThreadUrl(thread, props.mailbox?.email)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n underline=\"hover\"\n >\n {thread}\n </Link>\n {thread === enrollment.gmailThreadId ? ' (current)' : null}\n </span>\n ))}\n {enrollment.threadSubject ? (\n <Typography variant=\"caption\" color=\"text.secondary\">{`Started as “${enrollment.threadSubject}”`}</Typography>\n ) : null}\n {enrollment.messageIds.length ? (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ wordBreak: 'break-all' }}>\n {`Message-IDs in the current thread: ${enrollment.messageIds.join(' ')}`}\n </Typography>\n ) : null}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Stop\">\n {enrollment.stopReason\n ? `${outreachStopLabel(enrollment)} · ${time(enrollment.stoppedAtMs)}${enrollment.stoppedByUid ? ` · by ${memberName(enrollment.stoppedByUid)}` : ''}`\n : '—'}\n </Fact>\n <Fact label=\"Created · updated\">{`${time(enrollment.createdAtMs)} · ${time(enrollment.updatedAtMs)}`}</Fact>\n <Fact label=\"Enrollment id\">\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ fontFamily: 'monospace', wordBreak: 'break-all' }}>\n {enrollment.id}\n </Typography>\n <Tooltip title=\"Copy the id\">\n <IconButton size=\"small\" aria-label=\"Copy the enrollment id\" onClick={copyId}>\n <MdiIcon path={mdiContentCopy.path} fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Stack>\n </Fact>\n </Box>\n )\n}\n\nexport function OutreachEnrollmentDetail(props: OutreachEnrollmentDetailProps) {\n const { orgId, sectionPath, sequenceId, enrollmentId, orgMount } = props\n const api = useOutreachApi(orgId)\n const loadedSequence = useOutreachSequence(orgId, sequenceId)\n const loaded = useOutreachEnrollment(orgId, enrollmentId)\n const history = useOutreachEnrollmentHistory(orgId, enrollmentId)\n const gateway = useOutreachEnrollmentGateway(api, enrollmentId)\n const roster = useOrgMemberOptions(orgId, { enabled: true })\n const [detailsOpen, setDetailsOpen] = useState(false)\n const enrollment = loaded.data\n const sequence = loadedSequence.data\n const campaigns = useOrgCampaigns(orgId, {\n enabled: detailsOpen && Boolean(enrollment?.campaignIds?.length),\n })\n const steps = useMemo(() => sequence?.steps ?? [], [sequence])\n const actions = useOutreachEnrollmentActions({ api, steps })\n\n const memberName = useCallback(\n (uid: string) => roster.options.find((option) => option.uid === uid)?.label ?? 'a member',\n [roster.options],\n )\n const campaignName = useCallback(\n (id: string) => campaigns.options.find((option) => option.value === id)?.label ?? id,\n [campaigns.options],\n )\n\n const enrollmentsPath = `${sectionPath}/${sequenceId}/enrollments`\n const mailbox =\n props.mailboxes.mailboxes.find((entry) => entry.id === (enrollment?.mailboxId || sequence?.mailboxId)) ?? null\n const timeZone = mailbox?.timezone ?? null\n const time = (ms: number | null | undefined) => formatOutreachTime(ms, timeZone)\n const timeline = useMemo(\n () =>\n enrollment\n ? outreachEnrollmentTimeline({\n enrollment,\n steps,\n history: history.status === 'ready' ? history.data : null,\n memberName,\n formatTime: (ms) => formatOutreachTime(ms, timeZone),\n gateway: gateway.data?.intel?.gateway ?? null,\n })\n : [],\n [enrollment, steps, history, memberName, timeZone, gateway.data],\n )\n\n const back = (\n <Button\n // A real link, as the CRM record header's is: it opens in a new tab when asked.\n {...({ component: AppLink, componentVariant: 'naked', nativeButton: false } as object)}\n href={enrollmentsPath}\n size=\"small\"\n color=\"primary\"\n >\n Back to enrollments\n </Button>\n )\n\n if (loaded.status === 'loading' || loadedSequence.status === 'loading') {\n return <OutreachLoading label=\"Loading this person…\" />\n }\n if (loaded.status === 'error' || loaded.status === 'refused') {\n return <OutreachLoadProblem status={loaded.status} what=\"enrollment\" />\n }\n if (loadedSequence.status === 'error' || loadedSequence.status === 'refused') {\n return <OutreachLoadProblem status={loadedSequence.status} what=\"sequence\" />\n }\n // An id from another sequence reads as not here: the URL names both.\n if (!enrollment || !sequence || enrollment.sequenceId !== sequenceId) {\n return (\n <Card variant=\"outlined\">\n <EmptyStateComponent\n label=\"This person isn’t in this sequence\"\n description=\"They may have been removed from the workspace, or the link names a different sequence.\"\n action={back}\n />\n </Card>\n )\n }\n\n const name = enrollment.contactName || enrollment.email\n const kind = enrollment.target === 'lead' ? 'lead' : 'contact'\n const recordHref = outreachCrmRecordHref(\n kind,\n kind === 'lead' ? enrollment.leadId : enrollment.contactId,\n enrollment.hostId,\n orgMount,\n )\n const figures = outreachEnrollmentFigures(enrollment)\n const trackClicks = sequence.settings.trackClicks || sequence.stats?.clickTracked === true\n const open = enrollment.status === 'active' || enrollment.status === 'paused'\n const held = enrollment.status === 'paused' && enrollment.stopReason === 'gateway_blocked_here'\n\n /*\n * The one act that moves the person forward is the button: resuming a\n * paused one, else curating the next email. Everything else is in the\n * menu, the destructive acts included, as on every record page.\n */\n const available = outreachEnrollmentActionsFor(enrollment, steps)\n const primary: OutreachEnrollmentRowAction | null = available.includes('resume')\n ? 'resume'\n : available.includes('curate')\n ? 'curate'\n : null\n const menu = actions.menuItems(enrollment, (action) => action !== primary)\n const dash = (value: number) => (value ? value.toLocaleString() : '—')\n const notTracked = !trackClicks && !figures.clicks && !figures.scannerClicks ? 'Not tracked' : undefined\n const thread = enrollment.gmailThreadId ?? enrollment.gmailThreadIds.at(-1) ?? null\n const nothingYet =\n enrollment.status === 'active' && enrollment.nextDueAtMs\n ? `Nothing yet — step ${enrollment.stepIndex + 1} sends ${time(enrollment.nextDueAtMs)}.`\n : 'Nothing yet.'\n\n return (\n <Stack spacing={2}>\n {/* The page heading and the trail name the person; the card says what they are in. */}\n <PageHeaderRecord title={name} />\n <CardDisplay\n header=\"Enrollment\"\n subheader={\n <>\n {enrollment.contactName ? `${enrollment.email} · ` : ''}\n {`In ${sequence.name || 'Untitled'}`}\n </>\n }\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n action: (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n {back}\n {primary ? (\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={actions.busy === enrollment.id}\n onClick={() => actions.choose(enrollment, primary)}\n >\n {held ? 'Resume and send' : OUTREACH_ENROLLMENT_ACTION_LABELS[primary]}\n </Button>\n ) : null}\n {menu.length ? <RowActionsMenu label={name} items={menu} /> : null}\n </Stack>\n ),\n }}\n >\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n <Tooltip\n describeChild\n title={recordHref ? `Open the ${kind} in the CRM` : `The ${kind}’s record can’t be linked`}\n >\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={recordHref ? 'primary' : 'default'}\n icon={<MdiIcon path={mdiAccountOutline.path} fontSize=\"small\" />}\n label={kind === 'lead' ? 'Lead' : 'Contact'}\n {...(recordHref\n ? ({ component: AppLink, href: recordHref, clickable: true, componentVariant: 'naked' } as object)\n : {})}\n />\n </Tooltip>\n <OutreachEnrollmentStatusChip status={enrollment.status} />\n <Chip size=\"small\" variant=\"outlined\" label={outreachCurrentStepLabel(enrollment, steps)} />\n {outreachStepIsCurated(enrollment) ? (\n <Chip size=\"small\" variant=\"outlined\" color=\"success\" label=\"Curated\" />\n ) : null}\n {open && enrollment.nextDueAtMs ? (\n <Chip size=\"small\" variant=\"outlined\" label={`Next send ${time(enrollment.nextDueAtMs)}`} />\n ) : null}\n </Stack>\n {held ? (\n <Alert severity=\"warning\">\n {enrollment.stopDetail ||\n 'Their mail gateway refused this sender, so the next email is held. Resume to send it anyway.'}\n </Alert>\n ) : null}\n {figures.anything ? (\n <Stack direction=\"row\" spacing={3} sx={{ flexWrap: 'wrap', rowGap: 2 }} role=\"group\" aria-label=\"In numbers\">\n <OutreachFigure label=\"Emails sent\" value={dash(figures.emailsSent)} />\n <OutreachFigure label=\"Clicks\" value={dash(figures.clicks)} hint={notTracked} />\n <OutreachFigure\n label=\"Links followed\"\n value={\n figures.linksFollowed.count\n ? `${figures.linksFollowed.count}${figures.linksFollowed.atLeast ? '+' : ''}`\n : '—'\n }\n hint={\n notTracked ??\n (figures.linksFollowed.atLeast && figures.linksFollowed.count\n ? 'Earlier clicks kept the last link only'\n : undefined)\n }\n />\n <OutreachFigure label=\"Scanner clicks\" value={dash(figures.scannerClicks)} hint={notTracked ?? 'Not counted'} />\n <OutreachFigure label=\"Replies\" value={dash(figures.replies)} />\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {nothingYet}\n </Typography>\n )}\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header=\"Activity\"\n subheader=\"Newest first\"\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n contentGutterY\n HeaderProps={\n thread\n ? {\n action: (\n <Button\n size=\"small\"\n href={outreachGmailThreadUrl(thread, mailbox?.email)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Open thread in Gmail\n </Button>\n ),\n }\n : undefined\n }\n >\n <Stack spacing={1}>\n {history.status === 'loading' ? <OutreachLoading label=\"Loading their clicks…\" /> : null}\n {history.status === 'error' || history.status === 'refused' ? (\n <OutreachLoadProblem\n status={history.status}\n what=\"list of their clicks\"\n // Only the one-by-one list is missing: the totals, the sends and\n // every stop above come from the enrollment, which was read.\n message={\n history.status === 'refused'\n ? 'Their clicks can’t be listed one by one here; the numbers above still count them.'\n : 'Their clicks couldn’t be listed one by one. Reload the page to try again.'\n }\n />\n ) : null}\n <List disablePadding aria-label=\"Activity\">\n {timeline.map((entry, index) => (\n <TimelineRow\n key={entry.key}\n entry={entry}\n timeZone={timeZone}\n mailboxEmail={mailbox?.email ?? null}\n divider={index < timeline.length - 1}\n />\n ))}\n </List>\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header=\"Details\"\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n HeaderProps={{\n action: (\n <Button\n size=\"small\"\n aria-expanded={detailsOpen}\n aria-controls=\"outreach-enrollment-details\"\n endIcon={<MdiIcon path={(detailsOpen ? mdiChevronUp : mdiChevronDown).path} fontSize=\"small\" />}\n onClick={() => setDetailsOpen((was) => !was)}\n >\n {detailsOpen ? 'Hide' : 'Show'}\n </Button>\n ),\n }}\n >\n <Collapse in={detailsOpen} unmountOnExit>\n <Box id=\"outreach-enrollment-details\" sx={{ pb: 2 }}>\n <Divider sx={{ mb: 2 }} />\n <EnrollmentDetails\n enrollment={enrollment}\n sequence={sequence}\n mailbox={mailbox}\n gateway={gateway.status === 'ready' ? gateway.data : null}\n gatewayUnread={\n gateway.status === 'loading'\n ? 'Looking it up…'\n : gateway.status === 'refused'\n ? 'Your role cannot look it up'\n : 'Could not be looked up'\n }\n campaignName={campaignName}\n memberName={memberName}\n orgMount={orgMount}\n timeZone={timeZone}\n />\n </Box>\n </Collapse>\n </CardDisplay>\n\n {actions.dialogs}\n </Stack>\n )\n}\nOutreachEnrollmentDetail.displayName = 'OutreachEnrollmentDetail'\n\nexport default OutreachEnrollmentDetail\n"],"names":["PageHeaderRecord","pluginDocsHelp","crmOrgRecordHref","crmRecordHref","mdiAccountCancelOutline","mdiAccountOutline","mdiAccountPlusOutline","mdiAlertCircleOutline","mdiCheckCircleOutline","mdiChevronDown","mdiChevronUp","mdiClipboardCheckOutline","mdiContentCopy","mdiCursorDefaultClickOutline","mdiEmailAlertOutline","mdiEmailOffOutline","mdiEmailOutline","mdiHandBackLeftOutline","mdiPauseCircleOutline","mdiPencilOutline","mdiPlayCircleOutline","mdiReply","mdiShieldSearch","mdiStopCircleOutline","AppLink","CardDisplay","MdiIcon","EmptyStateComponent","RowActionsMenu","useSnackbar","useOrgCampaigns","useOrgMemberOptions","Alert","Box","Button","Card","Chip","Collapse","Divider","IconButton","Link","List","ListItem","ListItemIcon","ListItemText","Stack","Tooltip","Typography","useCallback","useMemo","useState","OUTREACH_MAIL_GATEWAY_LABELS","outreachClickSummary","outreachEnrollmentFigures","outreachEnrollmentTimeline","outreachStepName","OUTREACH_ATTESTATION_KINDS","OUTREACH_ATTESTATION_LABELS","OUTREACH_ENROLLMENT_ACTION_LABELS","outreachEnrollmentActionsFor","useOutreachEnrollmentActions","outreachCurrentStepLabel","outreachStepIsCurated","outreachStopLabel","formatOutreachTime","OutreachEnrollmentStatusChip","OutreachLoading","OutreachLoadProblem","OutreachFigure","useOutreachApi","useOutreachSequence","useOutreachEnrollment","useOutreachEnrollmentGateway","useOutreachEnrollmentHistory","outreachCrmRecordHref","kind","id","hostId","orgMount","orgSlug","host","hosts","find","entry","subdomain","outreachGmailThreadUrl","threadId","mailboxEmail","account","encodeURIComponent","KIND_ICONS","enrolled","curated","sent","task","click","scanner","paused","resumed","stopped","replied","bounced","held","released","failed","finished","TONE_COLORS","default","success","info","warning","error","Destination","props","variant","component","sx","display","wordBreak","label","href","url","target","rel","underline","TimelineRow","alignItems","divider","disableGutters","data-kind","minWidth","mt","color","tone","path","fontSize","disableTypography","primary","direction","xs","sm","spacing","justifyContent","fontWeight","title","whiteSpace","atMs","timeZone","secondary","urlLabel","detail","facts","length","gmailThreadId","join","Fact","m","typography","children","gatewaySentence","answer","intel","standing","status","domain","resolvedAtMs","from","sendingDomain","parts","gateway","mx","delivered30","blocked30","filter","Boolean","EnrollmentDetails","enrollment","sequence","memberName","enqueueSnackbar","time","ms","leadHref","leadId","contactHref","contactId","clicks","engagement","overrides","Object","entries","stepOverrides","sort","a","b","Number","attested","attestations","threads","gmailThreadIds","copyId","navigator","clipboard","writeText","then","catch","link","componentVariant","gridTemplateColumns","columnGap","rowGap","personalLine","createdAtMs","enrolledByUid","cold","pl","map","li","uid","mailbox","sendAs","email","mailboxId","campaignIds","campaignName","gatewayUnread","gatewayHold","heldAtMs","releasedAtMs","releasedByUid","gatewayDeliveredSteps","machineClicks","unloggedClicks","unloggedMachineClicks","firstClickAtMs","lastClickAtMs","followed","key","override","steps","source","edited","draftedByUid","draftedAtMs","model","subject","undefined","body","borderLeft","borderColor","prompt","thread","span","threadSubject","messageIds","stopReason","stoppedAtMs","stoppedByUid","updatedAtMs","fontFamily","size","aria-label","onClick","OutreachEnrollmentDetail","orgId","sectionPath","sequenceId","enrollmentId","api","loadedSequence","loaded","history","roster","enabled","detailsOpen","setDetailsOpen","data","campaigns","actions","options","option","value","enrollmentsPath","mailboxes","timezone","timeline","formatTime","back","nativeButton","what","description","action","name","contactName","recordHref","figures","trackClicks","settings","stats","clickTracked","open","available","includes","menu","menuItems","dash","toLocaleString","notTracked","scannerClicks","at","nothingYet","nextDueAtMs","stepIndex","header","subheader","help","anchor","contentGutterX","contentGutterY","HeaderProps","flexWrap","disabled","busy","choose","items","describeChild","icon","clickable","severity","stopDetail","anything","role","emailsSent","hint","linksFollowed","count","atLeast","replies","message","disablePadding","index","aria-expanded","aria-controls","endIcon","was","in","unmountOnExit","pb","mb","dialogs","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,SAEEA,gBAAgB,EAChBC,cAAc,QACT,eAAc;AACrB,SAASC,gBAAgB,EAAEC,aAAa,QAAQ,8CAA6C;AAC7F,SACEC,uBAAuB,EACvBC,iBAAiB,EACjBC,qBAAqB,EACrBC,qBAAqB,EACrBC,qBAAqB,EACrBC,cAAc,EACdC,YAAY,EACZC,wBAAwB,EACxBC,cAAc,EACdC,4BAA4B,EAC5BC,oBAAoB,EACpBC,kBAAkB,EAClBC,eAAe,EACfC,sBAAsB,EACtBC,qBAAqB,EACrBC,gBAAgB,EAChBC,oBAAoB,EACpBC,QAAQ,EACRC,eAAe,EACfC,oBAAoB,QACf,yBAAwB;AAC/B,SAASC,OAAO,EAAEC,WAAW,EAAEC,OAAO,QAAQ,uBAAsB;AACpE,OAAOC,yBAAyB,wDAAuD;AACvF,OAAOC,oBAAoB,6DAA4D;AACvF,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,eAAe,EAAEC,mBAAmB,QAAQ,iCAAgC;AACrF,SACEC,KAAK,EACLC,GAAG,EACHC,MAAM,EACNC,IAAI,EACJC,IAAI,EACJC,QAAQ,EACRC,OAAO,EACPC,UAAU,EACVC,IAAI,EACJC,IAAI,EACJC,QAAQ,EACRC,YAAY,EACZC,YAAY,EACZC,KAAK,EACLC,OAAO,EACPC,UAAU,QACL,gBAAe;AACtB,SAAyBC,WAAW,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACtE,SAASC,4BAA4B,QAAQ,4BAAwB;AACrE,SAASC,oBAAoB,QAAQ,oCAAgC;AACrE,SACEC,yBAAyB,EACzBC,0BAA0B,EAC1BC,gBAAgB,QAIX,kCAA8B;AACrC,SACEC,0BAA0B,EAC1BC,2BAA2B,QAItB,6BAAyB;AAChC,SACEC,iCAAiC,EACjCC,4BAA4B,EAE5BC,4BAA4B,QACvB,0BAAsB;AAC7B,SAASC,wBAAwB,EAAEC,qBAAqB,EAAEC,iBAAiB,QAAQ,yBAAqB;AACxG,SACEC,kBAAkB,EAClBC,4BAA4B,EAC5BC,eAAe,EACfC,mBAAmB,QACd,mBAAe;AACtB,SAASC,cAAc,QAAQ,4BAAwB;AACvD,SAASC,cAAc,QAAQ,wBAAoB;AACnD,SAASC,mBAAmB,QAAQ,yBAAqB;AAEzD,SACEC,qBAAqB,EACrBC,4BAA4B,EAC5BC,4BAA4B,QACvB,+BAA2B;AAkClC,0FAA0F,GAC1F,OAAO,SAASC,sBACdC,IAAwB,EACxBC,EAA6B,EAC7BC,MAAc,EACdC,QAAsE;QAGzDA;IADb,IAAI,CAACF,MAAM,EAACE,4BAAAA,SAAUC,OAAO,GAAE,OAAO;IACtC,MAAMC,QAAOF,uBAAAA,SAASG,KAAK,CAACC,IAAI,CAAC,CAACC,QAAUA,MAAMP,EAAE,KAAKC,4BAA5CC,qBAAqDM,SAAS;IAC3E,OAAOJ,OACH7E,cAAc;QAAE4E,SAASD,SAASC,OAAO;QAAEC;IAAK,GAAGL,MAAMC,MACzD1E,iBAAiB4E,SAASC,OAAO,EAAEJ,MAAMC;AAC/C;AAEA,yDAAyD,GACzD,OAAO,SAASS,uBAAuBC,QAAgB,EAAEC,YAAuC;IAC9F,MAAMC,UAAUD,eAAe,CAAC,UAAU,EAAEE,mBAAmBF,eAAe,GAAG;IACjF,OAAO,CAAC,6BAA6B,EAAEC,QAAQ,KAAK,EAAEC,mBAAmBH,WAAW;AACtF;AAEA,MAAMI,aAA6D;IACjEC,UAAUrF;IACVsF,SAASzE;IACT0E,MAAM7E;IACN8E,MAAMnF;IACNoF,OAAOlF;IACPmF,SAAS1E;IACT,kBAAkBT;IAClBoF,QAAQ/E;IACRgF,SAAS9E;IACT+E,SAAS5E;IACT,kBAAkBnB;IAClBgG,SAAS/E;IACTgF,SAASvF;IACT,aAAaC;IACbuF,MAAMrF;IACNsF,UAAUnF;IACVoF,QAAQjG;IACRkG,UAAUjG;AACZ;AAEA,MAAMkG,cAAoD;IACxDC,SAAS;IACTC,SAAS;IACTC,MAAM;IACNC,SAAS;IACTC,OAAO;AACT;AAEA,gDAAgD,GAChD,SAASC,YAAYC,KAAsC;IACzD,qBACE,MAAClE;QAAWmE,SAAQ;QAAQC,WAAU;QAAOC,IAAI;YAAEC,SAAS;YAASC,WAAW;QAAY;;YACzFL,MAAMM,KAAK,GAAG,GAAGN,MAAMM,KAAK,CAAC,EAAE,CAAC,GAAG;0BACpC,KAAC/E;gBAAKgF,MAAMP,MAAMQ,GAAG;gBAAEC,QAAO;gBAASC,KAAI;gBAAsBC,WAAU;0BACxEX,MAAMQ,GAAG;;;;AAIlB;AAEA,8BAA8B,GAC9B,SAASI,YAAYZ,KAKpB;IACC,MAAM,EAAE9B,KAAK,EAAE,GAAG8B;IAClB,qBACE,MAACvE;QAASoF,YAAW;QAAaC,SAASd,MAAMc,OAAO;QAAEC,cAAc;QAACC,aAAW9C,MAAMR,IAAI;;0BAC5F,KAAChC;gBAAayE,IAAI;oBAAEc,UAAU;oBAAIC,IAAI;oBAAMC,OAAO1B,WAAW,CAACvB,MAAMkD,IAAI,CAAC;gBAAC;0BACzE,cAAA,KAAC3G;oBAAQ4G,MAAM5C,UAAU,CAACP,MAAMR,IAAI,CAAC,CAAC2D,IAAI;oBAAEC,UAAS;;;0BAEvD,KAAC3F;gBACC4F,iBAAiB;gBACjBC,uBACE,MAAC5F;oBACC6F,WAAW;wBAAEC,IAAI;wBAAUC,IAAI;oBAAM;oBACrCC,SAAS;wBAAEF,IAAI;wBAAGC,IAAI;oBAAE;oBACxBxB,IAAI;wBAAE0B,gBAAgB;wBAAiBhB,YAAY;4BAAEc,IAAI;wBAAW;oBAAE;;sCAEtE,KAAC7F;4BAAWmE,SAAQ;4BAAQE,IAAI;gCAAE2B,YAAY;4BAAI;sCAC/C5D,MAAM6D,KAAK;;sCAEd,KAACjG;4BAAWmE,SAAQ;4BAAUkB,OAAM;4BAAiBhB,IAAI;gCAAE6B,YAAY;4BAAS;sCAC7EjF,mBAAmBmB,MAAM+D,IAAI,EAAEjC,MAAMkC,QAAQ;;;;gBAIpDC,yBACE,MAACvG;oBAAMgG,SAAS;oBAAMzB,IAAI;wBAAEe,IAAI;oBAAK;;wBAClChD,MAAMsC,GAAG,iBAAG,KAACT;4BAAYS,KAAKtC,MAAMsC,GAAG;4BAAEF,OAAOpC,MAAMkE,QAAQ;6BAAO;wBACrElE,MAAMmE,MAAM,iBACX,KAACvG;4BAAWmE,SAAQ;4BAAQE,IAAI;gCAAE6B,YAAY;gCAAY3B,WAAW;4BAAa;sCAC/EnC,MAAMmE,MAAM;6BAEb;wBACHnE,MAAMoE,KAAK,CAACC,MAAM,IAAIrE,MAAMsE,aAAa,iBACxC,MAAC1G;4BAAWmE,SAAQ;4BAAUkB,OAAM;4BAAiBjB,WAAU;;gCAC5DhC,MAAMoE,KAAK,CAACG,IAAI,CAAC;gCACjBvE,MAAMsE,aAAa,iBAClB;;wCACGtE,MAAMoE,KAAK,CAACC,MAAM,GAAG,QAAQ;sDAC9B,KAAChH;4CACCgF,MAAMnC,uBAAuBF,MAAMsE,aAAa,EAAExC,MAAM1B,YAAY;4CACpEmC,QAAO;4CACPC,KAAI;4CACJC,WAAU;sDACX;;;qCAID;;6BAEJ;;;;;;AAMhB;AAEA,kCAAkC,GAClC,SAAS+B,KAAK1C,KAA6C;IACzD,qBACE;;0BACE,KAAClE;gBAAWoE,WAAU;gBAAKD,SAAQ;gBAAQkB,OAAM;0BAC9CnB,MAAMM,KAAK;;0BAEd,KAACtF;gBAAIkF,WAAU;gBAAKC,IAAI;oBAAEwC,GAAG;oBAAG1B,UAAU;oBAAG2B,YAAY;oBAASvC,WAAW;gBAAa;0BACvFL,MAAM6C,QAAQ;;;;AAIvB;AAEA,wFAAwF,GACxF,SAASC,gBAAgBC,MAAyC,EAAEb,QAAuB;IACzF,MAAM,EAAEc,KAAK,EAAEC,QAAQ,EAAE,GAAGF;IAC5B,IAAI,CAACC,OAAO,OAAO;IACnB,IAAIA,MAAME,MAAM,KAAK,WAAWF,MAAME,MAAM,KAAK,WAAW;YAChDH;QAAV,OAAO,IAAGA,iBAAAA,OAAOI,MAAM,YAAbJ,iBAAiB,aAAa,2BAA2B,EAAEhG,mBAAmBiG,MAAMI,YAAY,EAAElB,WAAW;IACzH;IACA,MAAMmB,OAAON,OAAOO,aAAa,GAAG,CAAC,MAAM,EAAEP,OAAOO,aAAa,EAAE,GAAG;IACtE,MAAMC,QAAQ;QACZrH,4BAA4B,CAAC8G,MAAMQ,OAAO,CAAC;QAC3CR,MAAMS,EAAE,CAAClB,MAAM,GAAG,CAAC,GAAG,EAAES,MAAMS,EAAE,CAAChB,IAAI,CAAC,OAAO,GAAG;QAChDQ,WACI,GAAGA,SAASS,WAAW,CAAC,YAAY,EAAET,SAASU,SAAS,CAAC,QAAQ,EAAEN,KAAK,oBAAoB,CAAC,GAC7F;QACJ,CAAC,UAAU,EAAEtG,mBAAmBiG,MAAMI,YAAY,EAAElB,WAAW;KAChE;IACD,OAAOqB,MAAMK,MAAM,CAACC,SAASpB,IAAI,CAAC;AACpC;AAEA;;CAEC,GACD,SAASqB,kBAAkB9D,KAW1B;QAOkC+D;QAyF1BA,yBA2BKA,wBACAA;IA3HZ,MAAM,EAAEA,UAAU,EAAEC,QAAQ,EAAEC,UAAU,EAAE/B,QAAQ,EAAE,GAAGlC;IACvD,MAAM,EAAEkE,eAAe,EAAE,GAAGtJ;IAC5B,MAAMuJ,OAAO,CAACC,KAAkCrH,mBAAmBqH,IAAIlC;IACvE,MAAMmC,WAAW5G,sBAAsB,QAAQsG,WAAWO,MAAM,EAAEP,WAAWnG,MAAM,EAAEoC,MAAMnC,QAAQ;IACnG,MAAM0G,cAAc9G,sBAAsB,WAAWsG,WAAWS,SAAS,EAAET,WAAWnG,MAAM,EAAEoC,MAAMnC,QAAQ;IAC5G,MAAM4G,SAAStI,qBAAqB4H,WAAWW,UAAU;IACzD,MAAMC,YAAYC,OAAOC,OAAO,EAACd,4BAAAA,WAAWe,aAAa,YAAxBf,4BAA4B,CAAC,GAAGgB,IAAI,CACnE,CAAC,CAACC,EAAE,EAAE,CAACC,EAAE,GAAKC,OAAOF,KAAKE,OAAOD;IAEnC,MAAME,WAAW5I,2BAA2BqH,MAAM,CAAC,CAAClG;YAASqG;gBAAAA,2BAAAA,WAAWqB,YAAY,qBAAvBrB,wBAAyB,CAACrG,KAAK;;IAC5F,MAAM2H,UAAUtB,WAAWuB,cAAc,CAAC/C,MAAM,GAC5CwB,WAAWuB,cAAc,GACzBvB,WAAWvB,aAAa,GACtB;QAACuB,WAAWvB,aAAa;KAAC,GAC1B,EAAE;IACR,MAAM+C,SAAS;YACRC;QAAL,OAAKA,uBAAAA,UAAUC,SAAS,qBAAnBD,qBACDE,SAAS,CAAC3B,WAAWpG,EAAE,EACxBgI,IAAI,CAAC,IAAMzB,gBAAgB,yBAAyB;gBAAEjE,SAAS;YAAU,IACzE2F,KAAK,CAAC,IAAM1B,gBAAgB,+BAA+B;gBAAEjE,SAAS;YAAQ;IACnF;IACA,MAAM4F,OAAO,CAACtF,MAAqBD,QACjCC,qBACE,KAAChF,mBAAU;YAAE2E,WAAW3F;YAASuL,kBAAkB;QAAQ;YAAcvF,MAAMA;YAAMI,WAAU;sBAC5FL;cAGHA;IAGJ,qBACE,MAACtF;QACCkF,WAAU;QACVC,IAAI;YACFwC,GAAG;YACHvC,SAAS;YACT2F,qBAAqB;gBAAErE,IAAI;gBAAOC,IAAI;YAA2B;YACjEqE,WAAW;YACXC,QAAQ;QACV;;0BAEA,KAACvD;gBAAKpC,OAAM;0BACTyD,WAAWmC,YAAY,iBACtB,KAACpK;oBAAWmE,SAAQ;oBAAQE,IAAI;wBAAE6B,YAAY;oBAAW;8BACtD+B,WAAWmC,YAAY;qBAG1B;;0BAGJ,KAACxD;gBAAKpC,OAAM;0BACTyD,WAAWtD,MAAM,KAAK,SACrBoF,KAAKxB,UAAU,UACbN,WAAWO,MAAM,iBACnB;;wBACGuB,KAAKtB,aAAa;wBAClB;wBACAsB,KAAKxB,UAAU;;qBAGlBwB,KAAKtB,aAAa;;0BAGtB,KAAC7B;gBAAKpC,OAAM;0BACT,GAAG6D,KAAKJ,WAAWoC,WAAW,IAAIpC,WAAWqC,aAAa,GAAG,CAAC,IAAI,EAAEnC,WAAWF,WAAWqC,aAAa,GAAG,GAAG,IAAI;;0BAEpH,KAAC1D;gBAAKpC,OAAM;0BACTyD,WAAWsC,IAAI,GACZ,+FACA;;0BAEN,KAAC3D;gBAAKpC,OAAM;0BACT6E,SAAS5C,MAAM,iBACd,KAAC3G;oBAAMsE,WAAU;oBAAK0B,SAAS;oBAAMzB,IAAI;wBAAEwC,GAAG;wBAAG2D,IAAI;oBAAI;8BACtDnB,SAASoB,GAAG,CAAC,CAAC7I;;4BACCqG;wBAAd,MAAM7F,SAAQ6F,2BAAAA,WAAWqB,YAAY,qBAAvBrB,wBAAyB,CAACrG,KAAK;wBAC7C,qBACE,KAAC8I;sCACE,GAAGhK,2BAA2B,CAACkB,KAAK,CAAC,GAAG,EAAEuG,mBAAW/F,yBAAAA,MAAOuI,GAAG,mBAAI,IAAI,EAAE,EAAEtC,KAAKjG,yBAAAA,MAAO+D,IAAI,GAAG;2BADxFvE;oBAIb;qBAGF;;0BAGJ,KAACgF;gBAAKpC,OAAM;0BACTN,MAAM0G,OAAO,GACV,GAAG1G,MAAM0G,OAAO,CAACC,MAAM,IAAI3G,MAAM0G,OAAO,CAACE,KAAK,GAAG5G,MAAM0G,OAAO,CAACC,MAAM,IAAI3G,MAAM0G,OAAO,CAACC,MAAM,KAAK3G,MAAM0G,OAAO,CAACE,KAAK,GAAG,CAAC,EAAE,EAAE5G,MAAM0G,OAAO,CAACE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAC1J7C,WAAW8C,SAAS,GAClB,wBACA;;0BAER,KAACnE;gBAAKpC,OAAM;0BACTyD,EAAAA,0BAAAA,WAAW+C,WAAW,qBAAtB/C,wBAAwBxB,MAAM,IAC3BwB,WAAW+C,WAAW,CAACP,GAAG,CAACvG,MAAM+G,YAAY,EAAEtE,IAAI,CAAC,QACpD;;0BAEN,KAACC;gBAAKpC,OAAM;0BACTN,MAAMwD,OAAO,GAAGV,gBAAgB9C,MAAMwD,OAAO,EAAEtB,YAAYlC,MAAMgH,aAAa;;0BAEjF,MAACtE;gBAAKpC,OAAM;;oBACTyD,WAAWkD,WAAW,GACnB;wBACE/K,4BAA4B,CAAC6H,WAAWkD,WAAW,CAACzD,OAAO,CAAC;wBAC5DO,WAAWkD,WAAW,CAACC,QAAQ,GAAG,CAAC,KAAK,EAAE/C,KAAKJ,WAAWkD,WAAW,CAACC,QAAQ,GAAG,GAAG;wBACpFnD,WAAWkD,WAAW,CAACE,YAAY,GAC/B,CAAC,SAAS,EAAEhD,KAAKJ,WAAWkD,WAAW,CAACE,YAAY,IAAIpD,WAAWkD,WAAW,CAACG,aAAa,GAAG,CAAC,IAAI,EAAEnD,WAAWF,WAAWkD,WAAW,CAACG,aAAa,GAAG,GAAG,IAAI,GAC/J;qBACL,CAAC3E,IAAI,CAAC,SACP;oBACHsB,WAAWsD,qBAAqB,GAC7B,CAAC,EAAE,EAAEtD,WAAWsD,qBAAqB,CAAC,4DAA4D,CAAC,GACnG;;;0BAEN,MAAC3E;gBAAKpC,OAAM;;oBACTmE,OAAOA,MAAM,IAAIA,OAAO6C,aAAa,GAClC;wBACE,GAAG7C,OAAOA,MAAM,CAAC,cAAc,CAAC;wBAChC,GAAGA,OAAO6C,aAAa,CAAC,yBAAyB,CAAC;wBAClD,GAAG7C,OAAOA,MAAM,GAAGA,OAAO8C,cAAc,GAAG9C,OAAO6C,aAAa,GAAG7C,OAAO+C,qBAAqB,CAAC,kBAAkB,CAAC;wBAClHzD,EAAAA,yBAAAA,WAAWW,UAAU,qBAArBX,uBAAuB0D,cAAc,IAAG,CAAC,MAAM,EAAEtD,KAAKJ,WAAWW,UAAU,CAAC+C,cAAc,GAAG,GAAG;wBAChG1D,EAAAA,0BAAAA,WAAWW,UAAU,qBAArBX,wBAAuB2D,aAAa,IAAG,CAAC,KAAK,EAAEvD,KAAKJ,WAAWW,UAAU,CAACgD,aAAa,GAAG,GAAG;qBAC9F,CACE9D,MAAM,CAACC,SACPpB,IAAI,CAAC,SACR;oBACHgC,OAAOkD,QAAQ,CAACpF,MAAM,iBACrB,KAACvH;wBAAImF,IAAI;4BAAEe,IAAI;wBAAI;kCAChBuD,OAAOkD,QAAQ,CAACpB,GAAG,CAAC,CAAC/F,oBACpB,KAACT;gCAAsBS,KAAKA;+BAAVA;yBAGpB;;;0BAEN,KAACkC;gBAAKpC,OAAM;0BACTqE,UAAUpC,MAAM,iBACf,KAAC3G;oBAAMgG,SAAS;8BACb+C,UAAU4B,GAAG,CAAC,CAAC,CAACqB,KAAKC,SAAS,iBAC7B,MAAC7M;;8CACC,KAACc;oCAAWmE,SAAQ;oCAAQE,IAAI;wCAAE2B,YAAY;oCAAI;8CAC/CxF,iBAAiB0H,SAAS8D,KAAK,EAAE5C,OAAO0C;;8CAE3C,KAAC9L;oCAAWmE,SAAQ;oCAAUkB,OAAM;oCAAiBjB,WAAU;8CAC5D;wCACC2H,SAASE,MAAM,KAAK,OAAQF,SAASG,MAAM,GAAG,qBAAqB,aAAc;wCACjFH,SAASI,YAAY,GAAG,CAAC,aAAa,EAAEhE,WAAW4D,SAASI,YAAY,GAAG,GAAG;wCAC9EJ,SAASK,WAAW,GAAG/D,KAAK0D,SAASK,WAAW,IAAI;wCACpDL,SAASM,KAAK,GAAG,CAAC,MAAM,EAAEN,SAASM,KAAK,EAAE,GAAG;qCAC9C,CACEvE,MAAM,CAACC,SACPpB,IAAI,CAAC;;gCAEToF,SAASO,OAAO,KAAKC,0BACpB,KAACvM;oCAAWmE,SAAQ;8CAAS,CAAC,SAAS,EAAE4H,SAASO,OAAO,EAAE;qCACzD;gCACHP,SAASS,IAAI,KAAKD,0BACjB,KAACvM;oCACCmE,SAAQ;oCACRE,IAAI;wCAAE6B,YAAY;wCAAYd,IAAI;wCAAKoF,IAAI;wCAAKiC,YAAY;wCAAGC,aAAa;oCAAU;8CAErFX,SAASS,IAAI;qCAEd;gCACHT,SAASY,MAAM,iBACd,KAAC3M;oCAAWmE,SAAQ;oCAAUkB,OAAM;oCAAiBjB,WAAU;oCAAMC,IAAI;wCAAE6B,YAAY;wCAAYd,IAAI;oCAAI;8CACxG,CAAC,QAAQ,EAAE2G,SAASY,MAAM,EAAE;qCAE7B;;2BA7BIb;qBAkCd;;0BAGJ,KAAClF;gBAAKpC,OAAM;0BACT+E,QAAQ9C,MAAM,iBACb,MAAC3G;oBAAMgG,SAAS;;wBACbyD,QAAQkB,GAAG,CAAC,CAACmC;gCAG6B1I;iDAFzC,MAAC2I;;kDACC,KAACpN;wCACCgF,MAAMnC,uBAAuBsK,SAAQ1I,iBAAAA,MAAM0G,OAAO,qBAAb1G,eAAe4G,KAAK;wCACzDnG,QAAO;wCACPC,KAAI;wCACJC,WAAU;kDAET+H;;oCAEFA,WAAW3E,WAAWvB,aAAa,GAAG,eAAe;;+BAT7CkG;;wBAYZ3E,WAAW6E,aAAa,iBACvB,KAAC9M;4BAAWmE,SAAQ;4BAAUkB,OAAM;sCAAkB,CAAC,YAAY,EAAE4C,WAAW6E,aAAa,CAAC,CAAC,CAAC;6BAC9F;wBACH7E,WAAW8E,UAAU,CAACtG,MAAM,iBAC3B,KAACzG;4BAAWmE,SAAQ;4BAAUkB,OAAM;4BAAiBhB,IAAI;gCAAEE,WAAW;4BAAY;sCAC/E,CAAC,mCAAmC,EAAE0D,WAAW8E,UAAU,CAACpG,IAAI,CAAC,MAAM;6BAExE;;qBAGN;;0BAGJ,KAACC;gBAAKpC,OAAM;0BACTyD,WAAW+E,UAAU,GAClB,GAAGhM,kBAAkBiH,YAAY,GAAG,EAAEI,KAAKJ,WAAWgF,WAAW,IAAIhF,WAAWiF,YAAY,GAAG,CAAC,MAAM,EAAE/E,WAAWF,WAAWiF,YAAY,GAAG,GAAG,IAAI,GACpJ;;0BAEN,KAACtG;gBAAKpC,OAAM;0BAAqB,GAAG6D,KAAKJ,WAAWoC,WAAW,EAAE,GAAG,EAAEhC,KAAKJ,WAAWkF,WAAW,GAAG;;0BACpG,KAACvG;gBAAKpC,OAAM;0BACV,cAAA,MAAC1E;oBAAM6F,WAAU;oBAAMG,SAAS;oBAAKzB,IAAI;wBAAEU,YAAY;oBAAS;;sCAC9D,KAAC/E;4BAAWmE,SAAQ;4BAAQE,IAAI;gCAAE+I,YAAY;gCAAa7I,WAAW;4BAAY;sCAC/E0D,WAAWpG,EAAE;;sCAEhB,KAAC9B;4BAAQkG,OAAM;sCACb,cAAA,KAACzG;gCAAW6N,MAAK;gCAAQC,cAAW;gCAAyBC,SAAS9D;0CACpE,cAAA,KAAC9K;oCAAQ4G,MAAM1H,eAAe0H,IAAI;oCAAEC,UAAS;;;;;;;;;AAO3D;AAEA,OAAO,SAASgI,yBAAyBtJ,KAAoC;QA4BzEA,uCA+Ea+D,OAAAA;QA/FmBA,yBA6EmBC;IAxFrD,MAAM,EAAEuF,KAAK,EAAEC,WAAW,EAAEC,UAAU,EAAEC,YAAY,EAAE7L,QAAQ,EAAE,GAAGmC;IACnE,MAAM2J,MAAMvM,eAAemM;IAC3B,MAAMK,iBAAiBvM,oBAAoBkM,OAAOE;IAClD,MAAMI,SAASvM,sBAAsBiM,OAAOG;IAC5C,MAAMI,UAAUtM,6BAA6B+L,OAAOG;IACpD,MAAMlG,UAAUjG,6BAA6BoM,KAAKD;IAClD,MAAMK,SAASjP,oBAAoByO,OAAO;QAAES,SAAS;IAAK;IAC1D,MAAM,CAACC,aAAaC,eAAe,GAAGjO,SAAS;IAC/C,MAAM8H,aAAa8F,OAAOM,IAAI;IAC9B,MAAMnG,WAAW4F,eAAeO,IAAI;IACpC,MAAMC,YAAYvP,gBAAgB0O,OAAO;QACvCS,SAASC,eAAepG,QAAQE,+BAAAA,0BAAAA,WAAY+C,WAAW,qBAAvB/C,wBAAyBxB,MAAM;IACjE;IACA,MAAMuF,QAAQ9L,QAAQ;;uBAAMgI,4BAAAA,SAAU8D,KAAK,mBAAI,EAAE;OAAE;QAAC9D;KAAS;IAC7D,MAAMqG,UAAU1N,6BAA6B;QAAEgN;QAAK7B;IAAM;IAE1D,MAAM7D,aAAalI,YACjB,CAAC0K;;YAAgBsD;wBAAAA,uBAAAA,OAAOO,OAAO,CAACrM,IAAI,CAAC,CAACsM,SAAWA,OAAO9D,GAAG,KAAKA,yBAA/CsD,qBAAqDzJ,KAAK,mBAAI;OAC/E;QAACyJ,OAAOO,OAAO;KAAC;IAElB,MAAMvD,eAAehL,YACnB,CAAC4B;;YAAeyM;wBAAAA,0BAAAA,UAAUE,OAAO,CAACrM,IAAI,CAAC,CAACsM,SAAWA,OAAOC,KAAK,KAAK7M,wBAApDyM,wBAAyD9J,KAAK,mBAAI3C;OAClF;QAACyM,UAAUE,OAAO;KAAC;IAGrB,MAAMG,kBAAkB,GAAGjB,YAAY,CAAC,EAAEC,WAAW,YAAY,CAAC;IAClE,MAAM/C,WACJ1G,kCAAAA,MAAM0K,SAAS,CAACA,SAAS,CAACzM,IAAI,CAAC,CAACC,QAAUA,MAAMP,EAAE,KAAMoG,CAAAA,CAAAA,8BAAAA,WAAY8C,SAAS,MAAI7C,4BAAAA,SAAU6C,SAAS,CAAD,cAAnG7G,kCAA0G;IAC5G,MAAMkC,mBAAWwE,2BAAAA,QAASiE,QAAQ,mBAAI;IACtC,MAAMxG,OAAO,CAACC,KAAkCrH,mBAAmBqH,IAAIlC;IACvE,MAAM0I,WAAW5O,QACf;;YAQiBwH,qBAAAA;eAPfO,aACI1H,2BAA2B;YACzB0H;YACA+D;YACAgC,SAASA,QAAQ5G,MAAM,KAAK,UAAU4G,QAAQK,IAAI,GAAG;YACrDlG;YACA4G,YAAY,CAACzG,KAAOrH,mBAAmBqH,IAAIlC;YAC3CsB,OAAO,WAAEA,gBAAAA,QAAQ2G,IAAI,sBAAZ3G,sBAAAA,cAAcR,KAAK,qBAAnBQ,oBAAqBA,OAAO,mBAAI;QAC3C,KACA,EAAE;OACR;QAACO;QAAY+D;QAAOgC;QAAS7F;QAAY/B;QAAUsB,QAAQ2G,IAAI;KAAC;IAGlE,MAAMW,qBACJ,KAAC7P,qBAEM;QAAEiF,WAAW3F;QAASuL,kBAAkB;QAASiF,cAAc;IAAM;QAC1ExK,MAAMkK;QACNtB,MAAK;QACLhI,OAAM;kBACP;;IAKH,IAAI0I,OAAO3G,MAAM,KAAK,aAAa0G,eAAe1G,MAAM,KAAK,WAAW;QACtE,qBAAO,KAACjG;YAAgBqD,OAAM;;IAChC;IACA,IAAIuJ,OAAO3G,MAAM,KAAK,WAAW2G,OAAO3G,MAAM,KAAK,WAAW;QAC5D,qBAAO,KAAChG;YAAoBgG,QAAQ2G,OAAO3G,MAAM;YAAE8H,MAAK;;IAC1D;IACA,IAAIpB,eAAe1G,MAAM,KAAK,WAAW0G,eAAe1G,MAAM,KAAK,WAAW;QAC5E,qBAAO,KAAChG;YAAoBgG,QAAQ0G,eAAe1G,MAAM;YAAE8H,MAAK;;IAClE;IACA,qEAAqE;IACrE,IAAI,CAACjH,cAAc,CAACC,YAAYD,WAAW0F,UAAU,KAAKA,YAAY;QACpE,qBACE,KAACvO;YAAK+E,SAAQ;sBACZ,cAAA,KAACvF;gBACC4F,OAAM;gBACN2K,aAAY;gBACZC,QAAQJ;;;IAIhB;IAEA,MAAMK,OAAOpH,WAAWqH,WAAW,IAAIrH,WAAW6C,KAAK;IACvD,MAAMlJ,OAAOqG,WAAWtD,MAAM,KAAK,SAAS,SAAS;IACrD,MAAM4K,aAAa5N,sBACjBC,MACAA,SAAS,SAASqG,WAAWO,MAAM,GAAGP,WAAWS,SAAS,EAC1DT,WAAWnG,MAAM,EACjBC;IAEF,MAAMyN,UAAUlP,0BAA0B2H;IAC1C,MAAMwH,cAAcvH,SAASwH,QAAQ,CAACD,WAAW,IAAIvH,EAAAA,kBAAAA,SAASyH,KAAK,qBAAdzH,gBAAgB0H,YAAY,MAAK;IACtF,MAAMC,OAAO5H,WAAWb,MAAM,KAAK,YAAYa,WAAWb,MAAM,KAAK;IACrE,MAAM7D,OAAO0E,WAAWb,MAAM,KAAK,YAAYa,WAAW+E,UAAU,KAAK;IAEzE;;;;GAIC,GACD,MAAM8C,YAAYlP,6BAA6BqH,YAAY+D;IAC3D,MAAMtG,UAA8CoK,UAAUC,QAAQ,CAAC,YACnE,WACAD,UAAUC,QAAQ,CAAC,YACjB,WACA;IACN,MAAMC,OAAOzB,QAAQ0B,SAAS,CAAChI,YAAY,CAACmH,SAAWA,WAAW1J;IAClE,MAAMwK,OAAO,CAACxB,QAAmBA,QAAQA,MAAMyB,cAAc,KAAK;IAClE,MAAMC,aAAa,CAACX,eAAe,CAACD,QAAQ7G,MAAM,IAAI,CAAC6G,QAAQa,aAAa,GAAG,gBAAgB9D;IAC/F,MAAMK,UAAS3E,SAAAA,4BAAAA,WAAWvB,aAAa,YAAxBuB,4BAA4BA,WAAWuB,cAAc,CAAC8G,EAAE,CAAC,CAAC,cAA1DrI,QAAgE;IAC/E,MAAMsI,aACJtI,WAAWb,MAAM,KAAK,YAAYa,WAAWuI,WAAW,GACpD,CAAC,mBAAmB,EAAEvI,WAAWwI,SAAS,GAAG,EAAE,OAAO,EAAEpI,KAAKJ,WAAWuI,WAAW,EAAE,CAAC,CAAC,GACvF;IAEN,qBACE,MAAC1Q;QAAMgG,SAAS;;0BAEd,KAAC7I;gBAAiBgJ,OAAOoJ;;0BACzB,KAAC3Q;gBACCgS,QAAO;gBACPC,yBACE;;wBACG1I,WAAWqH,WAAW,GAAG,GAAGrH,WAAW6C,KAAK,CAAC,GAAG,CAAC,GAAG;wBACpD,CAAC,GAAG,EAAE5C,SAASmH,IAAI,IAAI,YAAY;;;gBAGxCuB,MAAM1T,eAAe,aAAa;oBAAE2T,QAAQ;gBAAkB;gBAC9DC,cAAc;gBACdC,cAAc;gBACdC,aAAa;oBACX5B,sBACE,MAACtP;wBAAM6F,WAAU;wBAAMG,SAAS;wBAAGzB,IAAI;4BAAEU,YAAY;4BAAUkM,UAAU;4BAAQ9G,QAAQ;wBAAE;;4BACxF6E;4BACAtJ,wBACC,KAACvG;gCACCgF,SAAQ;gCACRkJ,MAAK;gCACL6D,UAAU3C,QAAQ4C,IAAI,KAAKlJ,WAAWpG,EAAE;gCACxC0L,SAAS,IAAMgB,QAAQ6C,MAAM,CAACnJ,YAAYvC;0CAEzCnC,OAAO,oBAAoB5C,iCAAiC,CAAC+E,QAAQ;iCAEtE;4BACHsK,KAAKvJ,MAAM,iBAAG,KAAC5H;gCAAe2F,OAAO6K;gCAAMgC,OAAOrB;iCAAW;;;gBAGpE;0BAEA,cAAA,MAAClQ;oBAAMgG,SAAS;;sCACd,MAAChG;4BAAM6F,WAAU;4BAAMG,SAAS;4BAAGzB,IAAI;gCAAEU,YAAY;gCAAUkM,UAAU;gCAAQ9G,QAAQ;4BAAE;;8CACzF,KAACpK;oCACCuR,aAAa;oCACbrL,OAAOsJ,aAAa,CAAC,SAAS,EAAE3N,KAAK,WAAW,CAAC,GAAG,CAAC,IAAI,EAAEA,KAAK,yBAAyB,CAAC;8CAE1F,cAAA,KAACvC;wCACCgO,MAAK;wCACLlJ,SAAQ;wCACRkB,OAAOkK,aAAa,YAAY;wCAChCgC,oBAAM,KAAC5S;4CAAQ4G,MAAMjI,kBAAkBiI,IAAI;4CAAEC,UAAS;;wCACtDhB,OAAO5C,SAAS,SAAS,SAAS;uCAC7B2N,aACA;wCAAEnL,WAAW3F;wCAASgG,MAAM8K;wCAAYiC,WAAW;wCAAMxH,kBAAkB;oCAAQ,IACpF,CAAC;;8CAGT,KAAC9I;oCAA6BkG,QAAQa,WAAWb,MAAM;;8CACvD,KAAC/H;oCAAKgO,MAAK;oCAAQlJ,SAAQ;oCAAWK,OAAO1D,yBAAyBmH,YAAY+D;;gCACjFjL,sBAAsBkH,4BACrB,KAAC5I;oCAAKgO,MAAK;oCAAQlJ,SAAQ;oCAAWkB,OAAM;oCAAUb,OAAM;qCAC1D;gCACHqL,QAAQ5H,WAAWuI,WAAW,iBAC7B,KAACnR;oCAAKgO,MAAK;oCAAQlJ,SAAQ;oCAAWK,OAAO,CAAC,UAAU,EAAE6D,KAAKJ,WAAWuI,WAAW,GAAG;qCACtF;;;wBAELjN,qBACC,KAACtE;4BAAMwS,UAAS;sCACbxJ,WAAWyJ,UAAU,IACpB;6BAEF;wBACHlC,QAAQmC,QAAQ,iBACf,MAAC7R;4BAAM6F,WAAU;4BAAMG,SAAS;4BAAGzB,IAAI;gCAAE4M,UAAU;gCAAQ9G,QAAQ;4BAAE;4BAAGyH,MAAK;4BAAQtE,cAAW;;8CAC9F,KAACjM;oCAAemD,OAAM;oCAAckK,OAAOwB,KAAKV,QAAQqC,UAAU;;8CAClE,KAACxQ;oCAAemD,OAAM;oCAASkK,OAAOwB,KAAKV,QAAQ7G,MAAM;oCAAGmJ,MAAM1B;;8CAClE,KAAC/O;oCACCmD,OAAM;oCACNkK,OACEc,QAAQuC,aAAa,CAACC,KAAK,GACvB,GAAGxC,QAAQuC,aAAa,CAACC,KAAK,GAAGxC,QAAQuC,aAAa,CAACE,OAAO,GAAG,MAAM,IAAI,GAC3E;oCAENH,IAAI,EACF1B,qBAAAA,aACCZ,QAAQuC,aAAa,CAACE,OAAO,IAAIzC,QAAQuC,aAAa,CAACC,KAAK,GACzD,2CACAzF;;8CAGR,KAAClL;oCAAemD,OAAM;oCAAiBkK,OAAOwB,KAAKV,QAAQa,aAAa;oCAAGyB,IAAI,EAAE1B,qBAAAA,aAAc;;8CAC/F,KAAC/O;oCAAemD,OAAM;oCAAUkK,OAAOwB,KAAKV,QAAQ0C,OAAO;;;2CAG7D,KAAClS;4BAAWmE,SAAQ;4BAAQkB,OAAM;sCAC/BkL;;;;;0BAMT,KAAC7R;gBACCgS,QAAO;gBACPC,WAAU;gBACVC,MAAM1T,eAAe,aAAa;oBAAE2T,QAAQ;gBAAkB;gBAC9DC,cAAc;gBACdC,cAAc;gBACdC,aACEpE,SACI;oBACEwC,sBACE,KAACjQ;wBACCkO,MAAK;wBACL5I,MAAMnC,uBAAuBsK,QAAQhC,2BAAAA,QAASE,KAAK;wBACnDnG,QAAO;wBACPC,KAAI;kCACL;;gBAIL,IACA2H;0BAGN,cAAA,MAACzM;oBAAMgG,SAAS;;wBACbkI,QAAQ5G,MAAM,KAAK,0BAAY,KAACjG;4BAAgBqD,OAAM;6BAA6B;wBACnFwJ,QAAQ5G,MAAM,KAAK,WAAW4G,QAAQ5G,MAAM,KAAK,0BAChD,KAAChG;4BACCgG,QAAQ4G,QAAQ5G,MAAM;4BACtB8H,MAAK;4BACL,iEAAiE;4BACjE,6DAA6D;4BAC7DiD,SACEnE,QAAQ5G,MAAM,KAAK,YACf,sFACA;6BAGN;sCACJ,KAAC1H;4BAAK0S,cAAc;4BAAC9E,cAAW;sCAC7BwB,SAASrE,GAAG,CAAC,CAACrI,OAAOiQ;;qDACpB,KAACvN;oCAEC1C,OAAOA;oCACPgE,UAAUA;oCACV5D,YAAY,UAAEoI,2BAAAA,QAASE,KAAK,mBAAI;oCAChC9F,SAASqN,QAAQvD,SAASrI,MAAM,GAAG;mCAJ9BrE,MAAM0J,GAAG;;;;;;0BAWxB,KAACpN;gBACCgS,QAAO;gBACPE,MAAM1T,eAAe,aAAa;oBAAE2T,QAAQ;gBAAkB;gBAC9DC,cAAc;gBACdE,aAAa;oBACX5B,sBACE,KAACjQ;wBACCkO,MAAK;wBACLiF,iBAAenE;wBACfoE,iBAAc;wBACdC,uBAAS,KAAC7T;4BAAQ4G,MAAM,AAAC4I,CAAAA,cAAcxQ,eAAeD,cAAa,EAAG6H,IAAI;4BAAEC,UAAS;;wBACrF+H,SAAS,IAAMa,eAAe,CAACqE,MAAQ,CAACA;kCAEvCtE,cAAc,SAAS;;gBAG9B;0BAEA,cAAA,KAAC7O;oBAASoT,IAAIvE;oBAAawE,aAAa;8BACtC,cAAA,MAACzT;wBAAI2C,IAAG;wBAA8BwC,IAAI;4BAAEuO,IAAI;wBAAE;;0CAChD,KAACrT;gCAAQ8E,IAAI;oCAAEwO,IAAI;gCAAE;;0CACrB,KAAC7K;gCACCC,YAAYA;gCACZC,UAAUA;gCACV0C,SAASA;gCACTlD,SAASA,QAAQN,MAAM,KAAK,UAAUM,QAAQ2G,IAAI,GAAG;gCACrDnD,eACExD,QAAQN,MAAM,KAAK,YACf,mBACAM,QAAQN,MAAM,KAAK,YACjB,gCACA;gCAER6D,cAAcA;gCACd9C,YAAYA;gCACZpG,UAAUA;gCACVqE,UAAUA;;;;;;YAMjBmI,QAAQuE,OAAO;;;AAGtB;AACAtF,yBAAyBuF,WAAW,GAAG;AAEvC,eAAevF,yBAAwB"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/outreach/src/lib/components/enrollment-detail.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type ConsolePluginOrgMount,\n PageHeaderRecord,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport { crmOrgRecordHref, crmRecordHref } from '@aglyn/aglyn/app-utils/console-record-links'\nimport {\n mdiAccountCancelOutline,\n mdiAccountOutline,\n mdiAccountPlusOutline,\n mdiAlertCircleOutline,\n mdiCheckCircleOutline,\n mdiChevronDown,\n mdiChevronUp,\n mdiClipboardCheckOutline,\n mdiContentCopy,\n mdiCursorDefaultClickOutline,\n mdiEmailAlertOutline,\n mdiEmailOffOutline,\n mdiEmailOutline,\n mdiHandBackLeftOutline,\n mdiPauseCircleOutline,\n mdiPencilOutline,\n mdiPlayCircleOutline,\n mdiReply,\n mdiShieldSearch,\n mdiStopCircleOutline,\n} from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport RowActionsMenu from '@aglyn/shared-ui-jsx/components/row-actions-menu.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useOrgCampaigns, useOrgMemberOptions } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Card,\n Chip,\n Collapse,\n Divider,\n IconButton,\n Link,\n List,\n ListItem,\n ListItemIcon,\n ListItemText,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { type ReactNode, useCallback, useMemo, useState } from 'react'\nimport { OUTREACH_MAIL_GATEWAY_LABELS } from '../engine/mail-gateway'\nimport { outreachNextSendState } from '../engine/next-send'\nimport { outreachClickSummary } from '../model/enrollment-engagement'\nimport {\n outreachEnrollmentFigures,\n outreachEnrollmentTimeline,\n outreachStepName,\n type OutreachTimelineEntry,\n type OutreachTimelineKind,\n type OutreachTimelineTone,\n} from '../model/enrollment-timeline'\nimport {\n OUTREACH_ATTESTATION_KINDS,\n OUTREACH_ATTESTATION_LABELS,\n type OutreachEnrollment,\n type OutreachMailbox,\n type OutreachSequence,\n} from '../model/outreach.types'\nimport {\n OUTREACH_ENROLLMENT_ACTION_LABELS,\n outreachEnrollmentActionsFor,\n type OutreachEnrollmentRowAction,\n useOutreachEnrollmentActions,\n} from './enrollment-actions'\nimport { outreachCurrentStepLabel, outreachStepIsCurated, outreachStopLabel } from './enrollments-table'\nimport {\n formatOutreachTime,\n OutreachEnrollmentStatusChip,\n OutreachLoading,\n OutreachLoadProblem,\n} from './outreach-ui'\nimport { outreachNextSendDetail, outreachNextSendLabel, useOutreachNowMs } from './next-send'\nimport { OutreachFigure } from './sequence-report-card'\nimport { useOutreachApi } from './use-outreach-api'\nimport { useOutreachSequence } from './use-outreach-data'\nimport type { OutreachEnrollmentGatewayResponse } from '../model/outreach-api'\nimport {\n useOutreachEnrollment,\n useOutreachEnrollmentGateway,\n useOutreachEnrollmentHistory,\n} from './use-outreach-enrollment'\nimport type { OutreachMailboxesResult } from './use-outreach-mailboxes'\n\n/*==========================================\n * ONE PERSON IN ONE SEQUENCE (AGL-3332):\n * `/[orgSlug]/outreach/sequences/{sequenceId}/enrollments/{enrollmentId}`.\n *\n * A row of the Enrollments tab opens it, and its URL is the person's: a\n * comment or a message can link straight to them.\n *\n * Laid out the way every record page in the console is (the CRM's\n * `CrmRecordHeader` grammar): the page heading names the person; the first\n * card says what the record is, with the way back and the actions in its\n * HEADER — the one that changes things as a button, the rest and the\n * destructive ones behind the menu — and the facts that identify it as\n * chips. Under the chips, five numbers.\n *\n * Then ONE timeline, newest first, which is the page: every send, click,\n * reply, bounce, stop, hold and resume, from `model/enrollment-timeline.ts`.\n * Everything else stored on the enrollment is under Details, closed until\n * asked for — nothing is left out, and nothing is in the way.\n *=========================================*/\n\nexport interface OutreachEnrollmentDetailProps {\n orgId: string\n /** The org the hub is mounted under: its slug and sites, for the CRM record's address. */\n orgMount?: ConsolePluginOrgMount\n /** `/[orgSlug]/outreach/sequences`. */\n sectionPath: string\n sequenceId: string\n enrollmentId: string\n mailboxes: OutreachMailboxesResult\n}\n\n/** Where the CRM record the person is lives — the site's own CRM when the site is known. */\nexport function outreachCrmRecordHref(\n kind: 'lead' | 'contact',\n id: string | null | undefined,\n hostId: string,\n orgMount: Pick<ConsolePluginOrgMount, 'orgSlug' | 'hosts'> | undefined,\n): string | null {\n if (!id || !orgMount?.orgSlug) return null\n const host = orgMount.hosts.find((entry) => entry.id === hostId)?.subdomain\n return host\n ? crmRecordHref({ orgSlug: orgMount.orgSlug, host }, kind, id)\n : crmOrgRecordHref(orgMount.orgSlug, kind, id)\n}\n\n/** A Gmail thread, opened in the mailbox's own account. */\nexport function outreachGmailThreadUrl(threadId: string, mailboxEmail: string | null | undefined): string {\n const account = mailboxEmail ? `?authuser=${encodeURIComponent(mailboxEmail)}` : ''\n return `https://mail.google.com/mail/${account}#all/${encodeURIComponent(threadId)}`\n}\n\nconst KIND_ICONS: Record<OutreachTimelineKind, { path: string }> = {\n enrolled: mdiAccountPlusOutline,\n curated: mdiPencilOutline,\n sent: mdiEmailOutline,\n task: mdiClipboardCheckOutline,\n click: mdiCursorDefaultClickOutline,\n scanner: mdiShieldSearch,\n 'earlier-clicks': mdiCursorDefaultClickOutline,\n paused: mdiPauseCircleOutline,\n resumed: mdiPlayCircleOutline,\n stopped: mdiStopCircleOutline,\n 'do-not-contact': mdiAccountCancelOutline,\n replied: mdiReply,\n bounced: mdiEmailAlertOutline,\n 'opted-out': mdiEmailOffOutline,\n held: mdiHandBackLeftOutline,\n released: mdiPlayCircleOutline,\n failed: mdiAlertCircleOutline,\n finished: mdiCheckCircleOutline,\n}\n\nconst TONE_COLORS: Record<OutreachTimelineTone, string> = {\n default: 'text.secondary',\n success: 'success.main',\n info: 'info.main',\n warning: 'warning.main',\n error: 'error.main',\n}\n\n/** A destination, whole, opening in a new tab. */\nfunction Destination(props: { url: string; label?: string }) {\n return (\n <Typography variant=\"body2\" component=\"span\" sx={{ display: 'block', wordBreak: 'break-all' }}>\n {props.label ? `${props.label}: ` : null}\n <Link href={props.url} target=\"_blank\" rel=\"noopener noreferrer\" underline=\"hover\">\n {props.url}\n </Link>\n </Typography>\n )\n}\n\n/** One line of the timeline. */\nfunction TimelineRow(props: {\n entry: OutreachTimelineEntry\n timeZone: string | null\n mailboxEmail: string | null\n divider: boolean\n}) {\n const { entry } = props\n return (\n <ListItem alignItems=\"flex-start\" divider={props.divider} disableGutters data-kind={entry.kind}>\n <ListItemIcon sx={{ minWidth: 36, mt: 0.75, color: TONE_COLORS[entry.tone] }}>\n <MdiIcon path={KIND_ICONS[entry.kind].path} fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n disableTypography\n primary={\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={{ xs: 0, sm: 1 }}\n sx={{ justifyContent: 'space-between', alignItems: { sm: 'baseline' } }}\n >\n <Typography variant=\"body2\" sx={{ fontWeight: 500 }}>\n {entry.title}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ whiteSpace: 'nowrap' }}>\n {formatOutreachTime(entry.atMs, props.timeZone)}\n </Typography>\n </Stack>\n }\n secondary={\n <Stack spacing={0.25} sx={{ mt: 0.25 }}>\n {entry.url ? <Destination url={entry.url} label={entry.urlLabel} /> : null}\n {entry.detail ? (\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>\n {entry.detail}\n </Typography>\n ) : null}\n {entry.facts.length || entry.gmailThreadId ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {entry.facts.join(' · ')}\n {entry.gmailThreadId ? (\n <>\n {entry.facts.length ? ' · ' : null}\n <Link\n href={outreachGmailThreadUrl(entry.gmailThreadId, props.mailboxEmail)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n underline=\"hover\"\n >\n Open thread in Gmail\n </Link>\n </>\n ) : null}\n </Typography>\n ) : null}\n </Stack>\n }\n />\n </ListItem>\n )\n}\n\n/** One fact of the Details list. */\nfunction Fact(props: { label: string; children: ReactNode }) {\n return (\n <>\n <Typography component=\"dt\" variant=\"body2\" color=\"text.secondary\">\n {props.label}\n </Typography>\n <Box component=\"dd\" sx={{ m: 0, minWidth: 0, typography: 'body2', wordBreak: 'break-word' }}>\n {props.children}\n </Box>\n </>\n )\n}\n\n/** What mail from the sequence's sending domain met at the person's domain, in a line. */\nfunction gatewaySentence(answer: OutreachEnrollmentGatewayResponse, timeZone: string | null): string {\n const { intel, standing } = answer\n if (!intel) return 'Could not be looked up'\n if (intel.status === 'no_mx' || intel.status === 'null_mx') {\n return `${answer.domain ?? 'The domain'} takes no mail · looked up ${formatOutreachTime(intel.resolvedAtMs, timeZone)}`\n }\n const from = answer.sendingDomain ? ` from ${answer.sendingDomain}` : ''\n const parts = [\n OUTREACH_MAIL_GATEWAY_LABELS[intel.gateway],\n intel.mx.length ? `MX ${intel.mx.join(', ')}` : 'no MX; delivered to its address record',\n standing\n ? `${standing.delivered30} delivered, ${standing.blocked30} refused${from} in the last 30 days`\n : null,\n `looked up ${formatOutreachTime(intel.resolvedAtMs, timeZone)}`,\n ]\n return parts.filter(Boolean).join(' · ')\n}\n\n/**\n * Everything else the enrollment holds, all of it, behind one toggle.\n */\nfunction EnrollmentDetails(props: {\n enrollment: OutreachEnrollment\n sequence: OutreachSequence\n mailbox: OutreachMailbox | null\n gateway: OutreachEnrollmentGatewayResponse | null\n /** What the Mail gateway line says while there is no answer to show. */\n gatewayUnread: string\n campaignName: (id: string) => string\n memberName: (uid: string) => string\n orgMount?: ConsolePluginOrgMount\n timeZone: string | null\n}) {\n const { enrollment, sequence, memberName, timeZone } = props\n const { enqueueSnackbar } = useSnackbar()\n const time = (ms: number | null | undefined) => formatOutreachTime(ms, timeZone)\n const leadHref = outreachCrmRecordHref('lead', enrollment.leadId, enrollment.hostId, props.orgMount)\n const contactHref = outreachCrmRecordHref('contact', enrollment.contactId, enrollment.hostId, props.orgMount)\n const clicks = outreachClickSummary(enrollment.engagement)\n const overrides = Object.entries(enrollment.stepOverrides ?? {}).sort(\n ([a], [b]) => Number(a) - Number(b),\n )\n const attested = OUTREACH_ATTESTATION_KINDS.filter((kind) => enrollment.attestations?.[kind])\n const threads = enrollment.gmailThreadIds.length\n ? enrollment.gmailThreadIds\n : enrollment.gmailThreadId\n ? [enrollment.gmailThreadId]\n : []\n const copyId = () => {\n void navigator.clipboard\n ?.writeText(enrollment.id)\n .then(() => enqueueSnackbar('Enrollment id copied.', { variant: 'success' }))\n .catch(() => enqueueSnackbar('The id could not be copied.', { variant: 'error' }))\n }\n const link = (href: string | null, label: string) =>\n href ? (\n <Link {...({ component: AppLink, componentVariant: 'naked' } as object)} href={href} underline=\"hover\">\n {label}\n </Link>\n ) : (\n label\n )\n\n return (\n <Box\n component=\"dl\"\n sx={{\n m: 0,\n display: 'grid',\n gridTemplateColumns: { xs: '1fr', sm: 'minmax(160px, 220px) 1fr' },\n columnGap: 2,\n rowGap: 1.25,\n }}\n >\n <Fact label=\"Personal line\">\n {enrollment.personalLine ? (\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap' }}>\n {enrollment.personalLine}\n </Typography>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Enrolled as\">\n {enrollment.target === 'lead' ? (\n link(leadHref, 'Lead')\n ) : enrollment.leadId ? (\n <>\n {link(contactHref, 'Contact')}\n {', converted from a '}\n {link(leadHref, 'lead')}\n </>\n ) : (\n link(contactHref, 'Contact')\n )}\n </Fact>\n <Fact label=\"Enrolled\">\n {`${time(enrollment.createdAtMs)}${enrollment.enrolledByUid ? ` by ${memberName(enrollment.enrolledByUid)}` : ''}`}\n </Fact>\n <Fact label=\"Cold contact\">\n {enrollment.cold\n ? 'Yes — no inbound capture behind them, so the member confirmed the address before enrolling'\n : 'No'}\n </Fact>\n <Fact label=\"Attestations\">\n {attested.length ? (\n <Stack component=\"ul\" spacing={0.25} sx={{ m: 0, pl: 2.5 }}>\n {attested.map((kind) => {\n const entry = enrollment.attestations?.[kind]\n return (\n <li key={kind}>\n {`${OUTREACH_ATTESTATION_LABELS[kind]} — ${memberName(entry?.uid ?? '')}, ${time(entry?.atMs)}`}\n </li>\n )\n })}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Mailbox\">\n {props.mailbox\n ? `${props.mailbox.sendAs || props.mailbox.email}${props.mailbox.sendAs && props.mailbox.sendAs !== props.mailbox.email ? ` (${props.mailbox.email})` : ''}`\n : enrollment.mailboxId\n ? 'No longer connected'\n : '—'}\n </Fact>\n <Fact label=\"Campaigns\">\n {enrollment.campaignIds?.length\n ? enrollment.campaignIds.map(props.campaignName).join(', ')\n : '—'}\n </Fact>\n <Fact label=\"Mail gateway\">\n {props.gateway ? gatewaySentence(props.gateway, timeZone) : props.gatewayUnread}\n </Fact>\n <Fact label=\"Gateway hold\">\n {enrollment.gatewayHold\n ? [\n OUTREACH_MAIL_GATEWAY_LABELS[enrollment.gatewayHold.gateway],\n enrollment.gatewayHold.heldAtMs ? `held ${time(enrollment.gatewayHold.heldAtMs)}` : 'never held',\n enrollment.gatewayHold.releasedAtMs\n ? `released ${time(enrollment.gatewayHold.releasedAtMs)}${enrollment.gatewayHold.releasedByUid ? ` by ${memberName(enrollment.gatewayHold.releasedByUid)}` : ''}`\n : 'not released',\n ].join(' · ')\n : '—'}\n {enrollment.gatewayDeliveredSteps\n ? ` (${enrollment.gatewayDeliveredSteps} of their emails counted as delivered on the gateway ledger)`\n : null}\n </Fact>\n <Fact label=\"Clicks\">\n {clicks.clicks || clicks.machineClicks\n ? [\n `${clicks.clicks} by the person`,\n `${clicks.machineClicks} by scanners, not counted`,\n `${clicks.clicks - clicks.unloggedClicks + clicks.machineClicks - clicks.unloggedMachineClicks} listed one by one`,\n enrollment.engagement?.firstClickAtMs ? `first ${time(enrollment.engagement.firstClickAtMs)}` : null,\n enrollment.engagement?.lastClickAtMs ? `last ${time(enrollment.engagement.lastClickAtMs)}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n : '—'}\n {clicks.followed.length ? (\n <Box sx={{ mt: 0.5 }}>\n {clicks.followed.map((url) => (\n <Destination key={url} url={url} />\n ))}\n </Box>\n ) : null}\n </Fact>\n <Fact label=\"Curated steps\">\n {overrides.length ? (\n <Stack spacing={1.5}>\n {overrides.map(([key, override]) => (\n <Box key={key}>\n <Typography variant=\"body2\" sx={{ fontWeight: 500 }}>\n {outreachStepName(sequence.steps, Number(key))}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {[\n override.source === 'ai' ? (override.edited ? 'AI draft, edited' : 'AI draft') : 'Written by a member',\n override.draftedByUid ? `confirmed by ${memberName(override.draftedByUid)}` : null,\n override.draftedAtMs ? time(override.draftedAtMs) : null,\n override.model ? `model ${override.model}` : null,\n ]\n .filter(Boolean)\n .join(' · ')}\n </Typography>\n {override.subject !== undefined ? (\n <Typography variant=\"body2\">{`Subject: ${override.subject}`}</Typography>\n ) : null}\n {override.body !== undefined ? (\n <Typography\n variant=\"body2\"\n sx={{ whiteSpace: 'pre-wrap', mt: 0.5, pl: 1.5, borderLeft: 2, borderColor: 'divider' }}\n >\n {override.body}\n </Typography>\n ) : null}\n {override.prompt ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ whiteSpace: 'pre-wrap', mt: 0.5 }}>\n {`Prompt: ${override.prompt}`}\n </Typography>\n ) : null}\n </Box>\n ))}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Gmail threads\">\n {threads.length ? (\n <Stack spacing={0.25}>\n {threads.map((thread) => (\n <span key={thread}>\n <Link\n href={outreachGmailThreadUrl(thread, props.mailbox?.email)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n underline=\"hover\"\n >\n {thread}\n </Link>\n {thread === enrollment.gmailThreadId ? ' (current)' : null}\n </span>\n ))}\n {enrollment.threadSubject ? (\n <Typography variant=\"caption\" color=\"text.secondary\">{`Started as “${enrollment.threadSubject}”`}</Typography>\n ) : null}\n {enrollment.messageIds.length ? (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ wordBreak: 'break-all' }}>\n {`Message-IDs in the current thread: ${enrollment.messageIds.join(' ')}`}\n </Typography>\n ) : null}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n <Fact label=\"Stop\">\n {enrollment.stopReason\n ? `${outreachStopLabel(enrollment)} · ${time(enrollment.stoppedAtMs)}${enrollment.stoppedByUid ? ` · by ${memberName(enrollment.stoppedByUid)}` : ''}`\n : '—'}\n </Fact>\n <Fact label=\"Created · updated\">{`${time(enrollment.createdAtMs)} · ${time(enrollment.updatedAtMs)}`}</Fact>\n <Fact label=\"Enrollment id\">\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ fontFamily: 'monospace', wordBreak: 'break-all' }}>\n {enrollment.id}\n </Typography>\n <Tooltip title=\"Copy the id\">\n <IconButton size=\"small\" aria-label=\"Copy the enrollment id\" onClick={copyId}>\n <MdiIcon path={mdiContentCopy.path} fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Stack>\n </Fact>\n </Box>\n )\n}\n\nexport function OutreachEnrollmentDetail(props: OutreachEnrollmentDetailProps) {\n const { orgId, sectionPath, sequenceId, enrollmentId, orgMount } = props\n const api = useOutreachApi(orgId)\n const loadedSequence = useOutreachSequence(orgId, sequenceId)\n const loaded = useOutreachEnrollment(orgId, enrollmentId)\n const history = useOutreachEnrollmentHistory(orgId, enrollmentId)\n const gateway = useOutreachEnrollmentGateway(api, enrollmentId)\n const roster = useOrgMemberOptions(orgId, { enabled: true })\n const [detailsOpen, setDetailsOpen] = useState(false)\n const nowMs = useOutreachNowMs()\n const enrollment = loaded.data\n const sequence = loadedSequence.data\n const campaigns = useOrgCampaigns(orgId, {\n enabled: detailsOpen && Boolean(enrollment?.campaignIds?.length),\n })\n const steps = useMemo(() => sequence?.steps ?? [], [sequence])\n const actions = useOutreachEnrollmentActions({ api, steps })\n\n const memberName = useCallback(\n (uid: string) => roster.options.find((option) => option.uid === uid)?.label ?? 'a member',\n [roster.options],\n )\n const campaignName = useCallback(\n (id: string) => campaigns.options.find((option) => option.value === id)?.label ?? id,\n [campaigns.options],\n )\n\n const enrollmentsPath = `${sectionPath}/${sequenceId}/enrollments`\n const mailbox =\n props.mailboxes.mailboxes.find((entry) => entry.id === (enrollment?.mailboxId || sequence?.mailboxId)) ?? null\n const timeZone = mailbox?.timezone ?? null\n const time = (ms: number | null | undefined) => formatOutreachTime(ms, timeZone)\n const timeline = useMemo(\n () =>\n enrollment\n ? outreachEnrollmentTimeline({\n enrollment,\n steps,\n history: history.status === 'ready' ? history.data : null,\n memberName,\n formatTime: (ms) => formatOutreachTime(ms, timeZone),\n gateway: gateway.data?.intel?.gateway ?? null,\n })\n : [],\n [enrollment, steps, history, memberName, timeZone, gateway.data],\n )\n\n const back = (\n <Button\n // A real link, as the CRM record header's is: it opens in a new tab when asked.\n {...({ component: AppLink, componentVariant: 'naked', nativeButton: false } as object)}\n href={enrollmentsPath}\n size=\"small\"\n color=\"primary\"\n >\n Back to enrollments\n </Button>\n )\n\n if (loaded.status === 'loading' || loadedSequence.status === 'loading') {\n return <OutreachLoading label=\"Loading this person…\" />\n }\n if (loaded.status === 'error' || loaded.status === 'refused') {\n return <OutreachLoadProblem status={loaded.status} what=\"enrollment\" />\n }\n if (loadedSequence.status === 'error' || loadedSequence.status === 'refused') {\n return <OutreachLoadProblem status={loadedSequence.status} what=\"sequence\" />\n }\n // An id from another sequence reads as not here: the URL names both.\n if (!enrollment || !sequence || enrollment.sequenceId !== sequenceId) {\n return (\n <Card variant=\"outlined\">\n <EmptyStateComponent\n label=\"This person isn’t in this sequence\"\n description=\"They may have been removed from the workspace, or the link names a different sequence.\"\n action={back}\n />\n </Card>\n )\n }\n\n const name = enrollment.contactName || enrollment.email\n const kind = enrollment.target === 'lead' ? 'lead' : 'contact'\n const recordHref = outreachCrmRecordHref(\n kind,\n kind === 'lead' ? enrollment.leadId : enrollment.contactId,\n enrollment.hostId,\n orgMount,\n )\n const figures = outreachEnrollmentFigures(enrollment)\n const trackClicks = sequence.settings.trackClicks || sequence.stats?.clickTracked === true\n const open = enrollment.status === 'active' || enrollment.status === 'paused'\n const held = enrollment.status === 'paused' && enrollment.stopReason === 'gateway_blocked_here'\n\n /*\n * The one act that moves the person forward is the button: resuming a\n * paused one, else curating the next email. Everything else is in the\n * menu, the destructive acts included, as on every record page.\n */\n const available = outreachEnrollmentActionsFor(enrollment, steps)\n const primary: OutreachEnrollmentRowAction | null = available.includes('resume')\n ? 'resume'\n : available.includes('curate')\n ? 'curate'\n : null\n const menu = actions.menuItems(enrollment, (action) => action !== primary)\n const dash = (value: number) => (value ? value.toLocaleString() : '—')\n const notTracked = !trackClicks && !figures.clicks && !figures.scannerClicks ? 'Not tracked' : undefined\n const thread = enrollment.gmailThreadId ?? enrollment.gmailThreadIds.at(-1) ?? null\n const nextSend = outreachNextSendState({\n enrollment,\n sequence,\n mailbox: props.mailboxes.status === 'ready' ? mailbox : undefined,\n nowMs,\n })\n const nothingYet =\n enrollment.status === 'active' && enrollment.nextDueAtMs\n ? nextSend.kind === 'queued'\n ? `Nothing yet — step ${enrollment.stepIndex + 1} is due and queued to send.`\n : `Nothing yet — step ${enrollment.stepIndex + 1} sends ${time(enrollment.nextDueAtMs)}.`\n : 'Nothing yet.'\n\n return (\n <Stack spacing={2}>\n {/* The page heading and the trail name the person; the card says what they are in. */}\n <PageHeaderRecord title={name} />\n <CardDisplay\n header=\"Enrollment\"\n subheader={\n <>\n {enrollment.contactName ? `${enrollment.email} · ` : ''}\n {`In ${sequence.name || 'Untitled'}`}\n </>\n }\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n action: (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n {back}\n {primary ? (\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={actions.busy === enrollment.id}\n onClick={() => actions.choose(enrollment, primary)}\n >\n {held ? 'Resume and send' : OUTREACH_ENROLLMENT_ACTION_LABELS[primary]}\n </Button>\n ) : null}\n {menu.length ? <RowActionsMenu label={name} items={menu} /> : null}\n </Stack>\n ),\n }}\n >\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n <Tooltip\n describeChild\n title={recordHref ? `Open the ${kind} in the CRM` : `The ${kind}’s record can’t be linked`}\n >\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={recordHref ? 'primary' : 'default'}\n icon={<MdiIcon path={mdiAccountOutline.path} fontSize=\"small\" />}\n label={kind === 'lead' ? 'Lead' : 'Contact'}\n {...(recordHref\n ? ({ component: AppLink, href: recordHref, clickable: true, componentVariant: 'naked' } as object)\n : {})}\n />\n </Tooltip>\n <OutreachEnrollmentStatusChip status={enrollment.status} />\n <Chip size=\"small\" variant=\"outlined\" label={outreachCurrentStepLabel(enrollment, steps)} />\n {outreachStepIsCurated(enrollment) ? (\n <Chip size=\"small\" variant=\"outlined\" color=\"success\" label=\"Curated\" />\n ) : null}\n {open && enrollment.nextDueAtMs ? (\n nextSend.kind === 'queued' ? (\n <Tooltip describeChild title={outreachNextSendDetail(nextSend, timeZone)}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={\n nextSend.reason === 'mailbox_not_sending' || nextSend.reason === 'sequence_not_active'\n ? 'warning'\n : 'default'\n }\n label={`Next send ${outreachNextSendLabel(nextSend, timeZone)}`}\n />\n </Tooltip>\n ) : (\n <Chip size=\"small\" variant=\"outlined\" label={`Next send ${time(enrollment.nextDueAtMs)}`} />\n )\n ) : null}\n </Stack>\n {held ? (\n <Alert severity=\"warning\">\n {enrollment.stopDetail ||\n 'Their mail gateway refused this sender, so the next email is held. Resume to send it anyway.'}\n </Alert>\n ) : null}\n {figures.anything ? (\n <Stack direction=\"row\" spacing={3} sx={{ flexWrap: 'wrap', rowGap: 2 }} role=\"group\" aria-label=\"In numbers\">\n <OutreachFigure label=\"Emails sent\" value={dash(figures.emailsSent)} />\n <OutreachFigure label=\"Clicks\" value={dash(figures.clicks)} hint={notTracked} />\n <OutreachFigure\n label=\"Links followed\"\n value={\n figures.linksFollowed.count\n ? `${figures.linksFollowed.count}${figures.linksFollowed.atLeast ? '+' : ''}`\n : '—'\n }\n hint={\n notTracked ??\n (figures.linksFollowed.atLeast && figures.linksFollowed.count\n ? 'Earlier clicks kept the last link only'\n : undefined)\n }\n />\n <OutreachFigure label=\"Scanner clicks\" value={dash(figures.scannerClicks)} hint={notTracked ?? 'Not counted'} />\n <OutreachFigure label=\"Replies\" value={dash(figures.replies)} />\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {nothingYet}\n </Typography>\n )}\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header=\"Activity\"\n subheader=\"Newest first\"\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n contentGutterY\n HeaderProps={\n thread\n ? {\n action: (\n <Button\n size=\"small\"\n href={outreachGmailThreadUrl(thread, mailbox?.email)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Open thread in Gmail\n </Button>\n ),\n }\n : undefined\n }\n >\n <Stack spacing={1}>\n {history.status === 'loading' ? <OutreachLoading label=\"Loading their clicks…\" /> : null}\n {history.status === 'error' || history.status === 'refused' ? (\n <OutreachLoadProblem\n status={history.status}\n what=\"list of their clicks\"\n // Only the one-by-one list is missing: the totals, the sends and\n // every stop above come from the enrollment, which was read.\n message={\n history.status === 'refused'\n ? 'Their clicks can’t be listed one by one here; the numbers above still count them.'\n : 'Their clicks couldn’t be listed one by one. Reload the page to try again.'\n }\n />\n ) : null}\n <List disablePadding aria-label=\"Activity\">\n {timeline.map((entry, index) => (\n <TimelineRow\n key={entry.key}\n entry={entry}\n timeZone={timeZone}\n mailboxEmail={mailbox?.email ?? null}\n divider={index < timeline.length - 1}\n />\n ))}\n </List>\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header=\"Details\"\n help={pluginDocsHelp('sequences', { anchor: '#person-history' })}\n contentGutterX\n HeaderProps={{\n action: (\n <Button\n size=\"small\"\n aria-expanded={detailsOpen}\n aria-controls=\"outreach-enrollment-details\"\n endIcon={<MdiIcon path={(detailsOpen ? mdiChevronUp : mdiChevronDown).path} fontSize=\"small\" />}\n onClick={() => setDetailsOpen((was) => !was)}\n >\n {detailsOpen ? 'Hide' : 'Show'}\n </Button>\n ),\n }}\n >\n <Collapse in={detailsOpen} unmountOnExit>\n <Box id=\"outreach-enrollment-details\" sx={{ pb: 2 }}>\n <Divider sx={{ mb: 2 }} />\n <EnrollmentDetails\n enrollment={enrollment}\n sequence={sequence}\n mailbox={mailbox}\n gateway={gateway.status === 'ready' ? gateway.data : null}\n gatewayUnread={\n gateway.status === 'loading'\n ? 'Looking it up…'\n : gateway.status === 'refused'\n ? 'Your role cannot look it up'\n : 'Could not be looked up'\n }\n campaignName={campaignName}\n memberName={memberName}\n orgMount={orgMount}\n timeZone={timeZone}\n />\n </Box>\n </Collapse>\n </CardDisplay>\n\n {actions.dialogs}\n </Stack>\n )\n}\nOutreachEnrollmentDetail.displayName = 'OutreachEnrollmentDetail'\n\nexport default OutreachEnrollmentDetail\n"],"names":["PageHeaderRecord","pluginDocsHelp","crmOrgRecordHref","crmRecordHref","mdiAccountCancelOutline","mdiAccountOutline","mdiAccountPlusOutline","mdiAlertCircleOutline","mdiCheckCircleOutline","mdiChevronDown","mdiChevronUp","mdiClipboardCheckOutline","mdiContentCopy","mdiCursorDefaultClickOutline","mdiEmailAlertOutline","mdiEmailOffOutline","mdiEmailOutline","mdiHandBackLeftOutline","mdiPauseCircleOutline","mdiPencilOutline","mdiPlayCircleOutline","mdiReply","mdiShieldSearch","mdiStopCircleOutline","AppLink","CardDisplay","MdiIcon","EmptyStateComponent","RowActionsMenu","useSnackbar","useOrgCampaigns","useOrgMemberOptions","Alert","Box","Button","Card","Chip","Collapse","Divider","IconButton","Link","List","ListItem","ListItemIcon","ListItemText","Stack","Tooltip","Typography","useCallback","useMemo","useState","OUTREACH_MAIL_GATEWAY_LABELS","outreachNextSendState","outreachClickSummary","outreachEnrollmentFigures","outreachEnrollmentTimeline","outreachStepName","OUTREACH_ATTESTATION_KINDS","OUTREACH_ATTESTATION_LABELS","OUTREACH_ENROLLMENT_ACTION_LABELS","outreachEnrollmentActionsFor","useOutreachEnrollmentActions","outreachCurrentStepLabel","outreachStepIsCurated","outreachStopLabel","formatOutreachTime","OutreachEnrollmentStatusChip","OutreachLoading","OutreachLoadProblem","outreachNextSendDetail","outreachNextSendLabel","useOutreachNowMs","OutreachFigure","useOutreachApi","useOutreachSequence","useOutreachEnrollment","useOutreachEnrollmentGateway","useOutreachEnrollmentHistory","outreachCrmRecordHref","kind","id","hostId","orgMount","orgSlug","host","hosts","find","entry","subdomain","outreachGmailThreadUrl","threadId","mailboxEmail","account","encodeURIComponent","KIND_ICONS","enrolled","curated","sent","task","click","scanner","paused","resumed","stopped","replied","bounced","held","released","failed","finished","TONE_COLORS","default","success","info","warning","error","Destination","props","variant","component","sx","display","wordBreak","label","href","url","target","rel","underline","TimelineRow","alignItems","divider","disableGutters","data-kind","minWidth","mt","color","tone","path","fontSize","disableTypography","primary","direction","xs","sm","spacing","justifyContent","fontWeight","title","whiteSpace","atMs","timeZone","secondary","urlLabel","detail","facts","length","gmailThreadId","join","Fact","m","typography","children","gatewaySentence","answer","intel","standing","status","domain","resolvedAtMs","from","sendingDomain","parts","gateway","mx","delivered30","blocked30","filter","Boolean","EnrollmentDetails","enrollment","sequence","memberName","enqueueSnackbar","time","ms","leadHref","leadId","contactHref","contactId","clicks","engagement","overrides","Object","entries","stepOverrides","sort","a","b","Number","attested","attestations","threads","gmailThreadIds","copyId","navigator","clipboard","writeText","then","catch","link","componentVariant","gridTemplateColumns","columnGap","rowGap","personalLine","createdAtMs","enrolledByUid","cold","pl","map","li","uid","mailbox","sendAs","email","mailboxId","campaignIds","campaignName","gatewayUnread","gatewayHold","heldAtMs","releasedAtMs","releasedByUid","gatewayDeliveredSteps","machineClicks","unloggedClicks","unloggedMachineClicks","firstClickAtMs","lastClickAtMs","followed","key","override","steps","source","edited","draftedByUid","draftedAtMs","model","subject","undefined","body","borderLeft","borderColor","prompt","thread","span","threadSubject","messageIds","stopReason","stoppedAtMs","stoppedByUid","updatedAtMs","fontFamily","size","aria-label","onClick","OutreachEnrollmentDetail","orgId","sectionPath","sequenceId","enrollmentId","api","loadedSequence","loaded","history","roster","enabled","detailsOpen","setDetailsOpen","nowMs","data","campaigns","actions","options","option","value","enrollmentsPath","mailboxes","timezone","timeline","formatTime","back","nativeButton","what","description","action","name","contactName","recordHref","figures","trackClicks","settings","stats","clickTracked","open","available","includes","menu","menuItems","dash","toLocaleString","notTracked","scannerClicks","at","nextSend","nothingYet","nextDueAtMs","stepIndex","header","subheader","help","anchor","contentGutterX","contentGutterY","HeaderProps","flexWrap","disabled","busy","choose","items","describeChild","icon","clickable","reason","severity","stopDetail","anything","role","emailsSent","hint","linksFollowed","count","atLeast","replies","message","disablePadding","index","aria-expanded","aria-controls","endIcon","was","in","unmountOnExit","pb","mb","dialogs","displayName"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { type ListFilterClause, type ListFilterOption } from '@aglyn/shared-ui-jsx/const/list-grid-filter';
2
2
  import { type ReactNode } from 'react';
3
- import { type OutreachEnrollment, type OutreachSequenceStep } from '../model/outreach.types';
3
+ import { type OutreachEnrollment, type OutreachMailbox, type OutreachSequence, type OutreachSequenceStep } from '../model/outreach.types';
4
4
  import type { OutreachApi } from './use-outreach-api';
5
5
  export interface OutreachEnrollmentsTableProps {
6
6
  /** The organization, whose enrollments the table asks for. */
@@ -17,6 +17,13 @@ export interface OutreachEnrollmentsTableProps {
17
17
  trackClicks?: boolean;
18
18
  /** The mailbox's IANA zone, which next sends are read in; `null` for the reader's own. */
19
19
  timeZone: string | null;
20
+ /**
21
+ * The sequence's mailbox, whose pacing a due enrollment waits on
22
+ * (AGL-3366): `undefined` while the mailboxes load, `null` when it has none.
23
+ */
24
+ mailbox?: OutreachMailbox | null;
25
+ /** The sequence, whose status and window a due enrollment waits on too. */
26
+ sequence?: Pick<OutreachSequence, 'status' | 'steps' | 'settings'> | null;
20
27
  api: OutreachApi;
21
28
  /** Shown in the empty state when the sequence takes people. */
22
29
  enrollAction?: ReactNode;
@@ -29,8 +29,10 @@ import { useMemo } from "react";
29
29
  import { outreachClickCountLabel, outreachClickSummary } from "../model/enrollment-engagement.js";
30
30
  import { OUTREACH_ENROLLMENT_CLICK_FIELDS, OUTREACH_ENROLLMENT_LIST_QUERY } from "../model/enrollment-list-query.js";
31
31
  import { OUTREACH_ENROLLMENT_STATUSES, OUTREACH_STOP_REASONS, OUTREACH_TASK_KIND_LABELS } from "../model/outreach.types.js";
32
+ import { outreachNextSendState } from "../engine/next-send.js";
32
33
  import { useOutreachEnrollmentActions } from "./enrollment-actions.js";
33
34
  import { OUTREACH_CLICKED_FILTER_VALUE, OUTREACH_UNCLICKED_FILTER_VALUE } from "./enrollment-filter-params.js";
35
+ import { OutreachNextSend, outreachNextSendDetail, outreachNextSendLabel, useOutreachNowMs } from "./next-send.js";
34
36
  import { formatOutreachTime, OUTREACH_ENROLLMENT_STATUS_LABELS, OUTREACH_STOP_REASON_LABELS, OutreachEnrollmentStatusChip, OutreachLoading, OutreachLoadProblem } from "./outreach-ui.js";
35
37
  import { useOutreachEnrollmentList } from "./use-outreach-data.js";
36
38
  /** The step an enrollment is on, as a person reads it. */ export function outreachCurrentStepLabel(enrollment, steps) {
@@ -156,7 +158,7 @@ const CLICKED_OPTIONS = [
156
158
  children: text
157
159
  }) : text;
158
160
  }
159
- /** The table's columns; the person and the actions are drawn from the row's enrollment. */ function columns(rowActions, trackClicks) {
161
+ /** The table's columns; the person and the actions are drawn from the row's enrollment. */ function columns(rowActions, trackClicks, timeZone) {
160
162
  return [
161
163
  {
162
164
  field: 'person',
@@ -242,8 +244,18 @@ const CLICKED_OPTIONS = [
242
244
  {
243
245
  field: 'nextSend',
244
246
  headerName: 'Next send',
245
- width: 170,
246
- sortable: false
247
+ width: 190,
248
+ sortable: false,
249
+ renderCell: ({ row })=>/*#__PURE__*/ _jsx(Stack, {
250
+ sx: {
251
+ justifyContent: 'center',
252
+ height: '100%'
253
+ },
254
+ children: /*#__PURE__*/ _jsx(OutreachNextSend, {
255
+ state: row.nextSendState,
256
+ timeZone: timeZone
257
+ })
258
+ })
247
259
  },
248
260
  {
249
261
  field: 'lastActivity',
@@ -312,6 +324,7 @@ const CLICKED_OPTIONS = [
312
324
  */ export function OutreachEnrollmentsTable(props) {
313
325
  const { steps, timeZone, api, onOpen, hrefFor } = props;
314
326
  const trackClicks = props.trackClicks === true;
327
+ const nowMs = useOutreachNowMs();
315
328
  const theme = useTheme();
316
329
  const narrow = useMediaQuery(theme.breakpoints.down('md'));
317
330
  const actions = useOutreachEnrollmentActions({
@@ -438,7 +451,20 @@ const CLICKED_OPTIONS = [
438
451
  label: enrollment.contactName || enrollment.email,
439
452
  items: actions.menuItems(enrollment)
440
453
  });
441
- const nextSend = (enrollment)=>enrollment.status === 'active' || enrollment.status === 'paused' ? formatOutreachTime(enrollment.nextDueAtMs, timeZone) : '—';
454
+ /*
455
+ * A next send whose time has come says it is queued, and why, rather than
456
+ * showing a time already past (AGL-3366): the mailbox sends its share of
457
+ * the day each run, follow-ups first, so a first email can wait its turn
458
+ * for an hour or more without anything having failed.
459
+ */ const nextSendState = (enrollment)=>{
460
+ var _props_sequence;
461
+ return outreachNextSendState({
462
+ enrollment,
463
+ sequence: (_props_sequence = props.sequence) != null ? _props_sequence : null,
464
+ mailbox: props.mailbox,
465
+ nowMs
466
+ });
467
+ };
442
468
  const personName = (enrollment)=>{
443
469
  const name = enrollment.contactName || enrollment.email;
444
470
  if (!hrefFor) return /*#__PURE__*/ _jsx(Typography, {
@@ -558,10 +584,28 @@ const CLICKED_OPTIONS = [
558
584
  }) : null
559
585
  ]
560
586
  }),
561
- /*#__PURE__*/ _jsx(Typography, {
562
- variant: "body2",
563
- color: "text.secondary",
564
- children: `Next send: ${nextSend(enrollment)} · Last activity: ${formatOutreachTime(lastActivityMs(enrollment), timeZone)}`
587
+ /*#__PURE__*/ _jsxs(Stack, {
588
+ direction: "row",
589
+ spacing: 0.5,
590
+ sx: {
591
+ alignItems: 'baseline',
592
+ flexWrap: 'wrap',
593
+ color: 'text.secondary'
594
+ },
595
+ children: [
596
+ /*#__PURE__*/ _jsx(Typography, {
597
+ variant: "body2",
598
+ children: "Next send:"
599
+ }),
600
+ /*#__PURE__*/ _jsx(OutreachNextSend, {
601
+ state: nextSendState(enrollment),
602
+ timeZone: timeZone
603
+ }),
604
+ /*#__PURE__*/ _jsx(Typography, {
605
+ variant: "body2",
606
+ children: `· Last activity: ${formatOutreachTime(lastActivityMs(enrollment), timeZone)}`
607
+ })
608
+ ]
565
609
  }),
566
610
  trackClicks && clicks.clicks ? /*#__PURE__*/ _jsx(Typography, {
567
611
  variant: "body2",
@@ -580,7 +624,7 @@ const CLICKED_OPTIONS = [
580
624
  })
581
625
  }) : /*#__PURE__*/ _jsx(ListTable, {
582
626
  "aria-label": "Enrollments",
583
- columns: listFilterGridColumns(columns(rowActions, trackClicks), fields, filterOptions, ENROLLMENT_FILTER_HEADERS),
627
+ columns: listFilterGridColumns(columns(rowActions, trackClicks, timeZone), fields, filterOptions, ENROLLMENT_FILTER_HEADERS),
584
628
  initialState: {
585
629
  columns: {
586
630
  columnVisibilityModel: hiddenColumns
@@ -590,10 +634,16 @@ const CLICKED_OPTIONS = [
590
634
  rows: pageRows.map((enrollment)=>{
591
635
  var _enrollment_engagement;
592
636
  const clicks = clicksOf(enrollment);
637
+ const next = nextSendState(enrollment);
593
638
  return _extends({
594
639
  $id: enrollment.id
595
640
  }, filterRow(enrollment, steps, clicks), {
596
- nextSend: nextSend(enrollment),
641
+ nextSendState: next,
642
+ // What the export writes: the label, and for a queued send, why.
643
+ nextSend: [
644
+ outreachNextSendLabel(next, timeZone),
645
+ outreachNextSendDetail(next, timeZone)
646
+ ].filter(Boolean).join(' — '),
597
647
  lastActivity: formatOutreachTime(lastActivityMs(enrollment), timeZone),
598
648
  // What the export writes; the cells draw these their own way.
599
649
  clicks: outreachClickCountLabel(clicks),