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
4 changes: 2 additions & 2 deletions web/sdk/admin/views/organizations/details/apis/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
DEFAULT_PAGE_SIZE,
} from "~/utils/connect-pagination";
import { transformDataTableQueryToRQLRequest } from "~/utils/transform-query";
import { useDebounceValue } from "usehooks-ts";
import { useDebouncedValue } from "~hooks";
import { useTerminology } from "../../../../hooks/useTerminology";

const NoCredentials = () => {
Expand Down Expand Up @@ -81,7 +81,7 @@ export function OrganizationApisView() {
};
}, [tableQuery, searchQuery]);

const [query] = useDebounceValue(computedQuery, 200);
const query = useDebouncedValue(computedQuery, 200);

const [selectedServiceUser, setSelectedServiceUser] =
useState<SearchOrganizationServiceUsersResponse_OrganizationServiceUser | null>(
Expand Down
4 changes: 2 additions & 2 deletions web/sdk/admin/views/organizations/details/invoices/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
getGroupCountMapFromFirstPage,
} from "~/utils/connect-pagination";
import { transformDataTableQueryToRQLRequest } from "~/utils/transform-query";
import { useDebounceValue } from "usehooks-ts";
import { useDebouncedValue } from "~hooks";
import { useTerminology } from "../../../../hooks/useTerminology";

const DEFAULT_SORT: DataTableSort = { name: 'createdAt', order: 'desc' };
Expand Down Expand Up @@ -111,7 +111,7 @@ export function OrganizationInvoicesView() {
};
}, [tableQuery, searchQuery]);

const [query] = useDebounceValue(computedQuery, 200);
const query = useDebouncedValue(computedQuery, 200);

const {
data: infiniteData,
Expand Down
4 changes: 2 additions & 2 deletions web/sdk/admin/views/organizations/details/members/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
DEFAULT_PAGE_SIZE
} from '~/utils/connect-pagination';
import { transformDataTableQueryToRQLRequest } from '~/utils/transform-query';
import { useDebounceValue } from 'usehooks-ts';
import { useDebouncedValue } from '~hooks';

const updateRoleDialogHandle = AlertDialog.createHandle<UpdateRolePayload>();

Expand Down Expand Up @@ -97,7 +97,7 @@ export function OrganizationMembersView() {
};
}, [tableQuery, searchQuery]);

const [query] = useDebounceValue(computedQuery, 200);
const query = useDebouncedValue(computedQuery, 200);

const {
data: infiniteData,
Expand Down
4 changes: 2 additions & 2 deletions web/sdk/admin/views/organizations/details/pat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
type Project,
type SearchOrganizationPATsResponse_OrganizationPAT,
} from "@raystack/proton/frontier";
import { useDebounceValue } from "usehooks-ts";
import { useDebouncedValue } from "~hooks";
import { OrganizationContext } from "../contexts/organization-context";
import { PageTitle } from "~/admin/components/PageTitle";
import {
Expand Down Expand Up @@ -106,7 +106,7 @@ export function OrganizationPatView() {
};
}, [tableQuery, searchQuery]);

const [query] = useDebounceValue(computedQuery, 200);
const query = useDebouncedValue(computedQuery, 200);

const {
data: infiniteData,
Expand Down
4 changes: 2 additions & 2 deletions web/sdk/admin/views/organizations/details/projects/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
DEFAULT_PAGE_SIZE
} from '~/utils/connect-pagination';
import { transformDataTableQueryToRQLRequest } from '~/utils/transform-query';
import { useDebounceValue } from 'usehooks-ts';
import { useDebouncedValue } from '~hooks';
import { useTerminology } from "../../../../hooks/useTerminology";

const DEFAULT_SORT: DataTableSort = { name: 'createdAt', order: 'desc' };
Expand Down Expand Up @@ -95,7 +95,7 @@ export function OrganizationProjectsView() {
};
}, [tableQuery, searchQuery]);

const [query] = useDebounceValue(computedQuery, 200);
const query = useDebouncedValue(computedQuery, 200);

