Phase 2 Task 33. Components can now ask "is this feature on?", "how many
sessions left?", and "what stage is the trial in?" without re-implementing
the read against useBillingStore.
- useFeature(flagKey): boolean — reads enabledFeatures from store
- useFeatureLimit(field): { used, limit, percentage, isAtLimit, isLoading }
with non-blocking 60s module-level cache and graceful 404 degradation
- useTrialBanner(): derives stage from subscription status + trial countdown,
returns null on initial load to prevent flicker
- usageApi.getCount(field) — calls /api/v1/usage/{field}; backend endpoint
is not yet implemented (planned), so the hook degrades to used=0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
24 lines
724 B
TypeScript
24 lines
724 B
TypeScript
import apiClient from './client'
|
|
|
|
/**
|
|
* Usage counters API.
|
|
*
|
|
* TODO: backend `/usage/{field}` endpoint not yet implemented (planned).
|
|
* Tracked under self-serve signup Phase 2 — Task 33 calls this lazily; today
|
|
* it 404s and the consuming hook (`useFeatureLimit`) cleanly degrades to
|
|
* `used = 0`.
|
|
*/
|
|
export const usageApi = {
|
|
/**
|
|
* Fetch the current count for a usage field (e.g. `active_users`,
|
|
* `flowpilot_sessions_this_month`). The field name is the same key used in
|
|
* `BillingState.planLimits`.
|
|
*/
|
|
async getCount(field: string): Promise<{ used: number }> {
|
|
const response = await apiClient.get<{ used: number }>(`/usage/${field}`)
|
|
return response.data
|
|
},
|
|
}
|
|
|
|
export default usageApi
|