1- import { conform , useForm } from "@conform-to/react" ;
1+ import { useForm } from "@conform-to/react" ;
22import { parse } from "@conform-to/zod" ;
33import { ArrowUpCircleIcon , EnvelopeIcon , PlusIcon } from "@heroicons/react/20/solid" ;
44import { BookOpenIcon } from "@heroicons/react/24/solid" ;
@@ -126,11 +126,19 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
126126const PurchaseSchema = z . discriminatedUnion ( "action" , [
127127 z . object ( {
128128 action : z . literal ( "purchase" ) ,
129- amount : z . coerce . number ( ) . int ( "Must be a whole number" ) . min ( 0 , "Amount must be 0 or more" ) ,
129+ amount : z . coerce
130+ . number ( )
131+ . int ( "Must be a whole number" )
132+ . min ( 0 , "Amount must be 0 or more" )
133+ . refine ( ( n ) => n % 1000 === 0 , "Schedules are sold in bundles of 1,000" ) ,
130134 } ) ,
131135 z . object ( {
132136 action : z . literal ( "quota-increase" ) ,
133- amount : z . coerce . number ( ) . int ( "Must be a whole number" ) . min ( 1 , "Amount must be greater than 0" ) ,
137+ amount : z . coerce
138+ . number ( )
139+ . int ( "Must be a whole number" )
140+ . min ( 1 , "Amount must be greater than 0" )
141+ . refine ( ( n ) => n % 1000 === 0 , "Schedules are sold in bundles of 1,000" ) ,
134142 } ) ,
135143] ) ;
136144
@@ -623,10 +631,12 @@ function PurchaseSchedulesModal({
623631 shouldRevalidate : "onSubmit" ,
624632 } ) ;
625633
626- const [ amountValue , setAmountValue ] = useState ( extraSchedules ) ;
634+ const stepSize = schedulePricing . stepSize ;
635+ const [ bundles , setBundles ] = useState ( Math . round ( extraSchedules / stepSize ) ) ;
627636 useEffect ( ( ) => {
628- setAmountValue ( extraSchedules ) ;
629- } , [ extraSchedules ] ) ;
637+ setBundles ( Math . round ( extraSchedules / stepSize ) ) ;
638+ } , [ extraSchedules , stepSize ] ) ;
639+ const amountValue = bundles * stepSize ;
630640 const isLoading = fetcher . state !== "idle" ;
631641
632642 const [ open , setOpen ] = useState ( false ) ;
@@ -653,9 +663,9 @@ function PurchaseSchedulesModal({
653663 const changeClassName =
654664 state === "decrease" ? "text-error" : state === "increase" ? "text-success" : undefined ;
655665
656- const pricePerSchedule = schedulePricing . centsPerStep / schedulePricing . stepSize / 100 ;
666+ const pricePerSchedule = schedulePricing . centsPerStep / stepSize / 100 ;
657667 const pricePerStep = schedulePricing . centsPerStep / 100 ;
658- const stepUnit = formatNumber ( schedulePricing . stepSize ) ;
668+ const stepUnit = formatNumber ( stepSize ) ;
659669 const title = extraSchedules === 0 ? "Purchase extra schedules…" : "Add/remove extra schedules…" ;
660670
661671 return (
@@ -673,25 +683,29 @@ function PurchaseSchedulesModal({
673683 < div className = "flex flex-col gap-4 pt-2" >
674684 < div className = "flex flex-col gap-1" >
675685 < Paragraph variant = "small/bright" >
676- Purchase extra schedules at { formatCurrency ( pricePerStep , false ) } /month per { " " }
677- { stepUnit } schedules . Reducing the number of schedules will take effect at the start
678- of the next billing cycle (1st of the month).
686+ Schedules are purchased in bundles of { stepUnit } , at { " " }
687+ { formatCurrency ( pricePerStep , false ) } /month per bundle . Reducing will take effect at
688+ the start of the next billing cycle (1st of the month).
679689 </ Paragraph >
680690 </ div >
681691 < Fieldset >
682692 < InputGroup fullWidth >
683- < Label htmlFor = "amount " className = "text-text-dimmed" >
684- Total extra schedules
693+ < Label htmlFor = "schedule-bundles " className = "text-text-dimmed" >
694+ Bundles of { stepUnit } schedules
685695 </ Label >
686696 < InputNumberStepper
687- { ... conform . input ( amount , { type : "number" } ) }
688- step = { schedulePricing . stepSize }
697+ id = "schedule-bundles"
698+ step = { 1 }
689699 min = { 0 }
690- max = { undefined }
691- value = { amountValue }
692- onChange = { ( e ) => setAmountValue ( Number ( e . target . value ) ) }
700+ value = { bundles }
701+ onChange = { ( e ) => setBundles ( Number ( e . target . value ) ) }
693702 disabled = { isLoading }
694703 />
704+ < input type = "hidden" name = "amount" value = { amountValue } />
705+ < Paragraph variant = "small" className = "text-text-dimmed" >
706+ { formatNumber ( bundles ) } { bundles === 1 ? "bundle" : "bundles" } ={ " " }
707+ { formatNumber ( amountValue ) } schedules
708+ </ Paragraph >
695709 < FormError id = { amount . errorId } >
696710 { amount . error ?? amount . initialError ?. [ "" ] ?. [ 0 ] }
697711 </ FormError >
0 commit comments