@burdenoff/microfe-subscriberbot 2026.706.1 → 2026.706.3

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 (38) hide show
  1. package/dist/subscriberbot/SubscriberBotRoutes.js +14 -6
  2. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  3. package/dist/subscriberbot/components/Modal.js +51 -0
  4. package/dist/subscriberbot/components/Modal.js.map +1 -0
  5. package/dist/subscriberbot/components/index.js +7 -0
  6. package/dist/subscriberbot/components/viz.js +196 -0
  7. package/dist/subscriberbot/components/viz.js.map +1 -0
  8. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +364 -161
  9. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  10. package/dist/subscriberbot/pages/AssetVaultPage.js +182 -0
  11. package/dist/subscriberbot/pages/AssetVaultPage.js.map +1 -0
  12. package/dist/subscriberbot/pages/DashboardPage.js +272 -199
  13. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
  14. package/dist/subscriberbot/pages/InboxPage.js +682 -126
  15. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  16. package/dist/subscriberbot/pages/InsightsPage.js +220 -0
  17. package/dist/subscriberbot/pages/InsightsPage.js.map +1 -0
  18. package/dist/subscriberbot/pages/InvoicesPage.js +592 -81
  19. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
  20. package/dist/subscriberbot/pages/WorkflowsPage.js +344 -169
  21. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  22. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +401 -116
  23. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  24. package/dist/subscriberbot/pages/agents/AgentsListPage.js +185 -93
  25. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  26. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +735 -135
  27. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
  28. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +217 -153
  29. package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -1
  30. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +216 -111
  31. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
  32. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +902 -250
  33. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  34. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +242 -192
  35. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -1
  36. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +174 -131
  37. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
  38. 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 Check,\n Sparkles,\n Layers,\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 { Gauge, MiniProgress } from '../../components';\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 { cn } from '../../utils/cn';\nimport type {\n SubBillingInterval,\n SubPlan,\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/** Vendor-health 0–100 → label + semantic chip classes. Higher is healthier. */\nfunction healthMeta(score: number): { label: string; cls: string } {\n if (score >= 70)\n return { label: 'Healthy', cls: 'bg-status-success-bg-subtle text-status-success-text' };\n if (score >= 45)\n return { label: 'Fair', cls: 'bg-status-warning-bg-subtle text-status-warning-text' };\n return { label: 'At risk', cls: 'bg-status-error-bg-subtle text-status-error-text' };\n}\n\n/** Churn-risk 0–100 → label + tone. Higher is worse. */\nfunction churnMeta(score: number): {\n label: string;\n chip: string;\n tone: 'positive' | 'warning' | 'negative';\n} {\n if (score >= 67)\n return {\n label: 'High',\n chip: 'bg-status-error-bg-subtle text-status-error-text',\n tone: 'negative',\n };\n if (score >= 34)\n return {\n label: 'Moderate',\n chip: 'bg-status-warning-bg-subtle text-status-warning-text',\n tone: 'warning',\n };\n return {\n label: 'Low',\n chip: 'bg-status-success-bg-subtle text-status-success-text',\n tone: 'positive',\n };\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 // Highlight the cheapest active priced plan as \"Best value\" (derived from real\n // plan data — guard for the no-plans / all-free case).\n const bestValuePlanId =\n p.plans && p.plans.length > 1\n ? p.plans\n .filter((pl) => pl.isActive && pl.amount > 0)\n .reduce<SubPlan | null>(\n (min, pl) => (min === null || pl.amount < min.amount ? pl : min),\n null\n )?.id ?? null\n : 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 {/* Identity row */}\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"flex size-11 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-text-primary\">\n <Building2 className=\"h-5 w-5\" />\n </span>\n <StatusBadge status={p.status} />\n {p.industry && <span className=\"text-sm text-text-secondary\">{p.industry}</span>}\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 leading-relaxed text-text-secondary\">\n {p.description}\n </p>\n )}\n\n {p.tags.length > 0 && (\n <div className=\"mt-4 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 <div className=\"mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Plans — tier cards */}\n <div className=\"lg:col-span-2\">\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 action={\n <button\n type=\"button\"\n onClick={() => setShowAddPlan(true)}\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 plan\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n {p.plans.map((plan) => {\n const isBestValue = plan.id === bestValuePlanId && p.plans!.length > 1;\n return (\n <GlassCard\n key={plan.id}\n treatment={isBestValue ? 'insight' : 'metric'}\n glow={isBestValue}\n className=\"flex flex-col p-5\"\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 {isBestValue ? (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[11px] font-medium text-status-success-text\">\n <Sparkles className=\"h-3 w-3\" /> Best value\n </span>\n ) : (\n <StatusBadge status={plan.isActive ? 'ACTIVE' : 'DISABLED'} />\n )}\n </div>\n <p className=\"mt-3 text-2xl font-bold tabular-nums text-text-primary\">\n {formatCurrency(plan.amount, plan.currency)}\n <span className=\"text-sm font-normal text-text-secondary\">\n {formatIntervalSuffix(plan.interval)}\n </span>\n </p>\n {plan.description && (\n <p className=\"mt-2 text-xs leading-relaxed text-text-secondary\">\n {plan.description}\n </p>\n )}\n {plan.features.length > 0 && (\n <ul className=\"mt-4 space-y-2 border-t border-border-subtle pt-4\">\n {plan.features.slice(0, 6).map((f) => (\n <li\n key={f}\n className=\"flex items-start gap-2 text-xs text-text-secondary\"\n >\n <Check className=\"mt-0.5 h-3.5 w-3.5 shrink-0 text-status-success-text\" />\n <span>{f}</span>\n </li>\n ))}\n {plan.features.length > 6 && (\n <li className=\"pl-6 text-[11px] text-text-secondary\">\n +{plan.features.length - 6} more\n </li>\n )}\n </ul>\n )}\n </GlassCard>\n );\n })}\n </div>\n )}\n </Section>\n </div>\n\n {/* Sidebar — vendor health, churn risk, at-a-glance */}\n <div className=\"space-y-4\">\n <GlassCard treatment=\"metric\" className=\"p-5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"inline-flex items-center gap-2 text-sm font-medium text-text-primary\">\n <ShieldCheck className=\"h-4 w-4 text-text-secondary\" /> Vendor health\n </span>\n {p.vendorHealthScore != null && (\n <span\n className={cn(\n 'rounded-full px-2 py-0.5 text-[11px] font-medium',\n healthMeta(p.vendorHealthScore).cls\n )}\n >\n {healthMeta(p.vendorHealthScore).label}\n </span>\n )}\n </div>\n {p.vendorHealthScore != null ? (\n <div className=\"mt-2 flex flex-col items-center\">\n <Gauge value={p.vendorHealthScore} max={100} size={168} label=\"out of 100\" />\n </div>\n ) : (\n <p className=\"mt-4 text-sm text-text-secondary\">No health score yet.</p>\n )}\n </GlassCard>\n\n <GlassCard treatment=\"metric\" className=\"p-5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"inline-flex items-center gap-2 text-sm font-medium text-text-primary\">\n <TrendingDown className=\"h-4 w-4 text-text-secondary\" /> Churn risk\n </span>\n {p.churnRiskScore != null && (\n <span\n className={cn(\n 'rounded-full px-2 py-0.5 text-[11px] font-medium',\n churnMeta(p.churnRiskScore).chip\n )}\n >\n {churnMeta(p.churnRiskScore).label}\n </span>\n )}\n </div>\n {p.churnRiskScore != null ? (\n <>\n <div className=\"mt-3 flex items-baseline justify-between\">\n <span className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {p.churnRiskScore}\n </span>\n <span className=\"text-xs text-text-secondary\">/ 100</span>\n </div>\n <MiniProgress\n value={p.churnRiskScore}\n tone={churnMeta(p.churnRiskScore).tone}\n className=\"mt-2\"\n />\n </>\n ) : (\n <p className=\"mt-4 text-sm text-text-secondary\">No churn signal yet.</p>\n )}\n </GlassCard>\n\n <GlassCard treatment=\"metric\" className=\"p-5\">\n <span className=\"inline-flex items-center gap-2 text-sm font-medium text-text-primary\">\n <Layers className=\"h-4 w-4 text-text-secondary\" /> At a glance\n </span>\n <dl className=\"mt-3 space-y-2.5 text-sm\">\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-text-secondary\">Category</dt>\n <dd className=\"font-medium text-text-primary\">{formatEnumLabel(p.category)}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-text-secondary\">Industry</dt>\n <dd className=\"font-medium text-text-primary\">{p.industry ?? '—'}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-text-secondary\">Region</dt>\n <dd className=\"font-medium text-text-primary\">{p.region ?? '—'}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-text-secondary\">Language</dt>\n <dd className=\"font-medium text-text-primary\">{p.language ?? '—'}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-text-secondary\">Published plans</dt>\n <dd className=\"font-medium tabular-nums text-text-primary\">\n {p.plans?.length ?? 0}\n </dd>\n </div>\n </dl>\n </GlassCard>\n </div>\n </div>\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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"}
@@ -1,12 +1,14 @@
1
1
  import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
- import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { useCreateProvider as n } from "../../hooks/useSubscriberBotApi.js";
4
- import { useState as r } from "react";
5
- import { ArrowLeft as i } from "lucide-react";
6
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
- import { PagePurpose as s } from "@burdenoff/fe-libs/ui";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { formatEnumLabel as r } from "../../utils/formatters.js";
5
+ import { useCreateProvider as i } from "../../hooks/useSubscriberBotApi.js";
6
+ import { useState as a } from "react";
7
+ import { ArrowLeft as o, Building2 as s, Sparkles as c } from "lucide-react";
8
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
9
+ import { GlassCard as d, PagePurpose as f } from "@burdenoff/fe-libs/ui";
8
10
  //#region src/subscriberbot/pages/providers/ProviderNewPage.tsx
9
- var c = [
11
+ var p = [
10
12
  "SAAS",
11
13
  "AI_SERVICE",
12
14
  "STREAMING",
@@ -23,163 +25,225 @@ var c = [
23
25
  "LICENSE",
24
26
  "CONTRACT",
25
27
  "OTHER"
26
- ], l = "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)]", u = "mb-1 block text-xs font-medium text-text-secondary";
27
- function d() {
28
- let { navigateTo: d } = e(), f = n(), [p, m] = r(""), [h, g] = r("SAAS"), [_, v] = r(""), [y, b] = r(""), [x, S] = r(""), [C, w] = r(""), [T, E] = r(""), [D, O] = r(null);
29
- return /* @__PURE__ */ o(t, {
28
+ ], m = "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)]", h = "mb-1 block text-xs font-medium text-text-secondary";
29
+ function g() {
30
+ let { navigateTo: g } = e(), _ = i(), [v, y] = a(""), [b, x] = a("SAAS"), [S, C] = a(""), [w, T] = a(""), [E, D] = a(""), [O, k] = a(""), [A, j] = a(""), [M, N] = a(null), P = A.split(",").map((e) => e.trim()).filter(Boolean);
31
+ return /* @__PURE__ */ u(n, {
30
32
  title: "Add provider",
31
33
  description: "Register a new provider in the registry",
32
- actions: /* @__PURE__ */ o("button", {
34
+ actions: /* @__PURE__ */ u("button", {
33
35
  type: "button",
34
- onClick: () => d("/providers"),
36
+ onClick: () => g("/providers"),
35
37
  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",
36
- children: [/* @__PURE__ */ a(i, { className: "h-4 w-4" }), " Back"]
38
+ children: [/* @__PURE__ */ l(o, { className: "h-4 w-4" }), " Back"]
37
39
  }),
38
- children: [/* @__PURE__ */ a(s, {
40
+ children: [/* @__PURE__ */ l(f, {
39
41
  className: "mb-6",
40
42
  children: "Add a provider that isn't in the registry yet so you can attach relationships, plans and assets to it."
41
- }), /* @__PURE__ */ o("form", {
42
- onSubmit: (e) => {
43
- if (e.preventDefault(), O(null), !p.trim()) {
44
- O("A provider name is required.");
45
- return;
46
- }
47
- let t = T.split(",").map((e) => e.trim()).filter(Boolean), n = {
48
- name: p.trim(),
49
- category: h,
50
- ..._.trim() ? { description: _.trim() } : {},
51
- ...y.trim() ? { websiteUrl: y.trim() } : {},
52
- ...x.trim() ? { region: x.trim() } : {},
53
- ...C.trim() ? { industry: C.trim() } : {},
54
- ...t.length ? { tags: t } : {}
55
- };
56
- f.mutate(n, {
57
- onSuccess: (e) => d(`/providers/${e.id}`),
58
- onError: (e) => O(e instanceof Error ? e.message : "Could not create provider.")
59
- });
60
- },
61
- className: "max-w-2xl space-y-5",
62
- children: [
63
- D && /* @__PURE__ */ a("div", {
64
- className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
65
- children: D
66
- }),
67
- /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ o("label", {
68
- htmlFor: "prov-name",
69
- className: u,
70
- children: ["Name ", /* @__PURE__ */ a("span", {
71
- className: "text-status-error-text",
72
- children: "*"
73
- })]
74
- }), /* @__PURE__ */ a("input", {
75
- id: "prov-name",
76
- type: "text",
77
- value: p,
78
- onChange: (e) => m(e.target.value),
79
- placeholder: "e.g. OpenAI, Netflix, AWS",
80
- className: l,
81
- required: !0
82
- })] }),
83
- /* @__PURE__ */ o("div", {
84
- className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
85
- children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
86
- htmlFor: "prov-category",
87
- className: u,
88
- children: "Category"
89
- }), /* @__PURE__ */ a("select", {
90
- id: "prov-category",
91
- value: h,
92
- onChange: (e) => g(e.target.value),
93
- className: l,
94
- children: c.map((e) => /* @__PURE__ */ a("option", {
95
- value: e,
96
- children: e.replace(/_/g, " ")
97
- }, e))
98
- })] }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
99
- htmlFor: "prov-website",
100
- className: u,
101
- children: "Website"
102
- }), /* @__PURE__ */ a("input", {
103
- id: "prov-website",
104
- type: "url",
105
- value: y,
106
- onChange: (e) => b(e.target.value),
107
- placeholder: "https://…",
108
- className: l
109
- })] })]
110
- }),
111
- /* @__PURE__ */ o("div", {
112
- className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
113
- children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
114
- htmlFor: "prov-region",
115
- className: u,
116
- children: "Region"
117
- }), /* @__PURE__ */ a("input", {
118
- id: "prov-region",
119
- type: "text",
120
- value: x,
121
- onChange: (e) => S(e.target.value),
122
- placeholder: "e.g. Global, US, EU",
123
- className: l
124
- })] }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
125
- htmlFor: "prov-industry",
126
- className: u,
127
- children: "Industry"
128
- }), /* @__PURE__ */ a("input", {
129
- id: "prov-industry",
130
- type: "text",
131
- value: C,
132
- onChange: (e) => w(e.target.value),
133
- placeholder: "e.g. Cloud, Media",
134
- className: l
135
- })] })]
136
- }),
137
- /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
138
- htmlFor: "prov-desc",
139
- className: u,
140
- children: "Description"
141
- }), /* @__PURE__ */ a("textarea", {
142
- id: "prov-desc",
143
- value: _,
144
- onChange: (e) => v(e.target.value),
145
- rows: 3,
146
- placeholder: "What does this provider offer?",
147
- className: l
148
- })] }),
149
- /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ o("label", {
150
- htmlFor: "prov-tags",
151
- className: u,
152
- children: ["Tags ", /* @__PURE__ */ a("span", {
153
- className: "text-text-secondary",
154
- children: "(comma-separated)"
155
- })]
156
- }), /* @__PURE__ */ a("input", {
157
- id: "prov-tags",
158
- type: "text",
159
- value: T,
160
- onChange: (e) => E(e.target.value),
161
- placeholder: "ai, productivity, enterprise",
162
- className: l
163
- })] }),
164
- /* @__PURE__ */ o("div", {
165
- className: "flex gap-3",
166
- children: [/* @__PURE__ */ a("button", {
167
- type: "submit",
168
- disabled: f.isPending,
169
- className: "rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
170
- children: f.isPending ? "Creating…" : "Create provider"
171
- }), /* @__PURE__ */ a("button", {
172
- type: "button",
173
- onClick: () => d("/providers"),
174
- className: "rounded-lg border border-border-subtle px-5 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken",
175
- children: "Cancel"
176
- })]
43
+ }), /* @__PURE__ */ u("div", {
44
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
45
+ children: [/* @__PURE__ */ l(d, {
46
+ treatment: "metric",
47
+ className: "p-6 lg:col-span-2",
48
+ children: /* @__PURE__ */ u("form", {
49
+ onSubmit: (e) => {
50
+ if (e.preventDefault(), N(null), !v.trim()) {
51
+ N("A provider name is required.");
52
+ return;
53
+ }
54
+ let t = {
55
+ name: v.trim(),
56
+ category: b,
57
+ ...S.trim() ? { description: S.trim() } : {},
58
+ ...w.trim() ? { websiteUrl: w.trim() } : {},
59
+ ...E.trim() ? { region: E.trim() } : {},
60
+ ...O.trim() ? { industry: O.trim() } : {},
61
+ ...P.length ? { tags: P } : {}
62
+ };
63
+ _.mutate(t, {
64
+ onSuccess: (e) => g(`/providers/${e.id}`),
65
+ onError: (e) => N(e instanceof Error ? e.message : "Could not create provider.")
66
+ });
67
+ },
68
+ className: "space-y-5",
69
+ children: [
70
+ M && /* @__PURE__ */ l("div", {
71
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
72
+ children: M
73
+ }),
74
+ /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ u("label", {
75
+ htmlFor: "prov-name",
76
+ className: h,
77
+ children: ["Name ", /* @__PURE__ */ l("span", {
78
+ className: "text-status-error-text",
79
+ children: "*"
80
+ })]
81
+ }), /* @__PURE__ */ l("input", {
82
+ id: "prov-name",
83
+ type: "text",
84
+ value: v,
85
+ onChange: (e) => y(e.target.value),
86
+ placeholder: "e.g. OpenAI, Netflix, AWS",
87
+ className: m,
88
+ required: !0
89
+ })] }),
90
+ /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("span", {
91
+ className: h,
92
+ children: "Category"
93
+ }), /* @__PURE__ */ l("div", {
94
+ className: "flex flex-wrap gap-2",
95
+ role: "group",
96
+ "aria-label": "Provider category",
97
+ children: p.map((e) => {
98
+ let n = b === e;
99
+ return /* @__PURE__ */ l("button", {
100
+ type: "button",
101
+ "aria-pressed": n,
102
+ onClick: () => x(e),
103
+ className: t("rounded-full border px-3 py-1.5 text-xs font-medium transition-colors", n ? "border-transparent bg-action-primary-bg text-action-primary-text" : "border-border-subtle bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary"),
104
+ children: r(e)
105
+ }, e);
106
+ })
107
+ })] }),
108
+ /* @__PURE__ */ u("div", {
109
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
110
+ children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
111
+ htmlFor: "prov-website",
112
+ className: h,
113
+ children: "Website"
114
+ }), /* @__PURE__ */ l("input", {
115
+ id: "prov-website",
116
+ type: "url",
117
+ value: w,
118
+ onChange: (e) => T(e.target.value),
119
+ placeholder: "https://…",
120
+ className: m
121
+ })] }), /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
122
+ htmlFor: "prov-region",
123
+ className: h,
124
+ children: "Region"
125
+ }), /* @__PURE__ */ l("input", {
126
+ id: "prov-region",
127
+ type: "text",
128
+ value: E,
129
+ onChange: (e) => D(e.target.value),
130
+ placeholder: "e.g. Global, US, EU",
131
+ className: m
132
+ })] })]
133
+ }),
134
+ /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
135
+ htmlFor: "prov-industry",
136
+ className: h,
137
+ children: "Industry"
138
+ }), /* @__PURE__ */ l("input", {
139
+ id: "prov-industry",
140
+ type: "text",
141
+ value: O,
142
+ onChange: (e) => k(e.target.value),
143
+ placeholder: "e.g. Cloud, Media",
144
+ className: m
145
+ })] }),
146
+ /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("label", {
147
+ htmlFor: "prov-desc",
148
+ className: h,
149
+ children: "Description"
150
+ }), /* @__PURE__ */ l("textarea", {
151
+ id: "prov-desc",
152
+ value: S,
153
+ onChange: (e) => C(e.target.value),
154
+ rows: 3,
155
+ placeholder: "What does this provider offer?",
156
+ className: m
157
+ })] }),
158
+ /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ u("label", {
159
+ htmlFor: "prov-tags",
160
+ className: h,
161
+ children: ["Tags ", /* @__PURE__ */ l("span", {
162
+ className: "text-text-secondary",
163
+ children: "(comma-separated)"
164
+ })]
165
+ }), /* @__PURE__ */ l("input", {
166
+ id: "prov-tags",
167
+ type: "text",
168
+ value: A,
169
+ onChange: (e) => j(e.target.value),
170
+ placeholder: "ai, productivity, enterprise",
171
+ className: m
172
+ })] }),
173
+ /* @__PURE__ */ u("div", {
174
+ className: "flex flex-wrap gap-3 border-t border-border-subtle pt-5",
175
+ children: [/* @__PURE__ */ l("button", {
176
+ type: "submit",
177
+ disabled: _.isPending,
178
+ className: "rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
179
+ children: _.isPending ? "Creating…" : "Create provider"
180
+ }), /* @__PURE__ */ l("button", {
181
+ type: "button",
182
+ onClick: () => g("/providers"),
183
+ className: "rounded-lg border border-border-subtle px-5 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken",
184
+ children: "Cancel"
185
+ })]
186
+ })
187
+ ]
177
188
  })
