ReadReplicaPricingDialog.tsx117 lines · main
1import {
2 cn,
3 Dialog,
4 DialogContent,
5 DialogFooter,
6 DialogHeader,
7 DialogSection,
8 DialogSectionSeparator,
9 DialogTitle,
10 DialogTrigger,
11 Table,
12 TableBody,
13 TableCell,
14 TableHead,
15 TableHeader,
16 TableRow,
17} from 'ui'
18
19import { useGetReplicaCost } from './useGetReplicaCost'
20import { TaxDisclaimer } from '@/components/interfaces/Billing/TaxDisclaimer'
21import { DocsButton } from '@/components/ui/DocsButton'
22import { InlineLinkClassName } from '@/components/ui/InlineLink'
23import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
24import { DOCS_URL } from '@/lib/constants'
25
26export const ReadReplicaPricingDialog = () => {
27 const { data: project } = useSelectedProjectQuery()
28 const { compute, disk, iops, throughput } = useGetReplicaCost()
29
30 const showNewDiskManagementUI = project?.cloud_provider === 'AWS'
31
32 return (
33 <Dialog>
34 <DialogTrigger asChild>
35 <button className={cn(InlineLinkClassName, 'text-sm text-foreground-light')}>
36 Learn more
37 </button>
38 </DialogTrigger>
39 <DialogContent
40 size={showNewDiskManagementUI ? 'medium' : 'small'}
41 aria-describedby={undefined}
42 >
43 <DialogHeader>
44 <DialogTitle>Calculating costs for a new read replica</DialogTitle>
45 </DialogHeader>
46 <DialogSectionSeparator />
47 <DialogSection>
48 {showNewDiskManagementUI ? (
49 <>
50 <p className="text-foreground-light text-sm mb-2">
51 Read replicas will match the compute size of your primary database and will include
52 25% more disk size than the primary database to accommodate WAL files.
53 </p>
54 <p className="text-foreground-light text-sm">
55 The additional cost for the replica breaks down to:
56 </p>
57 <Table>
58 <TableHeader className="font-mono uppercase text-xs [&_th]:h-auto [&_th]:pb-2 [&_th]:pt-4">
59 <TableRow>
60 <TableHead className="w-[140px] pl-0">Item</TableHead>
61 <TableHead>Description</TableHead>
62 <TableHead className="text-right pr-0">Cost (/month)</TableHead>
63 </TableRow>
64 </TableHeader>
65 <TableBody className="[&_td]:py-0 [&_tr]:h-[50px] [&_tr]:border-dotted">
66 <TableRow>
67 <TableCell className="pl-0">Compute size</TableCell>
68 <TableCell>{compute.label}</TableCell>
69 <TableCell className="text-right font-mono pr-0" translate="no">
70 {compute.cost}
71 </TableCell>
72 </TableRow>
73 <TableRow>
74 <TableCell className="pl-0">Disk size</TableCell>
75 <TableCell>{disk.label}</TableCell>
76 <TableCell className="text-right font-mono pr-0" translate="no">
77 {disk.cost}
78 </TableCell>
79 </TableRow>
80 <TableRow>
81 <TableCell className="pl-0">IOPS</TableCell>
82 <TableCell>{iops.label}</TableCell>
83 <TableCell className="text-right font-mono pr-0" translate="no">
84 {iops.cost}
85 </TableCell>
86 </TableRow>
87 {disk.type === 'gp3' && (
88 <TableRow>
89 <TableCell className="pl-0">Throughput</TableCell>
90 <TableCell>{throughput.label}</TableCell>
91 <TableCell className="text-right font-mono pr-0">{throughput.cost}</TableCell>
92 </TableRow>
93 )}
94 </TableBody>
95 </Table>
96 </>
97 ) : (
98 <p className="text-foreground-light text-sm">
99 Read replicas will be on the same compute size as your primary database. Deploying a
100 read replica on the <span className="text-foreground">{compute.label}</span> size
101 incurs additional{' '}
102 <span className="text-foreground" translate="no">
103 {compute?.priceDescription}
104 </span>
105 .
106 </p>
107 )}
108 <TaxDisclaimer className="mt-3" />
109 </DialogSection>
110
111 <DialogFooter>
112 <DocsButton href={`${DOCS_URL}/guides/platform/manage-your-usage/read-replicas`} />
113 </DialogFooter>
114 </DialogContent>
115 </Dialog>
116 )
117}