import { PermissionAction } from '@supabase/shared-types/out/constants' import clsx from 'clsx' import dayjs from 'dayjs' import { ExternalLink, Info } from 'lucide-react' import Link from 'next/link' import { useEffect, useMemo, useState } from 'react' import { useParams } from 'common' import { ScaffoldContainer, ScaffoldContainerLegacy } from 'components/layouts/Scaffold' import DateRangePicker from 'components/to-be-cleaned/DateRangePicker' import AlertError from 'components/ui/AlertError' import InformationBox from 'components/ui/InformationBox' import NoPermission from 'components/ui/NoPermission' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useProjectsQuery } from 'data/projects/projects-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' import { TIME_PERIODS_BILLING, TIME_PERIODS_REPORTS } from 'lib/constants/metrics' import { Button, Listbox } from 'ui' import { Restriction } from '../BillingSettings/Restriction' import Activity from './Activity' import Bandwidth from './Bandwidth' import Compute from './Compute' import SizeAndCounts from './SizeAndCounts' import TotalUsage from './TotalUsage' const Usage = () => { const { slug, projectRef } = useParams() const [dateRange, setDateRange] = useState() const [selectedProjectRef, setSelectedProjectRef] = useState() const canReadSubscriptions = useCheckPermissions( PermissionAction.BILLING_READ, 'stripe.subscriptions' ) const organization = useSelectedOrganization() const { data: projects, isSuccess } = useProjectsQuery() const { data: subscription, error: subscriptionError, isLoading: isLoadingSubscription, isError: isErrorSubscription, isSuccess: isSuccessSubscription, } = useOrgSubscriptionQuery({ orgSlug: slug }) const orgProjects = projects?.filter((project) => project.organization_id === organization?.id) useEffect(() => { if (projectRef && isSuccess && orgProjects !== undefined) { if (orgProjects.find((project) => project.ref === projectRef)) { setSelectedProjectRef(projectRef) } } // [Joshen] Since we're already looking at isSuccess // eslint-disable-next-line react-hooks/exhaustive-deps }, [projectRef, isSuccess]) const billingCycleStart = dayjs.unix(subscription?.current_period_start ?? 0).utc() const billingCycleEnd = dayjs.unix(subscription?.current_period_end ?? 0).utc() const currentBillingCycleSelected = useMemo(() => { // Selected by default if (!dateRange?.period_start || !dateRange?.period_end || !subscription) return true const { current_period_start, current_period_end } = subscription return ( dayjs(dateRange.period_start.date).isSame(new Date(current_period_start * 1000)) && dayjs(dateRange.period_end.date).isSame(new Date(current_period_end * 1000)) ) }, [dateRange, subscription]) const startDate = useMemo(() => { // If end date is in future, set end date to now if (!dateRange?.period_start?.date) { return undefined } else { // LF seems to have an issue with the milliseconds, causes infinite loading sometimes return new Date(dateRange?.period_start?.date).toISOString().slice(0, -5) + 'Z' } // eslint-disable-next-line react-hooks/exhaustive-deps }, [dateRange, subscription]) const endDate = useMemo(() => { // If end date is in future, set end date to end of current day if (dateRange?.period_end?.date && dayjs(dateRange.period_end.date).isAfter(dayjs())) { // LF seems to have an issue with the milliseconds, causes infinite loading sometimes // In order to have full days from Prometheus metrics when using 1d interval, // the time needs to be greater or equal than the time of the start date return dayjs().endOf('day').toISOString().slice(0, -5) + 'Z' } else if (dateRange?.period_end?.date) { // LF seems to have an issue with the milliseconds, causes infinite loading sometimes return new Date(dateRange.period_end.date).toISOString().slice(0, -5) + 'Z' } // eslint-disable-next-line react-hooks/exhaustive-deps }, [dateRange, subscription]) const selectedProject = selectedProjectRef ? orgProjects?.find((it) => it.ref === selectedProjectRef) : undefined if (!canReadSubscriptions) { return ( ) } return ( <>
{isLoadingSubscription && } {isErrorSubscription && ( )} {isSuccessSubscription && ( <> { if (value === 'all-projects') setSelectedProjectRef(undefined) else setSelectedProjectRef(value) }} > All projects {orgProjects?.map((project) => ( {project.name} ))}

Organization is on the {subscription.plan.name} plan

{billingCycleStart.format('DD MMM YYYY')} -{' '} {billingCycleEnd.format('DD MMM YYYY')}

)}
{selectedProjectRef ? (

You are currently viewing usage for the " {selectedProject?.name || selectedProjectRef}" project. Since your organization is using the new organization-based billing, the included quota is for your whole organization and not just this project. For billing purposes, we sum up usage from all your projects. To view your usage quota, set the project filter above back to "All Projects".

} defaultVisibility hideCollapse icon={} />
) : ( )} {subscription?.plan.id !== 'free' && ( )} ) } export default Usage