ReadReplicaPricingDialog.tsx117 lines · main
| 1 | import { |
| 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 | |
| 19 | import { useGetReplicaCost } from './useGetReplicaCost' |
| 20 | import { TaxDisclaimer } from '@/components/interfaces/Billing/TaxDisclaimer' |
| 21 | import { DocsButton } from '@/components/ui/DocsButton' |
| 22 | import { InlineLinkClassName } from '@/components/ui/InlineLink' |
| 23 | import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' |
| 24 | import { DOCS_URL } from '@/lib/constants' |
| 25 | |
| 26 | export 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 | } |