Replace info box with toggle for granted balance in balance edit sheet
Swap the static "both will be updated" info box with a ConfigRow + Switch toggle so users can control whether adding to balance also updates the granted balance. Remove the overly restrictive included_grant validation on the server and clean up dead params in computeGrantedBalanceInput. Made-with: Cursor
This commit is contained in:
@@ -1,12 +1,8 @@
|
||||
import {
|
||||
ErrCode,
|
||||
findFeatureById,
|
||||
notNullish,
|
||||
nullish,
|
||||
RecaseError,
|
||||
UpdateBalanceParamsV0Schema,
|
||||
} from "@autumn/shared";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { createRoute } from "@/honoMiddlewares/routeHandler";
|
||||
import { runUpdateBalanceV2 } from "@/internal/balances/updateBalance/runUpdateBalanceV2";
|
||||
import { runUpdateUsage } from "@/internal/balances/updateBalance/runUpdateUsage";
|
||||
@@ -32,15 +28,6 @@ export const handleUpdateBalance = createRoute({
|
||||
|
||||
const targetBalance = params.remaining ?? params.current_balance;
|
||||
|
||||
if (notNullish(params.included_grant) && nullish(targetBalance)) {
|
||||
throw new RecaseError({
|
||||
message:
|
||||
"'remaining' is required when updating granted balance",
|
||||
code: ErrCode.InvalidRequest,
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
});
|
||||
}
|
||||
|
||||
let fullCustomer = await getOrSetCachedFullCustomer({
|
||||
ctx,
|
||||
customerId: params.customer_id,
|
||||
@@ -59,7 +46,6 @@ export const handleUpdateBalance = createRoute({
|
||||
}
|
||||
|
||||
if (notNullish(params.included_grant)) {
|
||||
|
||||
ctx.logger.info(
|
||||
`updating granted balance for feature ${params.feature_id} to ${params.included_grant}`,
|
||||
);
|
||||
|
||||
@@ -96,8 +96,6 @@ test.concurrent(`${chalk.yellowBright("update-prepaid-granted1: granted_balance
|
||||
|
||||
const grantedBalanceInput = computeGrantedBalanceInput({
|
||||
newGPB,
|
||||
defaultGPB,
|
||||
defaultBalance,
|
||||
prepaidAllowance,
|
||||
});
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ export function computeGrantedBalanceInput({
|
||||
prepaidAllowance,
|
||||
}: {
|
||||
newGPB: number;
|
||||
defaultGPB: number;
|
||||
defaultBalance: number;
|
||||
prepaidAllowance: number;
|
||||
}): number {
|
||||
return newGPB - prepaidAllowance;
|
||||
|
||||
@@ -13,7 +13,9 @@ import { ClockCountdownIcon } from "@phosphor-icons/react";
|
||||
import { useStore } from "@tanstack/react-form";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { ConfigRow } from "@/components/forms/shared/ConfigRow";
|
||||
import { DateInputUnix } from "@/components/general/DateInputUnix";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Button } from "@/components/v2/buttons/Button";
|
||||
import { CopyButton } from "@/components/v2/buttons/CopyButton";
|
||||
import { GroupedTabButton } from "@/components/v2/buttons/GroupedTabButton";
|
||||
@@ -26,7 +28,6 @@ import { useAxiosInstance } from "@/services/useAxiosInstance";
|
||||
import { formatUnixToDateTime } from "@/utils/formatUtils/formatDateUtils";
|
||||
import { getBackendErr, notNullish } from "@/utils/genUtils";
|
||||
import { useCusQuery } from "@/views/customers/customer/hooks/useCusQuery";
|
||||
import { InfoBox } from "@/views/onboarding2/integrate/components/InfoBox";
|
||||
import { useCustomerContext } from "../../customer/CustomerContext";
|
||||
import { BalanceEditPreviews } from "./BalanceEditPreviews";
|
||||
import { GrantedBalancePopover } from "./GrantedBalancePopover";
|
||||
@@ -463,6 +464,11 @@ function SetBalanceFields({
|
||||
/* ─── Add Balance Mode ─── */
|
||||
|
||||
function AddBalanceFields({ form }: { form: BalanceEditFormInstance }) {
|
||||
const updateGrantedBalance = useStore(
|
||||
form.store,
|
||||
(s) => s.values.updateGrantedBalance,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<form.Field name="addValue">
|
||||
@@ -482,9 +488,18 @@ function AddBalanceFields({ form }: { form: BalanceEditFormInstance }) {
|
||||
/>
|
||||
)}
|
||||
</form.Field>
|
||||
<InfoBox variant="note">
|
||||
Current and total granted balance will both be updated.
|
||||
</InfoBox>
|
||||
<ConfigRow
|
||||
title="Also Update Granted Balance"
|
||||
description="Increase the total granted balance by the same amount"
|
||||
action={
|
||||
<Switch
|
||||
checked={updateGrantedBalance}
|
||||
onCheckedChange={(checked) =>
|
||||
form.setFieldValue("updateGrantedBalance", !!checked)
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -551,9 +566,6 @@ function SubmitButton({
|
||||
if (values.mode === "set") {
|
||||
const grantedBalanceInput = computeGrantedBalanceInput({
|
||||
newGPB: values.grantedAndPurchasedBalance ?? 0,
|
||||
defaultGPB:
|
||||
form.options.defaultValues?.grantedAndPurchasedBalance ?? 0,
|
||||
defaultBalance: form.options.defaultValues?.balance ?? 0,
|
||||
prepaidAllowance: form.prepaidAllowance,
|
||||
});
|
||||
|
||||
@@ -566,18 +578,29 @@ function SubmitButton({
|
||||
feature_id: featureId,
|
||||
current_balance: targetBalance,
|
||||
included_grant: grantedBalanceInput ?? undefined,
|
||||
granted_balance: grantedBalanceInput ?? undefined,
|
||||
customer_entitlement_id: selectedCusEnt.id,
|
||||
entity_id: entityId ?? undefined,
|
||||
next_reset_at: values.nextResetAt ?? undefined,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
const addAmount = parseFloat(String(values.addValue));
|
||||
const defaultGPB =
|
||||
form.options.defaultValues?.grantedAndPurchasedBalance ?? 0;
|
||||
const newGPB = defaultGPB + addAmount;
|
||||
const grantedBalanceInput = values.updateGrantedBalance
|
||||
? computeGrantedBalanceInput({
|
||||
newGPB,
|
||||
prepaidAllowance: form.prepaidAllowance,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
promises.push(
|
||||
axiosInstance.post("/v1/balances/update", {
|
||||
customer_id: customer.id || customer.internal_id,
|
||||
feature_id: featureId,
|
||||
add_to_balance: parseFloat(String(values.addValue)),
|
||||
add_to_balance: addAmount,
|
||||
included_grant: grantedBalanceInput,
|
||||
customer_entitlement_id: selectedCusEnt.id,
|
||||
entity_id: entityId ?? undefined,
|
||||
}),
|
||||
|
||||
@@ -7,6 +7,7 @@ export const BalanceEditFormSchema = z
|
||||
grantedAndPurchasedBalance: z.number().nullable(),
|
||||
nextResetAt: z.number().nullable(),
|
||||
addValue: z.number().nullable(),
|
||||
updateGrantedBalance: z.boolean(),
|
||||
})
|
||||
.check((ctx) => {
|
||||
const { mode, balance, addValue } = ctx.value;
|
||||
|
||||
@@ -50,6 +50,7 @@ export function useBalanceEditForm({
|
||||
grantedAndPurchasedBalance: grantedAndPurchasedBalance ?? null,
|
||||
nextResetAt: selectedCusEnt.next_reset_at ?? null,
|
||||
addValue: null,
|
||||
updateGrantedBalance: true,
|
||||
} as BalanceEditForm,
|
||||
validators: {
|
||||
onChange: BalanceEditFormSchema,
|
||||
|
||||
Reference in New Issue
Block a user