178
- ]
189
+ }), /* @__PURE__ */ u("div", {
190
+ className: "lg:sticky lg:top-6 lg:self-start",
191
+ children: [/* @__PURE__ */ u("p", {
192
+ className: "mb-2 inline-flex items-center gap-1.5 text-xs font-medium text-text-secondary",
193
+ children: [/* @__PURE__ */ l(c, { className: "h-3.5 w-3.5" }), " Registry preview"]
194
+ }), /* @__PURE__ */ u(d, {
195
+ treatment: "glass",
196
+ className: "flex flex-col p-5",
197
+ children: [
198
+ /* @__PURE__ */ u("div", {
199
+ className: "flex items-start justify-between gap-2",
200
+ children: [/* @__PURE__ */ l("span", {
201
+ className: "flex size-10 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-text-primary",
202
+ children: /* @__PURE__ */ l(s, { className: "h-5 w-5" })
203
+ }), /* @__PURE__ */ l("span", {
204
+ className: "rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-[11px] font-medium text-status-warning-text",
205
+ children: "Unverified"
206
+ })]
207
+ }),
208
+ /* @__PURE__ */ l("p", {
209
+ className: "mt-3 truncate text-base font-semibold text-text-primary",
210
+ children: v.trim() || "Provider name"
211
+ }),
212
+ /* @__PURE__ */ l("span", {
213
+ className: "mt-1 inline-flex w-fit rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
214
+ children: r(b)
215
+ }),
216
+ S.trim() ? /* @__PURE__ */ l("p", {
217
+ className: "mt-3 line-clamp-3 text-xs leading-relaxed text-text-secondary",
218
+ children: S.trim()
219
+ }) : /* @__PURE__ */ l("p", {
220
+ className: "mt-3 text-xs italic text-text-secondary/70",
221
+ children: "A short description will appear here."
222
+ }),
223
+ (E.trim() || O.trim() || P.length > 0) && /* @__PURE__ */ u("div", {
224
+ className: "mt-4 flex flex-wrap items-center gap-2 border-t border-border-subtle pt-3",
225
+ children: [
226
+ O.trim() && /* @__PURE__ */ l("span", {
227
+ className: "text-[11px] text-text-secondary",
228
+ children: O.trim()
229
+ }),
230
+ E.trim() && /* @__PURE__ */ u("span", {
231
+ className: "text-[11px] text-text-secondary",
232
+ children: ["· ", E.trim()]
233
+ }),
234
+ P.slice(0, 4).map((e) => /* @__PURE__ */ l("span", {
235
+ className: "rounded-full bg-bg-sunken px-2 py-0.5 text-[11px] text-text-secondary",
236
+ children: e
237
+ }, e))
238
+ ]
239
+ })
240
+ ]
241
+ })]
242
+ })]
179
243
  })]
180
244
  });
181
245
  }
182
246
  //#endregion
183
- export { d as ProviderNewPage };
247
+ export { g as ProviderNewPage };
184
248
 
185
249
  //# sourceMappingURL=ProviderNewPage.js.map