@burdenoff/microfe-subscriberbot 2026.628.1 → 2026.706.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"RelationshipNewPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/relationships/RelationshipNewPage.tsx"],"sourcesContent":["/**\n * Create relationship\n * @module subscriberbot/pages/relationships\n *\n * Manual-add form for a recurring relationship AI can't auto-detect.\n * Writes `subCreateRelationship`. Provider + plan are optional pickers\n * sourced from the real registry (`subListProviders` / `subListPlans`).\n */\n\nimport { useState } from 'react';\nimport { ArrowLeft } from 'lucide-react';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { ErrorView } from '../../components/StateViews';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport {\n useCreateRelationship,\n useProviders,\n usePlans,\n} from '../../hooks/useSubscriberBotApi';\nimport type {\n SubBillingInterval,\n SubCreateRelationshipInput,\n SubRelationshipKind,\n} from '../../types';\n\nconst KINDS: SubRelationshipKind[] = [\n 'SUBSCRIPTION',\n 'MEMBERSHIP',\n 'LICENSE',\n 'CONTRACT',\n 'NEWSLETTER',\n 'RECURRING_PAYMENT',\n 'ENROLLMENT',\n 'TRIAL',\n];\n\nconst INTERVALS: SubBillingInterval[] = [\n 'MONTHLY',\n 'YEARLY',\n 'QUARTERLY',\n 'WEEKLY',\n 'DAILY',\n 'USAGE_BASED',\n 'LIFETIME',\n 'FREE',\n];\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\nexport function RelationshipNewPage() {\n const { navigateTo } = useSubscriberBot();\n const create = useCreateRelationship();\n const providersQ = useProviders({ pagination: { limit: 100, offset: 0 } });\n\n const [label, setLabel] = useState('');\n const [kind, setKind] = useState<SubRelationshipKind>('SUBSCRIPTION');\n const [providerId, setProviderId] = useState('');\n const [planId, setPlanId] = useState('');\n const [amount, setAmount] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [interval, setInterval] = useState<SubBillingInterval>('MONTHLY');\n const [renewsAt, setRenewsAt] = useState('');\n const [autoRenew, setAutoRenew] = useState(true);\n const [notes, setNotes] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n\n const plansQ = usePlans(providerId || undefined);\n const providers = providersQ.data?.items ?? [];\n const plans = plansQ.data ?? [];\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n if (!label.trim()) {\n setFormError('A label is required.');\n return;\n }\n const input: SubCreateRelationshipInput = {\n label: label.trim(),\n kind,\n interval,\n autoRenew,\n currency: currency.trim() || 'USD',\n ...(providerId ? { providerId } : {}),\n ...(planId ? { planId } : {}),\n ...(amount ? { amount: Number(amount) } : {}),\n ...(renewsAt ? { renewsAt: new Date(renewsAt).toISOString() } : {}),\n ...(notes.trim() ? { notes: notes.trim() } : {}),\n };\n create.mutate(input, {\n onSuccess: (rel) => navigateTo(`/relationships/${rel.id}`),\n onError: (err) =>\n setFormError(err instanceof Error ? err.message : 'Could not create relationship.'),\n });\n };\n\n if (providersQ.isError) {\n return (\n <PageLayout title=\"Add relationship\">\n <ErrorView\n message=\"Could not load the provider registry.\"\n onRetry={() => void providersQ.refetch()}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Add relationship\"\n description=\"Track a new recurring digital relationship\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships')}\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 <PagePurpose className=\"mb-6\">\n Manually add a subscription, membership, license or contract. Link it to a provider and plan\n from the registry, set the price and renewal date, and Subscriber Bot will track its\n lifecycle from here.\n </PagePurpose>\n\n <form onSubmit={handleSubmit} className=\"max-w-2xl space-y-5\">\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\n <div>\n <label htmlFor=\"rel-label\" className={labelCls}>\n Label <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"rel-label\"\n type=\"text\"\n value={label}\n onChange={(e) => setLabel(e.target.value)}\n placeholder=\"e.g. Netflix Premium, AWS Production\"\n className={inputCls}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"rel-kind\" className={labelCls}>\n Kind\n </label>\n <select\n id=\"rel-kind\"\n value={kind}\n onChange={(e) => setKind(e.target.value as SubRelationshipKind)}\n className={inputCls}\n >\n {KINDS.map((k) => (\n <option key={k} value={k}>\n {k.replace(/_/g, ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"rel-provider\" className={labelCls}>\n Provider\n </label>\n <select\n id=\"rel-provider\"\n value={providerId}\n onChange={(e) => {\n setProviderId(e.target.value);\n setPlanId('');\n }}\n className={inputCls}\n >\n <option value=\"\">— None —</option>\n {providers.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n {providerId && plans.length > 0 && (\n <div>\n <label htmlFor=\"rel-plan\" className={labelCls}>\n Plan\n </label>\n <select\n id=\"rel-plan\"\n value={planId}\n onChange={(e) => setPlanId(e.target.value)}\n className={inputCls}\n >\n <option value=\"\">— None —</option>\n {plans.map((pl) => (\n <option key={pl.id} value={pl.id}>\n {pl.name}\n </option>\n ))}\n </select>\n </div>\n )}\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div>\n <label htmlFor=\"rel-amount\" className={labelCls}>\n Amount\n </label>\n <input\n id=\"rel-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=\"rel-currency\" className={labelCls}>\n Currency\n </label>\n <input\n id=\"rel-currency\"\n type=\"text\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value.toUpperCase())}\n placeholder=\"USD\"\n maxLength={3}\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"rel-interval\" className={labelCls}>\n Billing interval\n </label>\n <select\n id=\"rel-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\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"rel-renews\" className={labelCls}>\n Renews on\n </label>\n <input\n id=\"rel-renews\"\n type=\"date\"\n value={renewsAt}\n onChange={(e) => setRenewsAt(e.target.value)}\n className={inputCls}\n />\n </div>\n <div className=\"flex items-end\">\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={autoRenew}\n onChange={(e) => setAutoRenew(e.target.checked)}\n className=\"size-4 rounded border-border-subtle\"\n />\n Auto-renews\n </label>\n </div>\n </div>\n\n <div>\n <label htmlFor=\"rel-notes\" className={labelCls}>\n Notes\n </label>\n <textarea\n id=\"rel-notes\"\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n rows={3}\n placeholder=\"Anything worth remembering about this relationship…\"\n className={inputCls}\n />\n </div>\n\n <div className=\"flex gap-3\">\n <button\n type=\"submit\"\n disabled={create.isPending}\n 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\"\n >\n {create.isPending ? 'Creating…' : 'Create relationship'}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships')}\n className=\"rounded-lg border border-border-subtle px-5 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n </div>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"RelationshipNewPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/relationships/RelationshipNewPage.tsx"],"sourcesContent":["/**\n * Create relationship\n * @module subscriberbot/pages/relationships\n *\n * Manual-add form for a recurring relationship AI can't auto-detect.\n * Writes `subCreateRelationship`. Provider + plan are optional pickers\n * sourced from the real registry (`subListProviders` / `subListPlans`).\n */\n\nimport { useState } from 'react';\nimport { ArrowLeft } from 'lucide-react';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { ErrorView } from '../../components/StateViews';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useCreateRelationship, useProviders, usePlans } from '../../hooks/useSubscriberBotApi';\nimport type {\n SubBillingInterval,\n SubCreateRelationshipInput,\n SubRelationshipKind,\n} from '../../types';\n\nconst KINDS: SubRelationshipKind[] = [\n 'SUBSCRIPTION',\n 'MEMBERSHIP',\n 'LICENSE',\n 'CONTRACT',\n 'NEWSLETTER',\n 'RECURRING_PAYMENT',\n 'ENROLLMENT',\n 'TRIAL',\n];\n\nconst INTERVALS: SubBillingInterval[] = [\n 'MONTHLY',\n 'YEARLY',\n 'QUARTERLY',\n 'WEEKLY',\n 'DAILY',\n 'USAGE_BASED',\n 'LIFETIME',\n 'FREE',\n];\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\nexport function RelationshipNewPage() {\n const { navigateTo } = useSubscriberBot();\n const create = useCreateRelationship();\n const providersQ = useProviders({ pagination: { limit: 100, offset: 0 } });\n\n const [label, setLabel] = useState('');\n const [kind, setKind] = useState<SubRelationshipKind>('SUBSCRIPTION');\n const [providerId, setProviderId] = useState('');\n const [planId, setPlanId] = useState('');\n const [amount, setAmount] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [interval, setInterval] = useState<SubBillingInterval>('MONTHLY');\n const [renewsAt, setRenewsAt] = useState('');\n const [autoRenew, setAutoRenew] = useState(true);\n const [notes, setNotes] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n\n const plansQ = usePlans(providerId || undefined);\n const providers = providersQ.data?.items ?? [];\n const plans = plansQ.data ?? [];\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n if (!label.trim()) {\n setFormError('A label is required.');\n return;\n }\n const input: SubCreateRelationshipInput = {\n label: label.trim(),\n kind,\n interval,\n autoRenew,\n currency: currency.trim() || 'USD',\n ...(providerId ? { providerId } : {}),\n ...(planId ? { planId } : {}),\n ...(amount ? { amount: Number(amount) } : {}),\n ...(renewsAt ? { renewsAt: new Date(renewsAt).toISOString() } : {}),\n ...(notes.trim() ? { notes: notes.trim() } : {}),\n };\n create.mutate(input, {\n onSuccess: (rel) => navigateTo(`/relationships/${rel.id}`),\n onError: (err) =>\n setFormError(err instanceof Error ? err.message : 'Could not create relationship.'),\n });\n };\n\n if (providersQ.isError) {\n return (\n <PageLayout title=\"Add relationship\">\n <ErrorView\n message=\"Could not load the provider registry.\"\n onRetry={() => void providersQ.refetch()}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Add relationship\"\n description=\"Track a new recurring digital relationship\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships')}\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 <PagePurpose className=\"mb-6\">\n Manually add a subscription, membership, license or contract. Link it to a provider and plan\n from the registry, set the price and renewal date, and Subscriber Bot will track its\n lifecycle from here.\n </PagePurpose>\n\n <form onSubmit={handleSubmit} className=\"max-w-2xl space-y-5\">\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\n <div>\n <label htmlFor=\"rel-label\" className={labelCls}>\n Label <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"rel-label\"\n type=\"text\"\n value={label}\n onChange={(e) => setLabel(e.target.value)}\n placeholder=\"e.g. Netflix Premium, AWS Production\"\n className={inputCls}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"rel-kind\" className={labelCls}>\n Kind\n </label>\n <select\n id=\"rel-kind\"\n value={kind}\n onChange={(e) => setKind(e.target.value as SubRelationshipKind)}\n className={inputCls}\n >\n {KINDS.map((k) => (\n <option key={k} value={k}>\n {k.replace(/_/g, ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"rel-provider\" className={labelCls}>\n Provider\n </label>\n <select\n id=\"rel-provider\"\n value={providerId}\n onChange={(e) => {\n setProviderId(e.target.value);\n setPlanId('');\n }}\n className={inputCls}\n >\n <option value=\"\">— None —</option>\n {providers.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n {providerId && plans.length > 0 && (\n <div>\n <label htmlFor=\"rel-plan\" className={labelCls}>\n Plan\n </label>\n <select\n id=\"rel-plan\"\n value={planId}\n onChange={(e) => setPlanId(e.target.value)}\n className={inputCls}\n >\n <option value=\"\">— None —</option>\n {plans.map((pl) => (\n <option key={pl.id} value={pl.id}>\n {pl.name}\n </option>\n ))}\n </select>\n </div>\n )}\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div>\n <label htmlFor=\"rel-amount\" className={labelCls}>\n Amount\n </label>\n <input\n id=\"rel-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=\"rel-currency\" className={labelCls}>\n Currency\n </label>\n <input\n id=\"rel-currency\"\n type=\"text\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value.toUpperCase())}\n placeholder=\"USD\"\n maxLength={3}\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"rel-interval\" className={labelCls}>\n Billing interval\n </label>\n <select\n id=\"rel-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\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"rel-renews\" className={labelCls}>\n Renews on\n </label>\n <input\n id=\"rel-renews\"\n type=\"date\"\n value={renewsAt}\n onChange={(e) => setRenewsAt(e.target.value)}\n className={inputCls}\n />\n </div>\n <div className=\"flex items-end\">\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={autoRenew}\n onChange={(e) => setAutoRenew(e.target.checked)}\n className=\"size-4 rounded border-border-subtle\"\n />\n Auto-renews\n </label>\n </div>\n </div>\n\n <div>\n <label htmlFor=\"rel-notes\" className={labelCls}>\n Notes\n </label>\n <textarea\n id=\"rel-notes\"\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n rows={3}\n placeholder=\"Anything worth remembering about this relationship…\"\n className={inputCls}\n />\n </div>\n\n <div className=\"flex gap-3\">\n <button\n type=\"submit\"\n disabled={create.isPending}\n 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\"\n >\n {create.isPending ? 'Creating…' : 'Create relationship'}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships')}\n className=\"rounded-lg border border-border-subtle px-5 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n </div>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;AAsBA,IAAM,IAA+B;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAEK,IAAkC;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAEK,IACJ,wMACI,IAAW;AAEjB,SAAgB,IAAsB;CACpC,IAAM,EAAE,kBAAe,GAAkB,EACnC,IAAS,GAAuB,EAChC,IAAa,EAAa,EAAE,YAAY;EAAE,OAAO;EAAK,QAAQ;EAAG,EAAE,CAAC,EAEpE,CAAC,GAAO,KAAY,EAAS,GAAG,EAChC,CAAC,GAAM,KAAW,EAA8B,eAAe,EAC/D,CAAC,GAAY,KAAiB,EAAS,GAAG,EAC1C,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAU,KAAe,EAAS,MAAM,EACzC,CAAC,GAAU,KAAe,EAA6B,UAAU,EACjE,CAAC,GAAU,KAAe,EAAS,GAAG,EACtC,CAAC,GAAW,KAAgB,EAAS,GAAK,EAC1C,CAAC,GAAO,KAAY,EAAS,GAAG,EAChC,CAAC,GAAW,KAAgB,EAAwB,KAAK,EAEzD,IAAS,EAAS,KAAc,KAAA,EAAU,EAC1C,IAAY,EAAW,MAAM,SAAS,EAAE,EACxC,IAAQ,EAAO,QAAQ,EAAE;AAuC/B,QAXI,EAAW,UAEX,kBAAC,GAAD;EAAY,OAAM;YAChB,kBAAC,GAAD;GACE,SAAQ;GACR,eAAe,KAAK,EAAW,SAAS;GACxC,CAAA;EACS,CAAA,GAKf,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAW,iBAAiB;GAC3C,WAAU;aAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAAA,QAC1B;;YAVb,CAaE,kBAAC,GAAD;GAAa,WAAU;aAAO;GAIhB,CAAA,EAEd,kBAAC,QAAD;GAAM,WAzDY,MAAuB;AAG3C,QAFA,EAAE,gBAAgB,EAClB,EAAa,KAAK,EACd,CAAC,EAAM,MAAM,EAAE;AACjB,OAAa,uBAAuB;AACpC;;IAEF,IAAM,IAAoC;KACxC,OAAO,EAAM,MAAM;KACnB;KACA;KACA;KACA,UAAU,EAAS,MAAM,IAAI;KAC7B,GAAI,IAAa,EAAE,eAAY,GAAG,EAAE;KACpC,GAAI,IAAS,EAAE,WAAQ,GAAG,EAAE;KAC5B,GAAI,IAAS,EAAE,QAAQ,OAAO,EAAO,EAAE,GAAG,EAAE;KAC5C,GAAI,IAAW,EAAE,UAAU,IAAI,KAAK,EAAS,CAAC,aAAa,EAAE,GAAG,EAAE;KAClE,GAAI,EAAM,MAAM,GAAG,EAAE,OAAO,EAAM,MAAM,EAAE,GAAG,EAAE;KAChD;AACD,MAAO,OAAO,GAAO;KACnB,YAAY,MAAQ,EAAW,kBAAkB,EAAI,KAAK;KAC1D,UAAU,MACR,EAAa,aAAe,QAAQ,EAAI,UAAU,iCAAiC;KACtF,CAAC;;GAkC8B,WAAU;aAAxC;IACG,KACC,kBAAC,OAAD;KAAK,WAAU;eACZ;KACG,CAAA;IAGR,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;KAAO,SAAQ;KAAY,WAAW;eAAtC,CAAgD,UACxC,kBAAC,QAAD;MAAM,WAAU;gBAAyB;MAAQ,CAAA,CACjD;QACR,kBAAC,SAAD;KACE,IAAG;KACH,MAAK;KACL,OAAO;KACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;KACzC,aAAY;KACZ,WAAW;KACX,UAAA;KACA,CAAA,CACE,EAAA,CAAA;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MAAO,SAAQ;MAAW,WAAW;gBAAU;MAEvC,CAAA,EACR,kBAAC,UAAD;MACE,IAAG;MACH,OAAO;MACP,WAAW,MAAM,EAAQ,EAAE,OAAO,MAA6B;MAC/D,WAAW;gBAEV,EAAM,KAAK,MACV,kBAAC,UAAD;OAAgB,OAAO;iBACpB,EAAE,QAAQ,MAAM,IAAI;OACd,EAFI,EAEJ,CACT;MACK,CAAA,CACL,EAAA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MAAO,SAAQ;MAAe,WAAW;gBAAU;MAE3C,CAAA,EACR,kBAAC,UAAD;MACE,IAAG;MACH,OAAO;MACP,WAAW,MAAM;AAEf,OADA,EAAc,EAAE,OAAO,MAAM,EAC7B,EAAU,GAAG;;MAEf,WAAW;gBAPb,CASE,kBAAC,UAAD;OAAQ,OAAM;iBAAG;OAAiB,CAAA,EACjC,EAAU,KAAK,MACd,kBAAC,UAAD;OAAmB,OAAO,EAAE;iBACzB,EAAE;OACI,EAFI,EAAE,GAEN,CACT,CACK;QACL,EAAA,CAAA,CACF;;IAEL,KAAc,EAAM,SAAS,KAC5B,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;KAAO,SAAQ;KAAW,WAAW;eAAU;KAEvC,CAAA,EACR,kBAAC,UAAD;KACE,IAAG;KACH,OAAO;KACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;KAC1C,WAAW;eAJb,CAME,kBAAC,UAAD;MAAQ,OAAM;gBAAG;MAAiB,CAAA,EACjC,EAAM,KAAK,MACV,kBAAC,UAAD;MAAoB,OAAO,EAAG;gBAC3B,EAAG;MACG,EAFI,EAAG,GAEP,CACT,CACK;OACL,EAAA,CAAA;IAGR,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAa,WAAW;iBAAU;OAEzC,CAAA,EACR,kBAAC,SAAD;OACE,IAAG;OACH,MAAK;OACL,KAAI;OACJ,MAAK;OACL,OAAO;OACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;OAC1C,aAAY;OACZ,WAAW;OACX,CAAA,CACE,EAAA,CAAA;MACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAe,WAAW;iBAAU;OAE3C,CAAA,EACR,kBAAC,SAAD;OACE,IAAG;OACH,MAAK;OACL,OAAO;OACP,WAAW,MAAM,EAAY,EAAE,OAAO,MAAM,aAAa,CAAC;OAC1D,aAAY;OACZ,WAAW;OACX,WAAW;OACX,CAAA,CACE,EAAA,CAAA;MACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAe,WAAW;iBAAU;OAE3C,CAAA,EACR,kBAAC,UAAD;OACE,IAAG;OACH,OAAO;OACP,WAAW,MAAM,EAAY,EAAE,OAAO,MAA4B;OAClE,WAAW;iBAEV,EAAU,KAAK,MACd,kBAAC,UAAD;QAAgB,OAAO;kBACpB,EAAE,QAAQ,MAAM,IAAI;QACd,EAFI,EAEJ,CACT;OACK,CAAA,CACL,EAAA,CAAA;MACF;;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MAAO,SAAQ;MAAa,WAAW;gBAAU;MAEzC,CAAA,EACR,kBAAC,SAAD;MACE,IAAG;MACH,MAAK;MACL,OAAO;MACP,WAAW,MAAM,EAAY,EAAE,OAAO,MAAM;MAC5C,WAAW;MACX,CAAA,CACE,EAAA,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,SAAD;QACE,MAAK;QACL,SAAS;QACT,WAAW,MAAM,EAAa,EAAE,OAAO,QAAQ;QAC/C,WAAU;QACV,CAAA,EAAA,cAEI;;MACJ,CAAA,CACF;;IAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;KAAO,SAAQ;KAAY,WAAW;eAAU;KAExC,CAAA,EACR,kBAAC,YAAD;KACE,IAAG;KACH,OAAO;KACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;KACzC,MAAM;KACN,aAAY;KACZ,WAAW;KACX,CAAA,CACE,EAAA,CAAA;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,UAAU,EAAO;MACjB,WAAU;gBAET,EAAO,YAAY,cAAc;MAC3B,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAW,iBAAiB;MAC3C,WAAU;gBACX;MAEQ,CAAA,CACL;;IACD;KACI"}
@@ -1 +1 @@
1
- {"version":3,"file":"RelationshipsListPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/relationships/RelationshipsListPage.tsx"],"sourcesContent":["/**\n * Relationships list\n * @module subscriberbot/pages/relationships\n *\n * The core CRUDL list — every recurring relationship (subscription /\n * membership / license / contract) in one paginated, filterable view.\n * Data comes from `subListRelationships` (a SubRelationshipConnection).\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, Search, Repeat2 } 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 { useRelationships } from '../../hooks/useSubscriberBotApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency, formatDate, formatEnumLabel, formatIntervalSuffix } from '../../utils/formatters';\nimport type { SubRelationshipKind, SubRelationshipStatus } from '../../types';\n\nconst PAGE_SIZE = 20;\n\nconst STATUS_OPTIONS: Array<{ value: '' | SubRelationshipStatus; label: string }> = [\n { value: '', label: 'All statuses' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'TRIAL', label: 'Trial' },\n { value: 'PAUSED', label: 'Paused' },\n { value: 'PAST_DUE', label: 'Past due' },\n { value: 'LAPSED', label: 'Lapsed' },\n { value: 'EXPIRED', label: 'Expired' },\n { value: 'CANCELLED', label: 'Cancelled' },\n];\n\nconst KIND_OPTIONS: Array<{ value: '' | SubRelationshipKind; label: string }> = [\n { value: '', label: 'All kinds' },\n { value: 'SUBSCRIPTION', label: 'Subscription' },\n { value: 'MEMBERSHIP', label: 'Membership' },\n { value: 'LICENSE', label: 'License' },\n { value: 'CONTRACT', label: 'Contract' },\n { value: 'NEWSLETTER', label: 'Newsletter' },\n { value: 'RECURRING_PAYMENT', label: 'Recurring payment' },\n { value: 'ENROLLMENT', label: 'Enrollment' },\n { value: 'TRIAL', label: 'Trial' },\n];\n\nexport function RelationshipsListPage() {\n const { navigateTo } = useSubscriberBot();\n const [page, setPage] = useState(0);\n const [statusFilter, setStatusFilter] = useState<'' | SubRelationshipStatus>('');\n const [kindFilter, setKindFilter] = useState<'' | SubRelationshipKind>('');\n const [search, setSearch] = useState('');\n\n const { data, isLoading, isError, refetch, isFetching } = useRelationships({\n status: statusFilter || undefined,\n kind: kindFilter || undefined,\n pagination: { limit: PAGE_SIZE, offset: page * PAGE_SIZE },\n });\n\n const items = useMemo(() => data?.items ?? [], [data]);\n const hasMore = data?.pageInfo.hasMore ?? false;\n\n // Client-side label search over the current page (server has no search arg).\n const visible = useMemo(() => {\n if (!search.trim()) return items;\n const q = search.toLowerCase();\n return items.filter(\n (r) =>\n r.label.toLowerCase().includes(q) ||\n (r.provider?.name?.toLowerCase().includes(q) ?? false)\n );\n }, [items, search]);\n\n return (\n <PageLayout\n title=\"Relationships\"\n description=\"Every subscription, membership, license and contract you track\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships/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 relationship\n </button>\n }\n >\n <PagePurpose className=\"mb-4\">\n This is the fundamental object of Subscriber Bot. Filter by lifecycle and kind, open any row\n to manage its plan, payment, entitlements, assets and renewals, or advance its lifecycle.\n </PagePurpose>\n\n <EmphasisPanel>\n <div 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 relationships on this page…\"\n value={search}\n onChange={(e) => setSearch(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 </div>\n </EmphasisPanel>\n\n <div className=\"mt-4 flex flex-wrap items-center gap-3\">\n <select\n value={statusFilter}\n onChange={(e) => {\n setStatusFilter(e.target.value as '' | SubRelationshipStatus);\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 <select\n value={kindFilter}\n onChange={(e) => {\n setKindFilter(e.target.value as '' | SubRelationshipKind);\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 {KIND_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 relationships…\" />\n ) : isError ? (\n <ErrorView message=\"Could not load relationships.\" onRetry={() => void refetch()} />\n ) : visible.length === 0 ? (\n <div className=\"mt-6\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<Repeat2 className=\"h-12 w-12\" />}\n title=\"No relationships found\"\n description={\n search\n ? `No matches for \"${search}\" on this page.`\n : 'Add your first recurring relationship to start tracking it.'\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships/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 relationship\n </button>\n }\n />\n </div>\n ) : (\n <>\n <div className=\"mt-6 overflow-hidden rounded-lg border border-border-subtle bg-bg-surface\">\n <div className=\"hidden grid-cols-[2fr_1fr_1fr_1fr_1fr] gap-4 border-b border-border-subtle bg-bg-sunken px-4 py-2.5 text-xs font-medium text-text-secondary sm:grid\">\n <span>Relationship</span>\n <span>Kind</span>\n <span>Status</span>\n <span className=\"text-right\">Amount</span>\n <span className=\"text-right\">Renews</span>\n </div>\n <div className=\"divide-y divide-border-subtle\">\n {visible.map((r) => (\n <button\n key={r.id}\n type=\"button\"\n onClick={() => navigateTo(`/relationships/${r.id}`)}\n className=\"grid w-full grid-cols-1 gap-2 px-4 py-3 text-left hover:bg-bg-sunken sm:grid-cols-[2fr_1fr_1fr_1fr_1fr] sm:items-center sm:gap-4\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{r.label}</p>\n {r.provider?.name && (\n <p className=\"truncate text-xs text-text-secondary\">{r.provider.name}</p>\n )}\n </div>\n <span className=\"text-xs text-text-secondary\">{formatEnumLabel(r.kind)}</span>\n <span>\n <StatusBadge status={r.status} />\n </span>\n <span className=\"text-sm font-semibold tabular-nums text-text-primary sm:text-right\">\n {formatCurrency(r.amount, r.currency)}\n <span className=\"text-xs font-normal text-text-secondary\">\n {formatIntervalSuffix(r.interval)}\n </span>\n </span>\n <span className=\"text-xs text-text-secondary sm:text-right\">\n {r.renewsAt ? formatDate(r.renewsAt) : '—'}\n </span>\n </button>\n ))}\n </div>\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":"RelationshipsListPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/relationships/RelationshipsListPage.tsx"],"sourcesContent":["/**\n * Relationships list\n * @module subscriberbot/pages/relationships\n *\n * The core CRUDL list — every recurring relationship (subscription /\n * membership / license / contract) in one paginated, filterable view.\n * Data comes from `subListRelationships` (a SubRelationshipConnection).\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, Search, Repeat2 } 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 { useRelationships } from '../../hooks/useSubscriberBotApi';\nimport { cn } from '../../utils/cn';\nimport {\n formatCurrency,\n formatDate,\n formatEnumLabel,\n formatIntervalSuffix,\n} from '../../utils/formatters';\nimport type { SubRelationshipKind, SubRelationshipStatus } from '../../types';\n\nconst PAGE_SIZE = 20;\n\nconst STATUS_OPTIONS: Array<{ value: '' | SubRelationshipStatus; label: string }> = [\n { value: '', label: 'All statuses' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'TRIAL', label: 'Trial' },\n { value: 'PAUSED', label: 'Paused' },\n { value: 'PAST_DUE', label: 'Past due' },\n { value: 'LAPSED', label: 'Lapsed' },\n { value: 'EXPIRED', label: 'Expired' },\n { value: 'CANCELLED', label: 'Cancelled' },\n];\n\nconst KIND_OPTIONS: Array<{ value: '' | SubRelationshipKind; label: string }> = [\n { value: '', label: 'All kinds' },\n { value: 'SUBSCRIPTION', label: 'Subscription' },\n { value: 'MEMBERSHIP', label: 'Membership' },\n { value: 'LICENSE', label: 'License' },\n { value: 'CONTRACT', label: 'Contract' },\n { value: 'NEWSLETTER', label: 'Newsletter' },\n { value: 'RECURRING_PAYMENT', label: 'Recurring payment' },\n { value: 'ENROLLMENT', label: 'Enrollment' },\n { value: 'TRIAL', label: 'Trial' },\n];\n\nexport function RelationshipsListPage() {\n const { navigateTo } = useSubscriberBot();\n const [page, setPage] = useState(0);\n const [statusFilter, setStatusFilter] = useState<'' | SubRelationshipStatus>('');\n const [kindFilter, setKindFilter] = useState<'' | SubRelationshipKind>('');\n const [search, setSearch] = useState('');\n\n const { data, isLoading, isError, refetch, isFetching } = useRelationships({\n status: statusFilter || undefined,\n kind: kindFilter || undefined,\n pagination: { limit: PAGE_SIZE, offset: page * PAGE_SIZE },\n });\n\n const items = useMemo(() => data?.items ?? [], [data]);\n const hasMore = data?.pageInfo.hasMore ?? false;\n\n // Client-side label search over the current page (server has no search arg).\n const visible = useMemo(() => {\n if (!search.trim()) return items;\n const q = search.toLowerCase();\n return items.filter(\n (r) =>\n r.label.toLowerCase().includes(q) || (r.provider?.name?.toLowerCase().includes(q) ?? false)\n );\n }, [items, search]);\n\n return (\n <PageLayout\n title=\"Relationships\"\n description=\"Every subscription, membership, license and contract you track\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships/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 relationship\n </button>\n }\n >\n <PagePurpose className=\"mb-4\">\n This is the fundamental object of Subscriber Bot. Filter by lifecycle and kind, open any row\n to manage its plan, payment, entitlements, assets and renewals, or advance its lifecycle.\n </PagePurpose>\n\n <EmphasisPanel>\n <div 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 relationships on this page…\"\n value={search}\n onChange={(e) => setSearch(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 </div>\n </EmphasisPanel>\n\n <div className=\"mt-4 flex flex-wrap items-center gap-3\">\n <select\n value={statusFilter}\n onChange={(e) => {\n setStatusFilter(e.target.value as '' | SubRelationshipStatus);\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 <select\n value={kindFilter}\n onChange={(e) => {\n setKindFilter(e.target.value as '' | SubRelationshipKind);\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 {KIND_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 relationships…\" />\n ) : isError ? (\n <ErrorView message=\"Could not load relationships.\" onRetry={() => void refetch()} />\n ) : visible.length === 0 ? (\n <div className=\"mt-6\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<Repeat2 className=\"h-12 w-12\" />}\n title=\"No relationships found\"\n description={\n search\n ? `No matches for \"${search}\" on this page.`\n : 'Add your first recurring relationship to start tracking it.'\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships/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 relationship\n </button>\n }\n />\n </div>\n ) : (\n <>\n <div className=\"mt-6 overflow-hidden rounded-lg border border-border-subtle bg-bg-surface\">\n <div className=\"hidden grid-cols-[2fr_1fr_1fr_1fr_1fr] gap-4 border-b border-border-subtle bg-bg-sunken px-4 py-2.5 text-xs font-medium text-text-secondary sm:grid\">\n <span>Relationship</span>\n <span>Kind</span>\n <span>Status</span>\n <span className=\"text-right\">Amount</span>\n <span className=\"text-right\">Renews</span>\n </div>\n <div className=\"divide-y divide-border-subtle\">\n {visible.map((r) => (\n <button\n key={r.id}\n type=\"button\"\n onClick={() => navigateTo(`/relationships/${r.id}`)}\n className=\"grid w-full grid-cols-1 gap-2 px-4 py-3 text-left hover:bg-bg-sunken sm:grid-cols-[2fr_1fr_1fr_1fr_1fr] sm:items-center sm:gap-4\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{r.label}</p>\n {r.provider?.name && (\n <p className=\"truncate text-xs text-text-secondary\">{r.provider.name}</p>\n )}\n </div>\n <span className=\"text-xs text-text-secondary\">{formatEnumLabel(r.kind)}</span>\n <span>\n <StatusBadge status={r.status} />\n </span>\n <span className=\"text-sm font-semibold tabular-nums text-text-primary sm:text-right\">\n {formatCurrency(r.amount, r.currency)}\n <span className=\"text-xs font-normal text-text-secondary\">\n {formatIntervalSuffix(r.interval)}\n </span>\n </span>\n <span className=\"text-xs text-text-secondary sm:text-right\">\n {r.renewsAt ? formatDate(r.renewsAt) : '—'}\n </span>\n </button>\n ))}\n </div>\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-subscriberbot",
3
- "version": "2026.628.1",
3
+ "version": "2026.706.1",
4
4
  "description": "Burdenoff SubscriberBot Microfrontend",
5
5
  "type": "module",
6
6
  "files": [