@sudobility/consumables_pages 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +92 -16
- package/dist/CreditBalanceBadge.d.ts +10 -0
- package/dist/CreditBalanceBadge.js +5 -0
- package/dist/CreditStorePage.d.ts +10 -0
- package/dist/CreditStorePage.js +5 -0
- package/dist/PurchaseHistoryPage.d.ts +10 -0
- package/dist/PurchaseHistoryPage.js +6 -0
- package/dist/UsageHistoryPage.d.ts +10 -0
- package/dist/UsageHistoryPage.js +6 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.js +6 -0
- package/package.json +4 -4
package/CLAUDE.md
CHANGED
|
@@ -3,36 +3,109 @@
|
|
|
3
3
|
Web-only UI components for consumable credits system.
|
|
4
4
|
|
|
5
5
|
**npm**: `@sudobility/consumables_pages` (public)
|
|
6
|
+
**Version**: 0.0.7
|
|
7
|
+
**License**: BUSL-1.1
|
|
6
8
|
|
|
7
9
|
## Tech Stack
|
|
8
10
|
|
|
9
|
-
- **Language**: TypeScript (strict mode, JSX)
|
|
11
|
+
- **Language**: TypeScript 5.9.3 (strict mode, JSX)
|
|
10
12
|
- **Runtime**: Bun
|
|
11
|
-
- **
|
|
13
|
+
- **Package Manager**: Bun (never npm/yarn/pnpm)
|
|
14
|
+
- **Build**: TypeScript compiler via `tsconfig.build.json` (ESM only)
|
|
15
|
+
- **Test**: Vitest 4.x with jsdom environment, React Testing Library
|
|
12
16
|
- **Styling**: Tailwind CSS classes (consumer provides Tailwind)
|
|
17
|
+
- **JSX**: react-jsx (React 18/19)
|
|
13
18
|
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
- **CreditStorePage** — Balance display + grid of credit packages with buy buttons
|
|
17
|
-
- **PurchaseHistoryPage** — Table of purchase records (responsive: table on desktop, cards on mobile)
|
|
18
|
-
- **UsageHistoryPage** — Table of usage records (responsive)
|
|
19
|
-
- **CreditBalanceBadge** — Small inline badge for topbar integration
|
|
19
|
+
## Project Structure
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
```
|
|
22
|
+
src/
|
|
23
|
+
├── index.ts # Barrel exports (components + types)
|
|
24
|
+
├── types.ts # All prop/label/formatter interfaces
|
|
25
|
+
├── CreditStorePage.tsx # Balance display + grid of credit packages with buy buttons
|
|
26
|
+
├── PurchaseHistoryPage.tsx # Responsive table/cards of purchase records
|
|
27
|
+
├── UsageHistoryPage.tsx # Responsive table/cards of usage records
|
|
28
|
+
├── CreditBalanceBadge.tsx # Small inline badge for topbar integration
|
|
29
|
+
└── __tests__/
|
|
30
|
+
├── setup.ts # Vitest setup (jsdom config)
|
|
31
|
+
├── CreditBalanceBadge.test.tsx
|
|
32
|
+
├── CreditStorePage.test.tsx
|
|
33
|
+
├── PurchaseHistoryPage.test.tsx
|
|
34
|
+
└── UsageHistoryPage.test.tsx
|
|
35
|
+
```
|
|
22
36
|
|
|
23
37
|
## Commands
|
|
24
38
|
|
|
25
39
|
```bash
|
|
26
|
-
bun run build # Build ESM
|
|
27
|
-
bun run dev # Watch mode
|
|
28
|
-
bun run
|
|
29
|
-
bun
|
|
40
|
+
bun run build # Build ESM via tsc -p tsconfig.build.json
|
|
41
|
+
bun run dev # Watch mode (tsc --watch)
|
|
42
|
+
bun run clean # Remove dist/
|
|
43
|
+
bun run typecheck # TypeScript check (bunx tsc --noEmit)
|
|
44
|
+
bun test # Run tests (vitest run)
|
|
45
|
+
bun run test:watch # Watch tests
|
|
46
|
+
bun run lint # ESLint
|
|
47
|
+
bun run lint:fix # ESLint with auto-fix
|
|
48
|
+
bun run format # Prettier format
|
|
30
49
|
```
|
|
31
50
|
|
|
51
|
+
## Components
|
|
52
|
+
|
|
53
|
+
### CreditStorePage
|
|
54
|
+
- Balance display panel (blue box) when authenticated
|
|
55
|
+
- Error display, login prompt for unauthenticated users
|
|
56
|
+
- Loading spinner
|
|
57
|
+
- Responsive grid of credit packages (1 col -> 2 col sm -> 3 col lg)
|
|
58
|
+
- Buy buttons with purchasing state
|
|
59
|
+
- Props: `CreditStorePageProps` (isAuthenticated, balance, packages, labels, formatters, callbacks)
|
|
60
|
+
|
|
61
|
+
### PurchaseHistoryPage
|
|
62
|
+
- Desktop: `<table>` with columns (date, credits, source, amount)
|
|
63
|
+
- Mobile: card layout (sm:hidden / hidden sm:block pattern)
|
|
64
|
+
- "Load more" pagination button
|
|
65
|
+
- Props: `PurchaseHistoryPageProps` (purchases, labels, formatters, onLoadMore, hasMore)
|
|
66
|
+
|
|
67
|
+
### UsageHistoryPage
|
|
68
|
+
- Desktop: `<table>` with columns (date, filename)
|
|
69
|
+
- Mobile: card layout
|
|
70
|
+
- "Load more" pagination button
|
|
71
|
+
- Props: `UsageHistoryPageProps` (usages, labels, formatters, onLoadMore, hasMore)
|
|
72
|
+
|
|
73
|
+
### CreditBalanceBadge
|
|
74
|
+
- Inline pill badge showing credit count with coin SVG icon
|
|
75
|
+
- Blue when balance > 0, red when balance is 0
|
|
76
|
+
- Optional `onClick` makes it a `<button>` instead of `<span>`
|
|
77
|
+
- Loading state shows animated "..."
|
|
78
|
+
- Returns `null` when balance is null and not loading
|
|
79
|
+
|
|
80
|
+
## Dependencies
|
|
81
|
+
|
|
82
|
+
### Peer Dependencies
|
|
83
|
+
- `@sudobility/consumables_client` ^0.0.6 -- TypeScript types only (CreditPackage)
|
|
84
|
+
- `@sudobility/types` ^1.9.53 -- shared types (ConsumablePurchaseRecord, ConsumableUsageRecord)
|
|
85
|
+
- `react` ^18.0.0 || ^19.0.0
|
|
86
|
+
- `react-dom` ^18.0.0 || ^19.0.0
|
|
87
|
+
|
|
88
|
+
### Dev Dependencies
|
|
89
|
+
- TypeScript ~5.9.3, Vitest ^4.0.4, @testing-library/react ^16.x, @testing-library/jest-dom ^6.x
|
|
90
|
+
- jsdom ^28.x, Vite ^7.x, ESLint ^9.x, Prettier ^3.x
|
|
91
|
+
|
|
92
|
+
## Build Configuration
|
|
93
|
+
|
|
94
|
+
- **tsconfig.json**: Used for type checking (`noEmit: true`), includes `allowImportingTsExtensions`
|
|
95
|
+
- **tsconfig.build.json**: Extends tsconfig.json, sets `noEmit: false`, `allowImportingTsExtensions: false`, `rootDir: ./src`
|
|
96
|
+
- **vitest.config.ts**: jsdom environment, globals enabled, setup file at `./src/__tests__/setup.ts`
|
|
97
|
+
|
|
98
|
+
## Type Architecture
|
|
99
|
+
|
|
100
|
+
All component prop types are defined in `src/types.ts`:
|
|
101
|
+
- **Labels interfaces** (`CreditStorePageLabels`, etc.) -- all user-facing strings for i18n
|
|
102
|
+
- **Formatters interfaces** (`CreditStorePageFormatters`, etc.) -- functions for formatting credits, dates, amounts, sources
|
|
103
|
+
- **Props interfaces** (`CreditStorePageProps`, etc.) -- combine data, labels, formatters, and callbacks
|
|
104
|
+
|
|
32
105
|
## Related Projects
|
|
33
106
|
|
|
34
|
-
- **consumables_client** (`@sudobility/consumables_client`)
|
|
35
|
-
- **@sudobility/types**
|
|
107
|
+
- **consumables_client** (`@sudobility/consumables_client`) -- Peer dependency that provides hooks (`useBalance`, `usePurchaseCredits`, etc.) and data types. This package does NOT call those hooks internally; the consuming app calls them and passes data as props.
|
|
108
|
+
- **@sudobility/types** -- Shared type definitions used across the consumables ecosystem.
|
|
36
109
|
|
|
37
110
|
Dependency direction: `consumables_pages` depends on `consumables_client` (peer dep for types only, not runtime calls)
|
|
38
111
|
|
|
@@ -40,8 +113,9 @@ Dependency direction: `consumables_pages` depends on `consumables_client` (peer
|
|
|
40
113
|
|
|
41
114
|
- **Props-driven components (no internal state)**: Components receive all data and callbacks via props. They do not call hooks, manage state, or fetch data. This makes them pure presentational components.
|
|
42
115
|
- **Customizable labels and formatters for i18n**: All user-facing text is passed in via `labels` props, and numeric/date formatting uses `formatter` props. Never hardcode user-visible strings inside components.
|
|
43
|
-
- **Responsive design with Tailwind sm
|
|
116
|
+
- **Responsive design with Tailwind sm breakpoint**: Components use `hidden sm:block` for desktop tables and `sm:hidden` for mobile cards. CreditStorePage uses `sm:grid-cols-2 lg:grid-cols-3` for its grid.
|
|
44
117
|
- **No direct CSS**: All styling uses Tailwind utility classes. Do not introduce CSS files, CSS modules, or styled-components.
|
|
118
|
+
- **Conditional wrapper element**: CreditBalanceBadge uses `const Wrapper = onClick ? "button" : "span"` for semantic HTML.
|
|
45
119
|
|
|
46
120
|
## Gotchas
|
|
47
121
|
|
|
@@ -49,6 +123,8 @@ Dependency direction: `consumables_pages` depends on `consumables_client` (peer
|
|
|
49
123
|
- **Components are purely presentational**: No hooks are called inside components. The parent app is responsible for calling `useBalance()`, `usePurchaseCredits()`, etc. from `consumables_client` and passing the results as props. Breaking this pattern creates tight coupling.
|
|
50
124
|
- **No internal state**: Components derive everything from props. If you need loading states or error states, they must be passed in as props, not managed internally with `useState`.
|
|
51
125
|
- **Peer dependency on consumables_client**: The package depends on `consumables_client` for TypeScript types (e.g., `CreditPackage`, `CreditBalance`), but it never imports runtime code from it. The peer dependency ensures type compatibility.
|
|
126
|
+
- **Hardcoded "Log in" button text**: The login button in `CreditStorePage` has hardcoded text `"Log in"` rather than using the labels prop. This is the only non-i18n string in the components.
|
|
127
|
+
- **`tsconfig.json` has `noEmit: true`**: The main tsconfig is for checking only. Building requires `tsconfig.build.json` (via `bun run build`).
|
|
52
128
|
|
|
53
129
|
## Testing
|
|
54
130
|
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Inline credit balance badge component for topbar integration.
|
|
3
|
+
* Displays a pill-shaped badge with a coin icon and the current balance.
|
|
4
|
+
* Renders as a button when onClick is provided, otherwise as a span.
|
|
5
|
+
*/
|
|
1
6
|
import type { CreditBalanceBadgeProps } from "./types";
|
|
7
|
+
/**
|
|
8
|
+
* Renders a small inline badge showing the user's credit balance.
|
|
9
|
+
* Blue when balance > 0, red when balance is 0. Returns null when balance is null.
|
|
10
|
+
* @param props - See {@link CreditBalanceBadgeProps} for full prop documentation.
|
|
11
|
+
*/
|
|
2
12
|
export declare function CreditBalanceBadge({ balance, isLoading, onClick, className, }: CreditBalanceBadgeProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Renders a small inline badge showing the user's credit balance.
|
|
4
|
+
* Blue when balance > 0, red when balance is 0. Returns null when balance is null.
|
|
5
|
+
* @param props - See {@link CreditBalanceBadgeProps} for full prop documentation.
|
|
6
|
+
*/
|
|
2
7
|
export function CreditBalanceBadge({ balance, isLoading, onClick, className, }) {
|
|
3
8
|
if (isLoading) {
|
|
4
9
|
return (_jsx("span", { className: `inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium text-gray-400 ${className || ""}`, children: _jsx("span", { className: "animate-pulse", children: "..." }) }));
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Credit store page component displaying the user's balance and
|
|
3
|
+
* a responsive grid of purchasable credit packages. Purely presentational --
|
|
4
|
+
* all data and callbacks are passed via props.
|
|
5
|
+
*/
|
|
1
6
|
import type { CreditStorePageProps } from "./types";
|
|
7
|
+
/**
|
|
8
|
+
* Renders a credit store with balance display, purchase packages grid,
|
|
9
|
+
* loading/error states, and a login prompt for unauthenticated users.
|
|
10
|
+
* @param props - See {@link CreditStorePageProps} for full prop documentation.
|
|
11
|
+
*/
|
|
2
12
|
export declare function CreditStorePage({ isAuthenticated, balance, packages, isLoading, isPurchasing, error, onPurchase, onLoginClick, labels, formatters, className, }: CreditStorePageProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/CreditStorePage.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Renders a credit store with balance display, purchase packages grid,
|
|
4
|
+
* loading/error states, and a login prompt for unauthenticated users.
|
|
5
|
+
* @param props - See {@link CreditStorePageProps} for full prop documentation.
|
|
6
|
+
*/
|
|
2
7
|
export function CreditStorePage({ isAuthenticated, balance, packages, isLoading, isPurchasing, error, onPurchase, onLoginClick, labels, formatters, className, }) {
|
|
3
8
|
return (_jsxs("div", { className: className, children: [_jsx("h1", { className: "text-2xl font-bold mb-6", children: labels.title }), isAuthenticated && balance !== null && (_jsxs("div", { className: "mb-8 p-4 bg-blue-50 rounded-lg border border-blue-200", children: [_jsx("p", { className: "text-sm text-blue-600 font-medium", children: labels.currentBalanceLabel }), _jsx("p", { className: "text-3xl font-bold text-blue-900", children: formatters.formatCredits(balance) })] })), error && (_jsxs("div", { className: "mb-6 p-4 bg-red-50 rounded-lg border border-red-200", children: [_jsx("p", { className: "text-sm font-medium text-red-800", children: labels.errorTitle }), _jsx("p", { className: "text-sm text-red-600", children: error })] })), !isAuthenticated && (_jsxs("div", { className: "mb-6 p-4 bg-yellow-50 rounded-lg border border-yellow-200", children: [_jsx("p", { className: "text-sm text-yellow-800", children: labels.loginRequired }), _jsx("button", { onClick: onLoginClick, className: "mt-2 px-4 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700", children: "Log in" })] })), isLoading && (_jsx("div", { className: "flex justify-center py-12", children: _jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }) })), !isLoading && packages.length === 0 && (_jsx("p", { className: "text-gray-500 text-center py-8", children: labels.noProducts })), !isLoading && packages.length > 0 && (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: packages.map((pkg) => (_jsx("div", { className: "p-6 bg-white rounded-xl border border-gray-200 shadow-sm hover:shadow-md transition-shadow", children: _jsxs("div", { className: "text-center", children: [_jsx("p", { className: "text-3xl font-bold text-gray-900", children: formatters.formatCredits(pkg.credits) }), formatters.getPackageDescription && (_jsx("p", { className: "text-sm text-gray-500 mt-1", children: formatters.getPackageDescription(pkg.packageId) })), _jsx("p", { className: "text-xl font-semibold text-blue-600 mt-3", children: pkg.priceString }), _jsx("button", { onClick: () => onPurchase(pkg.packageId), disabled: isPurchasing || !isAuthenticated, className: "mt-4 w-full px-4 py-2.5 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", children: isPurchasing
|
|
4
9
|
? labels.purchasingButton
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Purchase history page component with responsive table (desktop)
|
|
3
|
+
* and card (mobile) layouts. Supports load-more pagination.
|
|
4
|
+
*/
|
|
1
5
|
import type { PurchaseHistoryPageProps } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Renders a paginated list of purchase records.
|
|
8
|
+
* Desktop: table with date, credits, source, and amount columns.
|
|
9
|
+
* Mobile: compact card layout.
|
|
10
|
+
* @param props - See {@link PurchaseHistoryPageProps} for full prop documentation.
|
|
11
|
+
*/
|
|
2
12
|
export declare function PurchaseHistoryPage({ purchases, isLoading, error, onLoadMore, hasMore, labels, formatters, className, }: PurchaseHistoryPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Renders a paginated list of purchase records.
|
|
4
|
+
* Desktop: table with date, credits, source, and amount columns.
|
|
5
|
+
* Mobile: compact card layout.
|
|
6
|
+
* @param props - See {@link PurchaseHistoryPageProps} for full prop documentation.
|
|
7
|
+
*/
|
|
2
8
|
export function PurchaseHistoryPage({ purchases, isLoading, error, onLoadMore, hasMore, labels, formatters, className, }) {
|
|
3
9
|
return (_jsxs("div", { className: className, children: [_jsx("h1", { className: "text-2xl font-bold mb-6", children: labels.title }), error && (_jsx("div", { className: "mb-4 p-3 bg-red-50 rounded-lg border border-red-200", children: _jsx("p", { className: "text-sm text-red-600", children: error }) })), isLoading && (_jsx("div", { className: "flex justify-center py-12", children: _jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }) })), !isLoading && purchases.length === 0 && (_jsx("p", { className: "text-gray-500 text-center py-8", children: labels.noRecords })), !isLoading && purchases.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden sm:block overflow-x-auto", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-gray-200", children: [_jsx("th", { className: "text-left py-3 px-4 font-medium text-gray-500", children: labels.columnDate }), _jsx("th", { className: "text-right py-3 px-4 font-medium text-gray-500", children: labels.columnCredits }), _jsx("th", { className: "text-left py-3 px-4 font-medium text-gray-500", children: labels.columnSource }), _jsx("th", { className: "text-right py-3 px-4 font-medium text-gray-500", children: labels.columnAmount })] }) }), _jsx("tbody", { children: purchases.map((purchase) => (_jsxs("tr", { className: "border-b border-gray-100 hover:bg-gray-50", children: [_jsx("td", { className: "py-3 px-4 text-gray-700", children: formatters.formatDate(purchase.created_at) }), _jsxs("td", { className: "py-3 px-4 text-right font-medium text-green-600", children: ["+", purchase.credits] }), _jsx("td", { className: "py-3 px-4 text-gray-600", children: formatters.formatSource(purchase.source) }), _jsx("td", { className: "py-3 px-4 text-right text-gray-600", children: purchase.price_cents != null && purchase.currency
|
|
4
10
|
? formatters.formatAmount(purchase.price_cents, purchase.currency)
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Usage history page component with responsive table (desktop)
|
|
3
|
+
* and card (mobile) layouts. Supports load-more pagination.
|
|
4
|
+
*/
|
|
1
5
|
import type { UsageHistoryPageProps } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Renders a paginated list of usage records.
|
|
8
|
+
* Desktop: table with date and filename columns.
|
|
9
|
+
* Mobile: compact card layout.
|
|
10
|
+
* @param props - See {@link UsageHistoryPageProps} for full prop documentation.
|
|
11
|
+
*/
|
|
2
12
|
export declare function UsageHistoryPage({ usages, isLoading, error, onLoadMore, hasMore, labels, formatters, className, }: UsageHistoryPageProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/UsageHistoryPage.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Renders a paginated list of usage records.
|
|
4
|
+
* Desktop: table with date and filename columns.
|
|
5
|
+
* Mobile: compact card layout.
|
|
6
|
+
* @param props - See {@link UsageHistoryPageProps} for full prop documentation.
|
|
7
|
+
*/
|
|
2
8
|
export function UsageHistoryPage({ usages, isLoading, error, onLoadMore, hasMore, labels, formatters, className, }) {
|
|
3
9
|
return (_jsxs("div", { className: className, children: [_jsx("h1", { className: "text-2xl font-bold mb-6", children: labels.title }), error && (_jsx("div", { className: "mb-4 p-3 bg-red-50 rounded-lg border border-red-200", children: _jsx("p", { className: "text-sm text-red-600", children: error }) })), isLoading && (_jsx("div", { className: "flex justify-center py-12", children: _jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }) })), !isLoading && usages.length === 0 && (_jsx("p", { className: "text-gray-500 text-center py-8", children: labels.noRecords })), !isLoading && usages.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden sm:block overflow-x-auto", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-gray-200", children: [_jsx("th", { className: "text-left py-3 px-4 font-medium text-gray-500", children: labels.columnDate }), _jsx("th", { className: "text-left py-3 px-4 font-medium text-gray-500", children: labels.columnFilename })] }) }), _jsx("tbody", { children: usages.map((usage) => (_jsxs("tr", { className: "border-b border-gray-100 hover:bg-gray-50", children: [_jsx("td", { className: "py-3 px-4 text-gray-700", children: formatters.formatDate(usage.created_at) }), _jsx("td", { className: "py-3 px-4 text-gray-600", children: usage.filename || "-" })] }, usage.id))) })] }) }), _jsx("div", { className: "sm:hidden space-y-3", children: usages.map((usage) => (_jsxs("div", { className: "p-4 bg-white rounded-lg border border-gray-200", children: [_jsx("p", { className: "text-sm text-gray-500", children: formatters.formatDate(usage.created_at) }), _jsx("p", { className: "text-sm text-gray-700 font-medium", children: usage.filename || "-" })] }, usage.id))) }), hasMore && onLoadMore && (_jsx("div", { className: "mt-4 text-center", children: _jsx("button", { onClick: onLoadMore, className: "px-4 py-2 text-sm text-blue-600 hover:text-blue-800 font-medium", children: labels.loadMore }) }))] }))] }));
|
|
4
10
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type definitions for all consumables page components.
|
|
3
|
+
* Defines Labels, Formatters, and Props interfaces for CreditStorePage,
|
|
4
|
+
* PurchaseHistoryPage, UsageHistoryPage, and CreditBalanceBadge.
|
|
5
|
+
* All user-facing strings are defined via Labels for i18n support.
|
|
6
|
+
*/
|
|
1
7
|
import type { CreditPackage } from "@sudobility/consumables_client";
|
|
2
8
|
import type { ConsumablePurchaseRecord, ConsumableUsageRecord } from "@sudobility/types";
|
|
9
|
+
/** Localizable label strings for the CreditStorePage component. */
|
|
3
10
|
export interface CreditStorePageLabels {
|
|
4
11
|
title: string;
|
|
5
12
|
currentBalanceLabel: string;
|
|
@@ -10,10 +17,12 @@ export interface CreditStorePageLabels {
|
|
|
10
17
|
errorTitle: string;
|
|
11
18
|
loginRequired: string;
|
|
12
19
|
}
|
|
20
|
+
/** Formatting functions for the CreditStorePage component. */
|
|
13
21
|
export interface CreditStorePageFormatters {
|
|
14
22
|
formatCredits: (count: number) => string;
|
|
15
23
|
getPackageDescription?: (packageId: string) => string;
|
|
16
24
|
}
|
|
25
|
+
/** Props for the CreditStorePage component. */
|
|
17
26
|
export interface CreditStorePageProps {
|
|
18
27
|
isAuthenticated: boolean;
|
|
19
28
|
balance: number | null;
|
|
@@ -27,6 +36,7 @@ export interface CreditStorePageProps {
|
|
|
27
36
|
formatters: CreditStorePageFormatters;
|
|
28
37
|
className?: string;
|
|
29
38
|
}
|
|
39
|
+
/** Localizable label strings for the PurchaseHistoryPage component. */
|
|
30
40
|
export interface PurchaseHistoryPageLabels {
|
|
31
41
|
title: string;
|
|
32
42
|
columnDate: string;
|
|
@@ -37,11 +47,13 @@ export interface PurchaseHistoryPageLabels {
|
|
|
37
47
|
noRecords: string;
|
|
38
48
|
loadMore: string;
|
|
39
49
|
}
|
|
50
|
+
/** Formatting functions for the PurchaseHistoryPage component. */
|
|
40
51
|
export interface PurchaseHistoryPageFormatters {
|
|
41
52
|
formatDate: (dateStr: string) => string;
|
|
42
53
|
formatAmount: (cents: number, currency: string) => string;
|
|
43
54
|
formatSource: (source: string) => string;
|
|
44
55
|
}
|
|
56
|
+
/** Props for the PurchaseHistoryPage component. */
|
|
45
57
|
export interface PurchaseHistoryPageProps {
|
|
46
58
|
purchases: ConsumablePurchaseRecord[];
|
|
47
59
|
isLoading: boolean;
|
|
@@ -52,6 +64,7 @@ export interface PurchaseHistoryPageProps {
|
|
|
52
64
|
formatters: PurchaseHistoryPageFormatters;
|
|
53
65
|
className?: string;
|
|
54
66
|
}
|
|
67
|
+
/** Localizable label strings for the UsageHistoryPage component. */
|
|
55
68
|
export interface UsageHistoryPageLabels {
|
|
56
69
|
title: string;
|
|
57
70
|
columnDate: string;
|
|
@@ -59,9 +72,11 @@ export interface UsageHistoryPageLabels {
|
|
|
59
72
|
noRecords: string;
|
|
60
73
|
loadMore: string;
|
|
61
74
|
}
|
|
75
|
+
/** Formatting functions for the UsageHistoryPage component. */
|
|
62
76
|
export interface UsageHistoryPageFormatters {
|
|
63
77
|
formatDate: (dateStr: string) => string;
|
|
64
78
|
}
|
|
79
|
+
/** Props for the UsageHistoryPage component. */
|
|
65
80
|
export interface UsageHistoryPageProps {
|
|
66
81
|
usages: ConsumableUsageRecord[];
|
|
67
82
|
isLoading: boolean;
|
|
@@ -72,6 +87,7 @@ export interface UsageHistoryPageProps {
|
|
|
72
87
|
formatters: UsageHistoryPageFormatters;
|
|
73
88
|
className?: string;
|
|
74
89
|
}
|
|
90
|
+
/** Props for the CreditBalanceBadge component. */
|
|
75
91
|
export interface CreditBalanceBadgeProps {
|
|
76
92
|
balance: number | null;
|
|
77
93
|
isLoading: boolean;
|
package/dist/types.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type definitions for all consumables page components.
|
|
3
|
+
* Defines Labels, Formatters, and Props interfaces for CreditStorePage,
|
|
4
|
+
* PurchaseHistoryPage, UsageHistoryPage, and CreditBalanceBadge.
|
|
5
|
+
* All user-facing strings are defined via Labels for i18n support.
|
|
6
|
+
*/
|
|
1
7
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudobility/consumables_pages",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Web UI components for consumable credits (credit store, purchase history, usage history)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
"prepublishOnly": "bun run build"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@sudobility/consumables_client": "^0.0.
|
|
33
|
-
"@sudobility/types": "^1.9.
|
|
32
|
+
"@sudobility/consumables_client": "^0.0.8",
|
|
33
|
+
"@sudobility/types": "^1.9.54",
|
|
34
34
|
"react": "^18.0.0 || ^19.0.0",
|
|
35
35
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@sudobility/consumables_client": "^0.0.
|
|
38
|
+
"@sudobility/consumables_client": "^0.0.8",
|
|
39
39
|
"@testing-library/jest-dom": "^6.9.1",
|
|
40
40
|
"@testing-library/react": "^16.3.2",
|
|
41
41
|
"@types/bun": "^1.2.8",
|