const {
data: infiniteData,
Expand Down
4 changes: 2 additions & 2 deletions web/sdk/admin/views/organizations/details/tokens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useInfiniteQuery } from "@connectrpc/connect-query";
import { getConnectNextPageParam, DEFAULT_PAGE_SIZE } from "~/utils/connect-pagination";
import { transformDataTableQueryToRQLRequest } from "~/utils/transform-query";
import { getColumns } from "./columns";
import { useDebounceValue } from "usehooks-ts";
import { useDebouncedValue } from "~hooks";
import { useTerminology } from "../../../../hooks/useTerminology";

const DEFAULT_SORT: DataTableSort = { name: 'createdAt', order: 'desc' };
Expand Down Expand Up @@ -82,7 +82,7 @@ export function OrganizationTokensView() {
};
}, [tableQuery, searchQuery]);

const [query] = useDebounceValue(computedQuery, 200);
const query = useDebouncedValue(computedQuery, 200);

const {
data: infiniteData,
Expand Down
84 changes: 84 additions & 0 deletions web/sdk/client/hooks/useOrganizationInvoices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useMemo } from 'react';
import { useInfiniteQuery } from '@connectrpc/connect-query';
import { FrontierServiceQueries } from '@raystack/proton/frontier';
import type {
RQLRequest,
SearchOrganizationInvoicesResponse_OrganizationInvoice
} from '@raystack/proton/frontier';
import { useFrontier } from '../contexts/FrontierContext';
import {
getConnectNextPageParam,
getGroupCountMapFromFirstPage
} from '../utils/connect-pagination';

export interface UseOrganizationInvoicesOptions {
query: RQLRequest;
enabled?: boolean;
}

export interface UseOrganizationInvoicesReturn {
invoices: SearchOrganizationInvoicesResponse_OrganizationInvoice[];
groupCountMap: Record<string, Record<string, number>>;
isLoading: boolean;
isFetchingNextPage: boolean;
fetchNextPage: () => Promise<unknown>;
hasNextPage: boolean;
isError: boolean;
error: Error | null;
}

/**
* Common data source for organization invoices, backed by the
* `SearchOrganizationInvoices` RPC as a paginated infinite query.
*/
export function useOrganizationInvoices({
query,
enabled = true
}: UseOrganizationInvoicesOptions): UseOrganizationInvoicesReturn {
const { activeOrganization } = useFrontier();
const organizationId = activeOrganization?.id || '';

const {
data: infiniteData,
isLoading,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
isError,
error
} = useInfiniteQuery(
FrontierServiceQueries.searchOrganizationInvoices,
{ id: organizationId, query },
{
enabled: !!organizationId && enabled,
pageParamKey: 'query',
getNextPageParam: lastPage =>
getConnectNextPageParam(lastPage, { query }, 'organizationInvoices'),
staleTime: 0,
refetchOnWindowFocus: false,
retry: 1,
retryDelay: 1000
}
);

const invoices = useMemo(
() => infiniteData?.pages?.flatMap(page => page.organizationInvoices) ?? [],
[infiniteData]
);

const groupCountMap = useMemo(
() => (infiniteData ? getGroupCountMapFromFirstPage(infiniteData) : {}),
[infiniteData]
);

return {
invoices,
groupCountMap,
isLoading,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
isError,
error
};
}
38 changes: 3 additions & 35 deletions web/sdk/client/views/billing/billing-view.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
'use client';

