Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/app/(dashboard)/[orgSlug]/billing/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export default function BillingPage() {
<div className="grid gap-4 sm:grid-cols-2">
<CurrentSpend
baseCost={usage?.base_cost ?? 0}
tokenCost={usage?.token_cost ?? 0}
totalCost={usage?.total_cost ?? 0}
creditBalance={credits?.credit_balance_eur}
autoTopupFailed={credits?.auto_topup_failed}
Expand Down
2 changes: 0 additions & 2 deletions src/components/billing/current-spend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ import { AlertTriangle } from 'lucide-react'

interface CurrentSpendProps {
baseCost: number
tokenCost: number
totalCost: number
creditBalance?: number
autoTopupFailed?: boolean
}

export function CurrentSpend({
baseCost,
tokenCost,
totalCost,
creditBalance,
autoTopupFailed,
Expand Down
15 changes: 7 additions & 8 deletions src/components/layout/sidebar-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ interface SidebarStateContextValue {
const SidebarStateContext = createContext<SidebarStateContextValue | null>(null)

export function SidebarStateProvider({ children }: { children: React.ReactNode }) {
const [collapsed, setCollapsed] = useState(false)
const [hydrated, setHydrated] = useState(false)

useEffect(() => {
const stored = window.localStorage.getItem(SIDEBAR_STORAGE_KEY)
if (stored === 'true') setCollapsed(true)
setHydrated(true)
}, [])
const [collapsed, setCollapsed] = useState(() => {
if (typeof window !== 'undefined') {
return window.localStorage.getItem(SIDEBAR_STORAGE_KEY) === 'true'
}
return false
})
const [hydrated] = useState(() => typeof window !== 'undefined')

useEffect(() => {
if (hydrated) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/credits/balance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ vi.mock('@/lib/db/schema', () => ({
import { getBalance, checkSufficientBalance, deductCredits, addCredits } from './balance'

function mockSelectChain(balance: string) {
const chain: Record<string, any> = {}
const chain: Record<string, unknown> = {}
chain.from = vi.fn(() => chain)
chain.where = vi.fn(() => chain)
chain.limit = vi.fn(() => Promise.resolve([{ balance }]))
Expand All @@ -35,7 +35,7 @@ describe('getBalance', () => {
})

it('returns 0 when no org found', async () => {
const chain: Record<string, any> = {}
const chain: Record<string, unknown> = {}
chain.from = vi.fn(() => chain)
chain.where = vi.fn(() => chain)
chain.limit = vi.fn(() => Promise.resolve([]))
Expand Down
2 changes: 1 addition & 1 deletion src/lib/credits/balance.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { db } from '@/lib/db'
import { organizations, creditTransactions } from '@/lib/db/schema'
import { organizations } from '@/lib/db/schema'
import { eq, sql } from 'drizzle-orm'

interface DeductMeta {
Expand Down
5 changes: 5 additions & 0 deletions src/lib/stripe/ensure-customer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ describe('ensureStripeCustomer', () => {

it('returns existing stripe_customer_id if valid in current mode', async () => {
const org = makeOrg({ stripe_customer_id: 'cus_existing' })
// eslint-disable-next-line @typescript-eslint/no-explicit-any
vi.mocked(stripe.customers.retrieve).mockResolvedValue({ id: 'cus_existing' } as any)
const result = await ensureStripeCustomer(org)

Expand All @@ -62,10 +63,12 @@ describe('ensureStripeCustomer', () => {
it('creates new customer if existing ID is from wrong Stripe mode', async () => {
const org = makeOrg({ stripe_customer_id: 'cus_live_mode_id' })
vi.mocked(stripe.customers.retrieve).mockRejectedValue(new Error('No such customer'))
// eslint-disable-next-line @typescript-eslint/no-explicit-any
vi.mocked(stripe.customers.create).mockResolvedValue({ id: 'cus_test_new' } as any)

const mockEq = vi.fn().mockResolvedValue({ data: null, error: null })
const mockUpdate = vi.fn(() => ({ eq: mockEq }))
// eslint-disable-next-line @typescript-eslint/no-explicit-any
vi.mocked(supabaseAdmin.from).mockReturnValue({ update: mockUpdate } as any)

const result = await ensureStripeCustomer(org)
Expand All @@ -76,10 +79,12 @@ describe('ensureStripeCustomer', () => {

it('creates a Stripe customer when none exists', async () => {
const org = makeOrg({ stripe_customer_id: null })
// eslint-disable-next-line @typescript-eslint/no-explicit-any
vi.mocked(stripe.customers.create).mockResolvedValue({ id: 'cus_new123' } as any)

const mockEq = vi.fn().mockResolvedValue({ data: null, error: null })
const mockUpdate = vi.fn(() => ({ eq: mockEq }))
// eslint-disable-next-line @typescript-eslint/no-explicit-any
vi.mocked(supabaseAdmin.from).mockReturnValue({ update: mockUpdate } as any)

const result = await ensureStripeCustomer(org)
Expand Down
6 changes: 4 additions & 2 deletions src/lib/stripe/webhooks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ vi.mock('@/lib/constants', () => ({

import { handleStripeEvent } from './webhooks'

function chainMock(returnValue: unknown) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function chainMock(returnValue: unknown): Record<string, any> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const chain: Record<string, any> = {}
const terminal = () => Promise.resolve(returnValue)
const methods = ['from', 'select', 'update', 'insert', 'eq', 'in', 'single', 'order', 'limit']
Expand Down Expand Up @@ -181,7 +183,7 @@ describe('handleStripeEvent', () => {
describe('payment_intent.succeeded', () => {
it('adds credits for credit_topup payment intents', async () => {
const txnChain = chainMock({ data: [], error: null })
txnChain.single = undefined as any
txnChain.single = undefined as unknown
txnChain.limit = vi.fn(() => Promise.resolve({ data: [], error: null }))
const orgChain = chainMock({ data: null, error: null })

Expand Down
2 changes: 1 addition & 1 deletion src/lib/stripe/webhooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ async function handlePaymentIntentFailed(pi: Stripe.PaymentIntent): Promise<void
.eq('id', orgId)
}

async function handleSubscriptionCreated(_sub: Stripe.Subscription): Promise<void> {
async function handleSubscriptionCreated(_sub: Stripe.Subscription): Promise<void> { // eslint-disable-line @typescript-eslint/no-unused-vars
// Instance creation is handled in handleCheckoutCompleted.
}

Expand Down
Loading