16 - Update frontend for cents-based API
This commit is contained in:
parent
d6f60ab987
commit
cf89ee7cd2
2 changed files with 32 additions and 16 deletions
|
|
@ -54,7 +54,7 @@ export default function IncomeDistributionPreview({ scenarioId }: IncomeDistribu
|
|||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': csrfToken(),
|
||||
},
|
||||
body: JSON.stringify({ amount: parsed }),
|
||||
body: JSON.stringify({ amount: Math.round(parsed * 100) }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -126,11 +126,11 @@ export default function IncomeDistributionPreview({ scenarioId }: IncomeDistribu
|
|||
</div>
|
||||
<div className="text-right">
|
||||
<span className="font-semibold text-gray-900">
|
||||
${allocation.allocated_amount.toFixed(2)}
|
||||
${(allocation.allocated_amount / 100).toFixed(2)}
|
||||
</span>
|
||||
{allocation.remaining_capacity !== null && (
|
||||
<span className="ml-2 text-sm text-gray-500">
|
||||
(${allocation.remaining_capacity.toFixed(2)} remaining)
|
||||
(${(allocation.remaining_capacity / 100).toFixed(2)} remaining)
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -143,13 +143,13 @@ export default function IncomeDistributionPreview({ scenarioId }: IncomeDistribu
|
|||
|
||||
<div className="flex justify-between rounded-md bg-gray-50 px-4 py-3 text-sm font-medium">
|
||||
<span className="text-gray-700">Total Allocated</span>
|
||||
<span className="text-gray-900">${preview.total_allocated.toFixed(2)}</span>
|
||||
<span className="text-gray-900">${(preview.total_allocated / 100).toFixed(2)}</span>
|
||||
</div>
|
||||
|
||||
{preview.unallocated > 0 && (
|
||||
<div className="flex justify-between rounded-md bg-amber-50 px-4 py-3 text-sm font-medium">
|
||||
<span className="text-amber-700">Unallocated</span>
|
||||
<span className="text-amber-900">${preview.unallocated.toFixed(2)}</span>
|
||||
<span className="text-amber-900">${(preview.unallocated / 100).toFixed(2)}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ interface Bucket {
|
|||
allocation_value: number | null;
|
||||
allocation_type_label: string;
|
||||
buffer_multiplier: number;
|
||||
effective_capacity: number;
|
||||
effective_capacity: number | null;
|
||||
starting_amount: number;
|
||||
current_balance: number;
|
||||
has_available_space: boolean;
|
||||
available_space: number;
|
||||
available_space: number | null;
|
||||
}
|
||||
|
||||
interface Stream {
|
||||
|
|
@ -76,11 +76,23 @@ const bucketTypeOptions = [
|
|||
{ value: 'want', label: 'Want' },
|
||||
];
|
||||
|
||||
/** Convert cents to dollars for display */
|
||||
const centsToDollars = (cents: number): number => cents / 100;
|
||||
|
||||
/** Convert dollars to cents for storage */
|
||||
const dollarsToCents = (dollars: number): number => Math.round(dollars * 100);
|
||||
|
||||
/** Convert basis points to percent for display */
|
||||
const basisPointsToPercent = (bp: number): number => bp / 100;
|
||||
|
||||
/** Convert percent to basis points for storage */
|
||||
const percentToBasisPoints = (pct: number): number => Math.round(pct * 100);
|
||||
|
||||
const formatAllocationValue = (bucket: Bucket): string => {
|
||||
if (bucket.allocation_type === 'unlimited') return 'All remaining';
|
||||
if (bucket.allocation_value === null) return '--';
|
||||
if (bucket.allocation_type === 'percentage') return `${Number(bucket.allocation_value).toFixed(2)}%`;
|
||||
return `$${Number(bucket.allocation_value).toFixed(2)}`;
|
||||
if (bucket.allocation_type === 'percentage') return `${basisPointsToPercent(bucket.allocation_value).toFixed(2)}%`;
|
||||
return `$${centsToDollars(bucket.allocation_value).toFixed(2)}`;
|
||||
};
|
||||
|
||||
const csrfToken = () =>
|
||||
|
|
@ -158,7 +170,11 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream
|
|||
name: formData.name,
|
||||
type: formData.type,
|
||||
allocation_type: formData.allocation_type,
|
||||
allocation_value: formData.allocation_value ? parseFloat(formData.allocation_value) : null,
|
||||
allocation_value: formData.allocation_value
|
||||
? (formData.allocation_type === 'percentage'
|
||||
? percentToBasisPoints(parseFloat(formData.allocation_value))
|
||||
: dollarsToCents(parseFloat(formData.allocation_value)))
|
||||
: null,
|
||||
buffer_multiplier: formData.allocation_type === 'fixed_limit' ? parseFloat(formData.buffer_multiplier) || 0 : 0,
|
||||
}),
|
||||
});
|
||||
|
|
@ -306,11 +322,11 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream
|
|||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-600">Current Filling</span>
|
||||
<InlineEditInput
|
||||
value={bucket.starting_amount}
|
||||
onSave={(val) => patchBucket(bucket.id, { starting_amount: val })}
|
||||
value={centsToDollars(bucket.starting_amount)}
|
||||
onSave={(val) => patchBucket(bucket.id, { starting_amount: dollarsToCents(val) })}
|
||||
formatDisplay={(v) => `$${v.toFixed(2)}`}
|
||||
min={0}
|
||||
step="1"
|
||||
step="0.01"
|
||||
className="text-lg font-semibold text-gray-900"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -329,8 +345,8 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream
|
|||
min={0}
|
||||
step="0.01"
|
||||
/>
|
||||
{bucket.buffer_multiplier > 0 && (
|
||||
<> = ${bucket.effective_capacity.toFixed(2)} effective</>
|
||||
{bucket.buffer_multiplier > 0 && bucket.effective_capacity !== null && (
|
||||
<> = ${centsToDollars(bucket.effective_capacity).toFixed(2)} effective</>
|
||||
)}
|
||||
)
|
||||
</span>
|
||||
|
|
@ -342,7 +358,7 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream
|
|||
<div className="flex justify-between text-sm">
|
||||
<span>Progress</span>
|
||||
<span>
|
||||
${bucket.current_balance.toFixed(2)} / ${bucket.effective_capacity.toFixed(2)}
|
||||
${centsToDollars(bucket.current_balance).toFixed(2)} / ${bucket.effective_capacity !== null ? centsToDollars(bucket.effective_capacity).toFixed(2) : '∞'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-1 h-2 bg-gray-200 rounded-full">
|
||||
|
|
|
|||
Loading…
Reference in a new issue