mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
## Summary - Show a `ShimmeringLoader` skeleton in the new-org form while the creation preview is fetching for the first time, so users see feedback after entering their billing address. - Disable the **Create organization** button while the preview is refetching, to prevent submitting on stale totals. - Replace the inline charge summary with the shared `ChargeBreakdown` component, extending it with an optional `subtotalLabel` prop (defaults to `"Subtotal"`, `"Plan price"` here) to preserve the existing copy. ## Test plan - [ ] Navigate to `/new` → pick Pro/Team → enter a billing address → confirm shimmer shows until the first preview resolves. - [ ] Change address/tax ID → confirm existing totals fade to 50% while refetching and the submit button is disabled during the fetch. - [ ] Confirm the breakdown still renders "Plan price", "Tax (x%)", and "Total due today" correctly - [ ] FREE plan path unaffected — no preview request, submit button behaves as before. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Organization creation form now displays loading placeholders while billing preview data is being fetched, providing clearer visual feedback during the calculation process * Submit button is now properly disabled during billing information retrieval * Billing breakdown display has been refined for improved consistency <!-- end of auto-generated comment: release notes by coderabbit.ai -->
61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import { cn } from 'ui'
|
|
|
|
import { formatCurrency } from '@/lib/helpers'
|
|
|
|
export interface ChargeBreakdownProps {
|
|
subtotal: number
|
|
subtotalLabel?: string
|
|
total: number
|
|
tax?: { amount: number; percentage: number }
|
|
taxStatus?: 'calculated' | 'failed' | 'not_applicable'
|
|
isFetching: boolean
|
|
}
|
|
|
|
export const ChargeBreakdown = ({
|
|
subtotal,
|
|
subtotalLabel = 'Subtotal',
|
|
total,
|
|
tax,
|
|
taxStatus,
|
|
isFetching,
|
|
}: ChargeBreakdownProps) => {
|
|
return (
|
|
<div
|
|
className={cn('text-foreground-light text-sm transition-opacity', isFetching && 'opacity-50')}
|
|
>
|
|
{total !== subtotal && (
|
|
<div className="flex items-center justify-between gap-2 border-b border-muted text-sm">
|
|
<div className="py-2">{subtotalLabel}</div>
|
|
<div className="py-2 text-right tabular-nums" translate="no">
|
|
{formatCurrency(subtotal)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{taxStatus === 'calculated' && tax && tax.amount > 0 && (
|
|
<div className="flex items-center justify-between gap-2 border-b border-muted text-sm">
|
|
<div className="py-2">Tax ({tax.percentage}%)</div>
|
|
<div className="py-2 text-right tabular-nums" translate="no">
|
|
{formatCurrency(tax.amount)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{taxStatus === 'failed' && (
|
|
<div className="flex items-center justify-between gap-2 border-b border-muted text-sm">
|
|
<div className="py-2 text-foreground-lighter">
|
|
Tax could not be estimated and may be applied separately
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex items-center justify-between gap-2 text-foreground text-base">
|
|
<div className="py-2">Total due today</div>
|
|
<div className="py-2 text-right tabular-nums" translate="no">
|
|
{formatCurrency(total)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|