import { useCallback, useEffect, useMemo } from 'react';
import { useCallback } from 'react';
import qs from 'query-string';
import { Flex, Dialog, EmptyState, toastManager } from '@raystack/apsara';
import {
CreateCheckoutRequestSchema,
ListInvoicesRequestSchema,
FrontierServiceQueries
} from '@raystack/proton/frontier';
import {
useMutation,
useQuery as useConnectQuery
} from '@connectrpc/connect-query';
import { useMutation } from '@connectrpc/connect-query';
import { create } from '@bufbuild/protobuf';
import { useFrontier } from '../../contexts/FrontierContext';
import { useBillingPermission } from '../../hooks/useBillingPermission';
Expand Down Expand Up @@ -55,37 +51,9 @@ export function BillingView({ onNavigateToPlans }: BillingViewProps) {
const isPermissionsLoading = !activeOrganization?.id || isFetching;
const hasNoAccess = !canSeeBilling && !isPermissionsLoading;

const {
data: invoicesData,
isLoading: isInvoicesLoading,
error: invoicesError
} = useConnectQuery(
FrontierServiceQueries.listInvoices,
create(ListInvoicesRequestSchema, {
orgId: activeOrganization?.id || '',
nonzeroAmountOnly: true
}),
{
enabled: !!activeOrganization?.id && canSeeBilling
}
);

const invoices = useMemo(() => invoicesData?.invoices || [], [invoicesData]);

useEffect(() => {
if (invoicesError) {
toastManager.add({
title: 'Failed to load invoices',
description: invoicesError?.message,
type: 'error'
});
}
}, [invoicesError]);

const isLoading = !activeOrganization?.id ||
isBillingAccountLoading ||
isActiveSubscriptionLoading ||
isInvoicesLoading ||
isFetching ||
isOrganizationKycLoading;

Expand Down Expand Up @@ -175,7 +143,7 @@ export function BillingView({ onNavigateToPlans }: BillingViewProps) {
<PaymentIssue
isLoading={isLoading}
subscription={activeSubscription}
invoices={invoices}
hasAccess={canSeeBilling}
/>

<UpcomingPlanChangeBanner
Expand Down
46 changes: 8 additions & 38 deletions web/sdk/client/views/billing/components/invoices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,12 @@ import type {
import {
ExclamationTriangleIcon,
} from '@radix-ui/react-icons';
import { useInfiniteQuery } from '@connectrpc/connect-query';
import {
FrontierServiceQueries,
type SearchOrganizationInvoicesResponse_OrganizationInvoice
} from '@raystack/proton/frontier';
import { useDebounceValue } from 'usehooks-ts';
import { type SearchOrganizationInvoicesResponse_OrganizationInvoice } from '@raystack/proton/frontier';
import { useDebouncedValue } from '~hooks';
import { useFrontier } from '../../../contexts/FrontierContext';
import { useOrganizationInvoices } from '../../../hooks/useOrganizationInvoices';
import { DEFAULT_DATE_FORMAT, INVOICE_STATES } from '../../../utils/constants';
import {
DEFAULT_PAGE_SIZE,
getConnectNextPageParam,
getGroupCountMapFromFirstPage
} from '../../../utils/connect-pagination';
import { DEFAULT_PAGE_SIZE } from '../../../utils/connect-pagination';
import { transformDataTableQueryToRQLRequest } from '../../../utils/transform-query';
import { timestampToDayjs, type TimeStamp } from '../../../../utils/timestamp';
import { capitalize } from '../../../../utils';
Expand Down Expand Up @@ -154,7 +147,6 @@ const ErrorState = () => (

export function Invoices() {
const { activeOrganization, config } = useFrontier();
const organizationId = activeOrganization?.id || '';

const [tableQuery, setTableQuery] = useState<DataTableQuery>(INITIAL_QUERY);

Expand All @@ -163,35 +155,18 @@ export function Invoices() {
[tableQuery]
);

const [query] = useDebounceValue(computedQuery, 200);
const query = useDebouncedValue(computedQuery, 200);

const {
data: infiniteData,
invoices,
groupCountMap,
isLoading,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
isError
} = useInfiniteQuery(
FrontierServiceQueries.searchOrganizationInvoices,
{ id: organizationId, query },
{
enabled: !!organizationId,
pageParamKey: 'query',
getNextPageParam: lastPage =>
getConnectNextPageParam(lastPage, { query }, 'organizationInvoices'),
staleTime: 0,
refetchOnWindowFocus: false,
retry: 1,
retryDelay: 1000
}
);
} = useOrganizationInvoices({ query });

const invoices = useMemo(
() =>
infiniteData?.pages?.flatMap(page => page.organizationInvoices) ?? [],
[infiniteData]
);
const loading = (!activeOrganization?.id || isLoading || isFetchingNextPage) && !isError;

const onTableQueryChange = (newQuery: DataTableQuery) => {
Expand All @@ -204,11 +179,6 @@ export function Invoices() {
}
};

const groupCountMap = useMemo(
() => (infiniteData ? getGroupCountMapFromFirstPage(infiniteData) : {}),
[infiniteData]
);

const columns = getColumns({
dateFormat: config?.dateFormat || DEFAULT_DATE_FORMAT,
groupCountMap
Expand Down
Loading
Loading