@burdenoff/microfe-subscriberbot 2026.706.1 → 2026.706.2

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.
Files changed (23) hide show
  1. package/dist/subscriberbot/components/Modal.js +51 -0
  2. package/dist/subscriberbot/components/Modal.js.map +1 -0
  3. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +358 -163
  4. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  5. package/dist/subscriberbot/pages/InboxPage.js +339 -66
  6. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  7. package/dist/subscriberbot/pages/InvoicesPage.js +496 -73
  8. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
  9. package/dist/subscriberbot/pages/WorkflowsPage.js +136 -150
  10. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  11. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +197 -58
  12. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  13. package/dist/subscriberbot/pages/agents/AgentsListPage.js +2 -0
  14. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  15. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +538 -71
  16. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
  17. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +2 -0
  18. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
  19. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +664 -126
  20. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  21. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +18 -16
  22. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
  23. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderDetailPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/providers/ProviderDetailPage.tsx"],"sourcesContent":["/**\n * Provider detail\n * @module subscriberbot/pages/providers\n *\n * A provider profile from the registry: category, status, region, scores,\n * tags and its published plans. Reads `subProvider(id)`.\n */\n\nimport { ArrowLeft, Building2, Globe, ShieldCheck, TrendingDown, Tag } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView, Section } from '../../components/StateViews';\nimport { useParams } from 'react-router-dom';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useProvider } from '../../hooks/useSubscriberBotApi';\nimport { formatCurrency, formatEnumLabel, formatIntervalSuffix } from '../../utils/formatters';\n\nexport function ProviderDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useSubscriberBot();\n const { data: provider, isLoading, isError, refetch } = useProvider(id);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Provider\">\n <LoadingView label=\"Loading provider…\" />\n </PageLayout>\n );\n }\n\n if (isError) {\n return (\n <PageLayout title=\"Provider\">\n <ErrorView message=\"Could not load this provider.\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n if (!provider) {\n return (\n <PageLayout title=\"Provider\">\n <EmptyState\n illustration=\"empty-data\"\n title=\"Provider not found\"\n description=\"It may have been removed, or you may not have access to it.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Back to providers\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n const p = provider;\n\n return (\n <PageLayout\n title={p.name}\n description={formatEnumLabel(p.category)}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n }\n >\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"flex size-10 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n <Building2 className=\"h-5 w-5\" />\n </span>\n <StatusBadge status={p.status} />\n {p.region && <span className=\"text-sm text-text-secondary\">{p.region}</span>}\n {p.websiteUrl && (\n <a\n href={p.websiteUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-sm text-text-link hover:underline\"\n >\n <Globe className=\"h-3.5 w-3.5\" /> Website\n </a>\n )}\n </div>\n\n {p.description && (\n <p className=\"mt-4 max-w-3xl text-sm text-text-secondary\">{p.description}</p>\n )}\n\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n <ShieldCheck className=\"h-3.5 w-3.5\" /> Vendor health\n </div>\n <p className=\"mt-1.5 text-lg font-semibold tabular-nums text-text-primary\">\n {p.vendorHealthScore != null ? `${p.vendorHealthScore}/100` : '—'}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n <TrendingDown className=\"h-3.5 w-3.5\" /> Churn risk\n </div>\n <p className=\"mt-1.5 text-lg font-semibold tabular-nums text-text-primary\">\n {p.churnRiskScore != null ? `${p.churnRiskScore}/100` : '—'}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n Industry\n </div>\n <p className=\"mt-1.5 text-sm text-text-primary\">{p.industry ?? '—'}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n Language\n </div>\n <p className=\"mt-1.5 text-sm text-text-primary\">{p.language ?? '—'}</p>\n </GlassCard>\n </div>\n\n {p.tags.length > 0 && (\n <div className=\"mt-5 flex flex-wrap items-center gap-2\">\n <Tag className=\"h-3.5 w-3.5 text-text-secondary\" />\n {p.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n\n <Section title=\"Plans\" description=\"Pricing this provider publishes\">\n {!p.plans || p.plans.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No published plans\"\n description=\"When this provider publishes plans, they'll appear here.\"\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {p.plans.map((plan) => (\n <div\n key={plan.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"text-sm font-semibold text-text-primary\">{plan.name}</p>\n <StatusBadge status={plan.isActive ? 'ACTIVE' : 'DISABLED'} />\n </div>\n <p className=\"mt-2 text-lg font-bold tabular-nums text-text-primary\">\n {formatCurrency(plan.amount, plan.currency)}\n <span className=\"text-xs font-normal text-text-secondary\">\n {formatIntervalSuffix(plan.interval)}\n </span>\n </p>\n {plan.description && (\n <p className=\"mt-1 text-xs text-text-secondary\">{plan.description}</p>\n )}\n {plan.features.length > 0 && (\n <ul className=\"mt-3 space-y-1\">\n {plan.features.slice(0, 5).map((f) => (\n <li key={f} className=\"text-xs text-text-secondary\">\n • {f}\n </li>\n ))}\n </ul>\n )}\n </div>\n ))}\n </div>\n )}\n </Section>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProviderDetailPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/providers/ProviderDetailPage.tsx"],"sourcesContent":["/**\n * Provider detail\n * @module subscriberbot/pages/providers\n *\n * A provider profile from the registry: category, status, region, scores,\n * tags and its published plans. Reads `subProvider(id)`; writes\n * `subUpdateProvider`, `subArchiveProvider`, `subCreatePlan`.\n */\n\nimport { useState } from 'react';\nimport {\n ArrowLeft,\n Building2,\n Globe,\n ShieldCheck,\n TrendingDown,\n Tag,\n Pencil,\n Plus,\n Archive,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Modal } from '../../components/Modal';\nimport { LoadingView, ErrorView, Section } from '../../components/StateViews';\nimport { useParams } from 'react-router-dom';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport {\n useProvider,\n useUpdateProvider,\n useArchiveProvider,\n useCreatePlan,\n} from '../../hooks/useSubscriberBotApi';\nimport { formatCurrency, formatEnumLabel, formatIntervalSuffix } from '../../utils/formatters';\nimport type {\n SubBillingInterval,\n SubProvider,\n SubProviderCategory,\n SubProviderStatus,\n SubUpdateProviderInput,\n} from '../../types';\n\nconst inputCls =\n 'w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\nconst labelCls = 'mb-1 block text-xs font-medium text-text-secondary';\n\nconst CATEGORIES: SubProviderCategory[] = [\n 'SAAS',\n 'AI_SERVICE',\n 'STREAMING',\n 'NEWSLETTER',\n 'NEWS_DIGEST',\n 'MEMBERSHIP',\n 'COMMUNITY',\n 'EDUCATION',\n 'FINANCIAL',\n 'INSURANCE',\n 'TELECOM',\n 'UTILITY',\n 'ASSOCIATION',\n 'LICENSE',\n 'CONTRACT',\n 'OTHER',\n];\n\nconst STATUSES: SubProviderStatus[] = ['UNVERIFIED', 'VERIFIED', 'CLAIMED', 'DEPRECATED'];\n\nconst INTERVALS: SubBillingInterval[] = [\n 'MONTHLY',\n 'YEARLY',\n 'QUARTERLY',\n 'WEEKLY',\n 'DAILY',\n 'USAGE_BASED',\n 'LIFETIME',\n 'FREE',\n];\n\n// ---------------------------------------------------------------------------\n// Edit provider modal → subUpdateProvider\n// ---------------------------------------------------------------------------\n\nfunction ProviderEditModal({ provider, onClose }: { provider: SubProvider; onClose: () => void }) {\n const update = useUpdateProvider();\n const [name, setName] = useState(provider.name);\n const [category, setCategory] = useState<SubProviderCategory>(provider.category);\n const [status, setStatus] = useState<SubProviderStatus>(provider.status);\n const [description, setDescription] = useState(provider.description ?? '');\n const [industry, setIndustry] = useState(provider.industry ?? '');\n const [region, setRegion] = useState(provider.region ?? '');\n const [language, setLanguage] = useState(provider.language ?? '');\n const [websiteUrl, setWebsiteUrl] = useState(provider.websiteUrl ?? '');\n const [churnRiskScore, setChurnRiskScore] = useState(\n provider.churnRiskScore != null ? String(provider.churnRiskScore) : ''\n );\n const [vendorHealthScore, setVendorHealthScore] = useState(\n provider.vendorHealthScore != null ? String(provider.vendorHealthScore) : ''\n );\n const [tags, setTags] = useState(provider.tags.join(', '));\n const [formError, setFormError] = useState<string | null>(null);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n if (!name.trim()) {\n setFormError('A provider name is required.');\n return;\n }\n const parsedTags = tags\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n const input: SubUpdateProviderInput = {\n name: name.trim(),\n category,\n status,\n description: description.trim(),\n tags: parsedTags,\n ...(industry.trim() ? { industry: industry.trim() } : {}),\n ...(region.trim() ? { region: region.trim() } : {}),\n ...(language.trim() ? { language: language.trim() } : {}),\n ...(websiteUrl.trim() ? { websiteUrl: websiteUrl.trim() } : {}),\n ...(churnRiskScore.trim() ? { churnRiskScore: Number(churnRiskScore) } : {}),\n ...(vendorHealthScore.trim() ? { vendorHealthScore: Number(vendorHealthScore) } : {}),\n };\n update.mutate(\n { id: provider.id, input },\n {\n onSuccess: () => onClose(),\n onError: (err) =>\n setFormError(err instanceof Error ? err.message : 'Could not update provider.'),\n }\n );\n };\n\n return (\n <Modal title=\"Edit provider\" onClose={onClose} maxWidthClassName=\"max-w-2xl\">\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {formError && (\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text\">\n {formError}\n </div>\n )}\n <div>\n <label htmlFor=\"prov-edit-name\" className={labelCls}>\n Name <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"prov-edit-name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className={inputCls}\n required\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"prov-edit-category\" className={labelCls}>\n Category\n </label>\n <select\n id=\"prov-edit-category\"\n value={category}\n onChange={(e) => setCategory(e.target.value as SubProviderCategory)}\n className={inputCls}\n >\n {CATEGORIES.map((c) => (\n <option key={c} value={c}>\n {c.replace(/_/g, ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"prov-edit-status\" className={labelCls}>\n Status\n </label>\n <select\n id=\"prov-edit-status\"\n value={status}\n onChange={(e) => setStatus(e.target.value as SubProviderStatus)}\n className={inputCls}\n >\n {STATUSES.map((s) => (\n <option key={s} value={s}>\n {s.replace(/_/g, ' ')}\n </option>\n ))}\n </select>\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div>\n <label htmlFor=\"prov-edit-industry\" className={labelCls}>\n Industry\n </label>\n <input\n id=\"prov-edit-industry\"\n type=\"text\"\n value={industry}\n onChange={(e) => setIndustry(e.target.value)}\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"prov-edit-region\" className={labelCls}>\n Region\n </label>\n <input\n id=\"prov-edit-region\"\n type=\"text\"\n value={region}\n onChange={(e) => setRegion(e.target.value)}\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"prov-edit-language\" className={labelCls}>\n Language\n </label>\n <input\n id=\"prov-edit-language\"\n type=\"text\"\n value={language}\n onChange={(e) => setLanguage(e.target.value)}\n className={inputCls}\n />\n </div>\n </div>\n <div>\n <label htmlFor=\"prov-edit-website\" className={labelCls}>\n Website\n </label>\n <input\n id=\"prov-edit-website\"\n type=\"url\"\n value={websiteUrl}\n onChange={(e) => setWebsiteUrl(e.target.value)}\n placeholder=\"https://…\"\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"prov-edit-desc\" className={labelCls}>\n Description\n </label>\n <textarea\n id=\"prov-edit-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={3}\n className={inputCls}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"prov-edit-churn\" className={labelCls}>\n Churn risk (0–100)\n </label>\n <input\n id=\"prov-edit-churn\"\n type=\"number\"\n min=\"0\"\n max=\"100\"\n value={churnRiskScore}\n onChange={(e) => setChurnRiskScore(e.target.value)}\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"prov-edit-health\" className={labelCls}>\n Vendor health (0–100)\n </label>\n <input\n id=\"prov-edit-health\"\n type=\"number\"\n min=\"0\"\n max=\"100\"\n value={vendorHealthScore}\n onChange={(e) => setVendorHealthScore(e.target.value)}\n className={inputCls}\n />\n </div>\n </div>\n <div>\n <label htmlFor=\"prov-edit-tags\" className={labelCls}>\n Tags <span className=\"text-text-secondary\">(comma-separated)</span>\n </label>\n <input\n id=\"prov-edit-tags\"\n type=\"text\"\n value={tags}\n onChange={(e) => setTags(e.target.value)}\n className={inputCls}\n />\n </div>\n <div className=\"flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={update.isPending}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n {update.isPending ? 'Saving…' : 'Save changes'}\n </button>\n </div>\n </form>\n </Modal>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Add plan modal → subCreatePlan\n// ---------------------------------------------------------------------------\n\nfunction AddPlanModal({ providerId, onClose }: { providerId: string; onClose: () => void }) {\n const create = useCreatePlan();\n const [name, setName] = useState('');\n const [amount, setAmount] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [interval, setInterval] = useState<SubBillingInterval>('MONTHLY');\n const [description, setDescription] = useState('');\n const [features, setFeatures] = useState('');\n const [isActive, setIsActive] = useState(true);\n const [formError, setFormError] = useState<string | null>(null);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n if (!name.trim()) {\n setFormError('A plan name is required.');\n return;\n }\n const parsedFeatures = features\n .split('\\n')\n .map((f) => f.trim())\n .filter(Boolean);\n create.mutate(\n {\n providerId,\n name: name.trim(),\n interval,\n currency: currency.trim() || 'USD',\n ...(amount.trim() ? { amount: Number(amount) } : {}),\n ...(description.trim() ? { description: description.trim() } : {}),\n ...(parsedFeatures.length ? { features: parsedFeatures } : {}),\n },\n {\n onSuccess: () => onClose(),\n onError: (err) => setFormError(err instanceof Error ? err.message : 'Could not add plan.'),\n }\n );\n };\n\n return (\n <Modal title=\"Add plan\" onClose={onClose} maxWidthClassName=\"max-w-xl\">\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {formError && (\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text\">\n {formError}\n </div>\n )}\n <div>\n <label htmlFor=\"plan-name\" className={labelCls}>\n Name <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"plan-name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. Pro, Team, Enterprise\"\n className={inputCls}\n required\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div>\n <label htmlFor=\"plan-amount\" className={labelCls}>\n Amount\n </label>\n <input\n id=\"plan-amount\"\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n placeholder=\"0.00\"\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"plan-currency\" className={labelCls}>\n Currency\n </label>\n <input\n id=\"plan-currency\"\n type=\"text\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value.toUpperCase())}\n maxLength={3}\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"plan-interval\" className={labelCls}>\n Interval\n </label>\n <select\n id=\"plan-interval\"\n value={interval}\n onChange={(e) => setInterval(e.target.value as SubBillingInterval)}\n className={inputCls}\n >\n {INTERVALS.map((i) => (\n <option key={i} value={i}>\n {i.replace(/_/g, ' ')}\n </option>\n ))}\n </select>\n </div>\n </div>\n <div>\n <label htmlFor=\"plan-desc\" className={labelCls}>\n Description\n </label>\n <textarea\n id=\"plan-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"plan-features\" className={labelCls}>\n Features <span className=\"text-text-secondary\">(one per line)</span>\n </label>\n <textarea\n id=\"plan-features\"\n value={features}\n onChange={(e) => setFeatures(e.target.value)}\n rows={3}\n placeholder={'Unlimited projects\\nPriority support\\nSSO'}\n className={inputCls}\n />\n </div>\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={isActive}\n onChange={(e) => setIsActive(e.target.checked)}\n className=\"size-4 rounded border-border-subtle\"\n />\n Active\n </label>\n <div className=\"flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={create.isPending}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n {create.isPending ? 'Adding…' : 'Add plan'}\n </button>\n </div>\n </form>\n </Modal>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Archive confirmation modal → subArchiveProvider\n// ---------------------------------------------------------------------------\n\nfunction ArchiveProviderModal({\n provider,\n onClose,\n}: {\n provider: SubProvider;\n onClose: () => void;\n}) {\n const { navigateTo } = useSubscriberBot();\n const archive = useArchiveProvider();\n const [error, setError] = useState<string | null>(null);\n\n const handleArchive = () => {\n setError(null);\n archive.mutate(provider.id, {\n onSuccess: () => navigateTo('/providers'),\n onError: (err) =>\n setError(err instanceof Error ? err.message : 'Could not archive this provider.'),\n });\n };\n\n return (\n <Modal title=\"Archive provider\" onClose={onClose}>\n <div className=\"space-y-4\">\n {error && (\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text\">\n {error}\n </div>\n )}\n <p className=\"text-sm text-text-secondary\">\n Archive <span className=\"font-medium text-text-primary\">{provider.name}</span>? It will be\n removed from the active registry. This can be reversed by an administrator.\n </p>\n <div className=\"flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleArchive}\n disabled={archive.isPending}\n className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm font-medium text-status-error-text hover:opacity-90 disabled:opacity-50\"\n >\n {archive.isPending ? 'Archiving…' : 'Archive provider'}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n\nexport function ProviderDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useSubscriberBot();\n const { data: provider, isLoading, isError, refetch } = useProvider(id);\n const [showEdit, setShowEdit] = useState(false);\n const [showAddPlan, setShowAddPlan] = useState(false);\n const [showArchive, setShowArchive] = useState(false);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Provider\">\n <LoadingView label=\"Loading provider…\" />\n </PageLayout>\n );\n }\n\n if (isError) {\n return (\n <PageLayout title=\"Provider\">\n <ErrorView message=\"Could not load this provider.\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n if (!provider) {\n return (\n <PageLayout title=\"Provider\">\n <EmptyState\n illustration=\"empty-data\"\n title=\"Provider not found\"\n description=\"It may have been removed, or you may not have access to it.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Back to providers\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n const p = provider;\n // Only render the website as a link when it is a safe http(s) URL — websiteUrl\n // is user-controlled, so guard against javascript:/data: schemes and add\n // rel=\"noopener noreferrer\" to the target=\"_blank\" anchor.\n const safeWebsiteUrl = p.websiteUrl && /^https?:\\/\\//i.test(p.websiteUrl) ? p.websiteUrl : null;\n\n return (\n <PageLayout\n title={p.name}\n description={formatEnumLabel(p.category)}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => setShowEdit(true)}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <Pencil className=\"h-4 w-4\" /> Edit\n </button>\n <button\n type=\"button\"\n onClick={() => setShowArchive(true)}\n className=\"inline-flex items-center gap-2 rounded-lg border border-status-error-text/30 px-3 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle\"\n >\n <Archive className=\"h-4 w-4\" /> Archive\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n </div>\n }\n >\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"flex size-10 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n <Building2 className=\"h-5 w-5\" />\n </span>\n <StatusBadge status={p.status} />\n {p.region && <span className=\"text-sm text-text-secondary\">{p.region}</span>}\n {safeWebsiteUrl && (\n <a\n href={safeWebsiteUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1 text-sm text-text-link hover:underline\"\n >\n <Globe className=\"h-3.5 w-3.5\" /> Website\n </a>\n )}\n </div>\n\n {p.description && (\n <p className=\"mt-4 max-w-3xl text-sm text-text-secondary\">{p.description}</p>\n )}\n\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n <ShieldCheck className=\"h-3.5 w-3.5\" /> Vendor health\n </div>\n <p className=\"mt-1.5 text-lg font-semibold tabular-nums text-text-primary\">\n {p.vendorHealthScore != null ? `${p.vendorHealthScore}/100` : '—'}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n <TrendingDown className=\"h-3.5 w-3.5\" /> Churn risk\n </div>\n <p className=\"mt-1.5 text-lg font-semibold tabular-nums text-text-primary\">\n {p.churnRiskScore != null ? `${p.churnRiskScore}/100` : '—'}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n Industry\n </div>\n <p className=\"mt-1.5 text-sm text-text-primary\">{p.industry ?? '—'}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n Language\n </div>\n <p className=\"mt-1.5 text-sm text-text-primary\">{p.language ?? '—'}</p>\n </GlassCard>\n </div>\n\n {p.tags.length > 0 && (\n <div className=\"mt-5 flex flex-wrap items-center gap-2\">\n <Tag className=\"h-3.5 w-3.5 text-text-secondary\" />\n {p.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n\n <Section\n title=\"Plans\"\n description=\"Pricing this provider publishes\"\n action={\n <button\n type=\"button\"\n onClick={() => setShowAddPlan(true)}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <Plus className=\"h-3.5 w-3.5\" /> Add plan\n </button>\n }\n >\n {!p.plans || p.plans.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No published plans\"\n description=\"When this provider publishes plans, they'll appear here.\"\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {p.plans.map((plan) => (\n <div\n key={plan.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"text-sm font-semibold text-text-primary\">{plan.name}</p>\n <StatusBadge status={plan.isActive ? 'ACTIVE' : 'DISABLED'} />\n </div>\n <p className=\"mt-2 text-lg font-bold tabular-nums text-text-primary\">\n {formatCurrency(plan.amount, plan.currency)}\n <span className=\"text-xs font-normal text-text-secondary\">\n {formatIntervalSuffix(plan.interval)}\n </span>\n </p>\n {plan.description && (\n <p className=\"mt-1 text-xs text-text-secondary\">{plan.description}</p>\n )}\n {plan.features.length > 0 && (\n <ul className=\"mt-3 space-y-1\">\n {plan.features.slice(0, 5).map((f) => (\n <li key={f} className=\"text-xs text-text-secondary\">\n • {f}\n </li>\n ))}\n </ul>\n )}\n </div>\n ))}\n </div>\n )}\n </Section>\n\n {showEdit && <ProviderEditModal provider={p} onClose={() => setShowEdit(false)} />}\n {showAddPlan && <AddPlanModal providerId={p.id} onClose={() => setShowAddPlan(false)} />}\n {showArchive && <ArchiveProviderModal provider={p} onClose={() => setShowArchive(false)} />}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -142,6 +142,7 @@ function S() {
142
142
  /* @__PURE__ */ g("div", {
143
143
  className: "mt-4 flex flex-wrap items-center gap-3",
144
144
  children: [/* @__PURE__ */ h("select", {
145
+ "aria-label": "Filter by category",
145
146
  value: k,
146
147
  onChange: (e) => {
147
148
  A(e.target.value), w(0);
@@ -152,6 +153,7 @@ function S() {
152
153
  children: e.label
153
154
  }, e.value))
154
155
  }), /* @__PURE__ */ h("select", {
156
+ "aria-label": "Filter by status",
155
157
  value: j,
156
158
  onChange: (e) => {
157
159
  M(e.target.value), w(0);
@@ -1 +1 @@
1
- {"version":3,"file":"ProvidersListPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/providers/ProvidersListPage.tsx"],"sourcesContent":["/**\n * Providers list (Global Provider Registry)\n * @module subscriberbot/pages/providers\n *\n * Discovery: search and browse the provider registry. Server-side search +\n * category/status filters + pagination via `subListProviders`\n * (a SubProviderConnection).\n */\n\nimport { useState } from 'react';\nimport { Plus, Search, Building2, ShieldCheck } from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useProviders } from '../../hooks/useSubscriberBotApi';\nimport { cn } from '../../utils/cn';\nimport { formatEnumLabel } from '../../utils/formatters';\nimport type { SubProviderCategory, SubProviderStatus } from '../../types';\n\nconst PAGE_SIZE = 24;\n\nconst CATEGORY_OPTIONS: Array<{ value: '' | SubProviderCategory; label: string }> = [\n { value: '', label: 'All categories' },\n { value: 'SAAS', label: 'SaaS' },\n { value: 'AI_SERVICE', label: 'AI service' },\n { value: 'STREAMING', label: 'Streaming' },\n { value: 'NEWSLETTER', label: 'Newsletter' },\n { value: 'NEWS_DIGEST', label: 'News digest' },\n { value: 'MEMBERSHIP', label: 'Membership' },\n { value: 'COMMUNITY', label: 'Community' },\n { value: 'EDUCATION', label: 'Education' },\n { value: 'FINANCIAL', label: 'Financial' },\n { value: 'INSURANCE', label: 'Insurance' },\n { value: 'TELECOM', label: 'Telecom' },\n { value: 'UTILITY', label: 'Utility' },\n { value: 'ASSOCIATION', label: 'Association' },\n { value: 'LICENSE', label: 'License' },\n { value: 'CONTRACT', label: 'Contract' },\n { value: 'OTHER', label: 'Other' },\n];\n\nconst STATUS_OPTIONS: Array<{ value: '' | SubProviderStatus; label: string }> = [\n { value: '', label: 'Any status' },\n { value: 'VERIFIED', label: 'Verified' },\n { value: 'CLAIMED', label: 'Claimed' },\n { value: 'UNVERIFIED', label: 'Unverified' },\n { value: 'DEPRECATED', label: 'Deprecated' },\n];\n\nexport function ProvidersListPage() {\n const { navigateTo } = useSubscriberBot();\n const [page, setPage] = useState(0);\n const [search, setSearch] = useState('');\n const [searchInput, setSearchInput] = useState('');\n const [category, setCategory] = useState<'' | SubProviderCategory>('');\n const [status, setStatus] = useState<'' | SubProviderStatus>('');\n\n const { data, isLoading, isError, refetch, isFetching } = useProviders({\n search: search || undefined,\n category: category || undefined,\n status: status || undefined,\n pagination: { limit: PAGE_SIZE, offset: page * PAGE_SIZE },\n });\n\n const items = data?.items ?? [];\n const hasMore = data?.pageInfo.hasMore ?? false;\n\n const submitSearch = (e: React.FormEvent) => {\n e.preventDefault();\n setSearch(searchInput.trim());\n setPage(0);\n };\n\n return (\n <PageLayout\n title=\"Providers\"\n description=\"Discover and browse the global provider registry\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers/new')}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n <Plus className=\"h-4 w-4\" /> Add provider\n </button>\n }\n >\n <PagePurpose className=\"mb-4\">\n The registry is the public face of the Subscription Knowledge Graph — every provider exists\n here whether or not it integrates. Search and filter to find the ones you have relationships\n with, or add a new one.\n </PagePurpose>\n\n <EmphasisPanel>\n <form onSubmit={submitSearch} className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search providers by name…\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </form>\n </EmphasisPanel>\n\n <div className=\"mt-4 flex flex-wrap items-center gap-3\">\n <select\n value={category}\n onChange={(e) => {\n setCategory(e.target.value as '' | SubProviderCategory);\n setPage(0);\n }}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n {CATEGORY_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n <select\n value={status}\n onChange={(e) => {\n setStatus(e.target.value as '' | SubProviderStatus);\n setPage(0);\n }}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n {STATUS_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading providers…\" />\n ) : isError ? (\n <ErrorView message=\"Could not load the provider registry.\" onRetry={() => void refetch()} />\n ) : items.length === 0 ? (\n <div className=\"mt-6\">\n <EmptyState\n illustration=\"empty-search\"\n icon={<Building2 className=\"h-12 w-12\" />}\n title=\"No providers found\"\n description={\n search\n ? `No providers match \"${search}\".`\n : 'No providers in the registry with these filters yet.'\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Add provider\n </button>\n }\n />\n </div>\n ) : (\n <>\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {items.map((p) => (\n <button\n key={p.id}\n type=\"button\"\n onClick={() => navigateTo(`/providers/${p.id}`)}\n className=\"flex flex-col rounded-lg border border-border-subtle bg-bg-surface p-4 text-left transition-shadow hover:shadow-md\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"flex size-9 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n <Building2 className=\"h-4 w-4\" />\n </span>\n <StatusBadge status={p.status} />\n </div>\n <p className=\"mt-3 truncate text-sm font-semibold text-text-primary\">{p.name}</p>\n <p className=\"text-xs text-text-secondary\">{formatEnumLabel(p.category)}</p>\n {p.description && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{p.description}</p>\n )}\n <div className=\"mt-3 flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n {p.region && <span>{p.region}</span>}\n {p.vendorHealthScore != null && (\n <span className=\"inline-flex items-center gap-1\">\n <ShieldCheck className=\"h-3 w-3\" />\n {p.vendorHealthScore}/100\n </span>\n )}\n </div>\n </button>\n ))}\n </div>\n\n <div className=\"mt-4 flex items-center justify-between\">\n <p className=\"text-xs text-text-secondary\">\n Page {page + 1}\n {isFetching ? ' · refreshing…' : ''}\n </p>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n disabled={page === 0}\n onClick={() => setPage((p) => Math.max(0, p - 1))}\n className={cn(\n 'rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium',\n page === 0\n ? 'cursor-not-allowed text-text-secondary opacity-50'\n : 'text-text-primary hover:bg-bg-sunken'\n )}\n >\n Previous\n </button>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setPage((p) => p + 1)}\n className={cn(\n 'rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium',\n !hasMore\n ? 'cursor-not-allowed text-text-secondary opacity-50'\n : 'text-text-primary hover:bg-bg-sunken'\n )}\n >\n Next\n </button>\n </div>\n </div>\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProvidersListPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/providers/ProvidersListPage.tsx"],"sourcesContent":["/**\n * Providers list (Global Provider Registry)\n * @module subscriberbot/pages/providers\n *\n * Discovery: search and browse the provider registry. Server-side search +\n * category/status filters + pagination via `subListProviders`\n * (a SubProviderConnection).\n */\n\nimport { useState } from 'react';\nimport { Plus, Search, Building2, ShieldCheck } from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useProviders } from '../../hooks/useSubscriberBotApi';\nimport { cn } from '../../utils/cn';\nimport { formatEnumLabel } from '../../utils/formatters';\nimport type { SubProviderCategory, SubProviderStatus } from '../../types';\n\nconst PAGE_SIZE = 24;\n\nconst CATEGORY_OPTIONS: Array<{ value: '' | SubProviderCategory; label: string }> = [\n { value: '', label: 'All categories' },\n { value: 'SAAS', label: 'SaaS' },\n { value: 'AI_SERVICE', label: 'AI service' },\n { value: 'STREAMING', label: 'Streaming' },\n { value: 'NEWSLETTER', label: 'Newsletter' },\n { value: 'NEWS_DIGEST', label: 'News digest' },\n { value: 'MEMBERSHIP', label: 'Membership' },\n { value: 'COMMUNITY', label: 'Community' },\n { value: 'EDUCATION', label: 'Education' },\n { value: 'FINANCIAL', label: 'Financial' },\n { value: 'INSURANCE', label: 'Insurance' },\n { value: 'TELECOM', label: 'Telecom' },\n { value: 'UTILITY', label: 'Utility' },\n { value: 'ASSOCIATION', label: 'Association' },\n { value: 'LICENSE', label: 'License' },\n { value: 'CONTRACT', label: 'Contract' },\n { value: 'OTHER', label: 'Other' },\n];\n\nconst STATUS_OPTIONS: Array<{ value: '' | SubProviderStatus; label: string }> = [\n { value: '', label: 'Any status' },\n { value: 'VERIFIED', label: 'Verified' },\n { value: 'CLAIMED', label: 'Claimed' },\n { value: 'UNVERIFIED', label: 'Unverified' },\n { value: 'DEPRECATED', label: 'Deprecated' },\n];\n\nexport function ProvidersListPage() {\n const { navigateTo } = useSubscriberBot();\n const [page, setPage] = useState(0);\n const [search, setSearch] = useState('');\n const [searchInput, setSearchInput] = useState('');\n const [category, setCategory] = useState<'' | SubProviderCategory>('');\n const [status, setStatus] = useState<'' | SubProviderStatus>('');\n\n const { data, isLoading, isError, refetch, isFetching } = useProviders({\n search: search || undefined,\n category: category || undefined,\n status: status || undefined,\n pagination: { limit: PAGE_SIZE, offset: page * PAGE_SIZE },\n });\n\n const items = data?.items ?? [];\n const hasMore = data?.pageInfo.hasMore ?? false;\n\n const submitSearch = (e: React.FormEvent) => {\n e.preventDefault();\n setSearch(searchInput.trim());\n setPage(0);\n };\n\n return (\n <PageLayout\n title=\"Providers\"\n description=\"Discover and browse the global provider registry\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers/new')}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n <Plus className=\"h-4 w-4\" /> Add provider\n </button>\n }\n >\n <PagePurpose className=\"mb-4\">\n The registry is the public face of the Subscription Knowledge Graph — every provider exists\n here whether or not it integrates. Search and filter to find the ones you have relationships\n with, or add a new one.\n </PagePurpose>\n\n <EmphasisPanel>\n <form onSubmit={submitSearch} className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search providers by name…\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </form>\n </EmphasisPanel>\n\n <div className=\"mt-4 flex flex-wrap items-center gap-3\">\n <select\n aria-label=\"Filter by category\"\n value={category}\n onChange={(e) => {\n setCategory(e.target.value as '' | SubProviderCategory);\n setPage(0);\n }}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n {CATEGORY_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n <select\n aria-label=\"Filter by status\"\n value={status}\n onChange={(e) => {\n setStatus(e.target.value as '' | SubProviderStatus);\n setPage(0);\n }}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n {STATUS_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading providers…\" />\n ) : isError ? (\n <ErrorView message=\"Could not load the provider registry.\" onRetry={() => void refetch()} />\n ) : items.length === 0 ? (\n <div className=\"mt-6\">\n <EmptyState\n illustration=\"empty-search\"\n icon={<Building2 className=\"h-12 w-12\" />}\n title=\"No providers found\"\n description={\n search\n ? `No providers match \"${search}\".`\n : 'No providers in the registry with these filters yet.'\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Add provider\n </button>\n }\n />\n </div>\n ) : (\n <>\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {items.map((p) => (\n <button\n key={p.id}\n type=\"button\"\n onClick={() => navigateTo(`/providers/${p.id}`)}\n className=\"flex flex-col rounded-lg border border-border-subtle bg-bg-surface p-4 text-left transition-shadow hover:shadow-md\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"flex size-9 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n <Building2 className=\"h-4 w-4\" />\n </span>\n <StatusBadge status={p.status} />\n </div>\n <p className=\"mt-3 truncate text-sm font-semibold text-text-primary\">{p.name}</p>\n <p className=\"text-xs text-text-secondary\">{formatEnumLabel(p.category)}</p>\n {p.description && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{p.description}</p>\n )}\n <div className=\"mt-3 flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n {p.region && <span>{p.region}</span>}\n {p.vendorHealthScore != null && (\n <span className=\"inline-flex items-center gap-1\">\n <ShieldCheck className=\"h-3 w-3\" />\n {p.vendorHealthScore}/100\n </span>\n )}\n </div>\n </button>\n ))}\n </div>\n\n <div className=\"mt-4 flex items-center justify-between\">\n <p className=\"text-xs text-text-secondary\">\n Page {page + 1}\n {isFetching ? ' · refreshing…' : ''}\n </p>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n disabled={page === 0}\n onClick={() => setPage((p) => Math.max(0, p - 1))}\n className={cn(\n 'rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium',\n page === 0\n ? 'cursor-not-allowed text-text-secondary opacity-50'\n : 'text-text-primary hover:bg-bg-sunken'\n )}\n >\n Previous\n </button>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setPage((p) => p + 1)}\n className={cn(\n 'rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium',\n !hasMore\n ? 'cursor-not-allowed text-text-secondary opacity-50'\n : 'text-text-primary hover:bg-bg-sunken'\n )}\n >\n Next\n </button>\n </div>\n </div>\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}