import { useMemo } from 'react' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import { useReplicationCostEstimateQuery } from '@/data/replication/cost-estimate-query' import { formatBytes, formatCurrency } from '@/lib/helpers' interface RestartCostEstimateProps { open: boolean projectRef?: string sourceId?: number publicationName?: string tableNames: string[] } interface EstimatedTable { schema: string name: string estimated_bytes: number estimated_cost: number is_row_filtered: boolean } export const calculateRestartCostEstimate = (tables: EstimatedTable[], tableNames: string[]) => { const tableNameSet = new Set(tableNames) const matchedTables = tables.filter((table) => tableNameSet.has(`${table.schema}.${table.name}`)) return { isComplete: matchedTables.length === tableNames.length, estimatedBytes: matchedTables.reduce((total, table) => total + table.estimated_bytes, 0), estimatedCost: matchedTables.reduce((total, table) => total + table.estimated_cost, 0), hasRowFilteredTables: matchedTables.some((table) => table.is_row_filtered), } } export const RestartCostEstimate = ({ open, projectRef, sourceId, publicationName, tableNames, }: RestartCostEstimateProps) => { const { data: estimate, isFetching } = useReplicationCostEstimateQuery( { projectRef, sourceId, publicationName }, { enabled: open } ) const restartEstimate = useMemo( () => estimate === undefined ? undefined : calculateRestartCostEstimate(estimate.table_copy.tables, tableNames), [estimate, tableNames] ) return (
Estimated additional initial sync
{formatBytes(restartEstimate.estimatedBytes)} across {tableNames.length}{' '} {tableNames.length === 1 ? 'table' : 'tables'}
A cost estimate is unavailable. You can still restart the{' '} {tableNames.length === 1 ? 'table' : 'tables'}.
)} {restartEstimate?.isComplete && restartEstimate.hasRowFilteredTables && (*Tables with row filters may cost less than shown.
)}