@@ -3,7 +3,7 @@ import { parse } from "@conform-to/zod";
33import { BellAlertIcon , CurrencyDollarIcon , EnvelopeIcon } from "@heroicons/react/20/solid" ;
44import { Form , useActionData , type MetaFunction } from "@remix-run/react" ;
55import { type ActionFunction , json , type LoaderFunctionArgs } from "@remix-run/server-runtime" ;
6- import { Fragment , useRef , useState } from "react" ;
6+ import { Fragment , useEffect , useRef , useState } from "react" ;
77import { redirect , typedjson , useTypedLoaderData } from "remix-typedjson" ;
88import { z } from "zod" ;
99import { AdminDebugTooltip } from "~/components/admin/debugTooltip" ;
@@ -30,6 +30,7 @@ import { useOrganization } from "~/hooks/useOrganizations";
3030import { redirectWithErrorMessage , redirectWithSuccessMessage } from "~/models/message.server" ;
3131import { getBillingAlerts , setBillingAlert } from "~/services/platform.v3.server" ;
3232import { requireUserId } from "~/services/session.server" ;
33+ import { formatCurrency , formatNumber } from "~/utils/numberFormatter" ;
3334import {
3435 OrganizationParamsSchema ,
3536 organizationPath ,
@@ -146,7 +147,6 @@ export const action: ActionFunction = async ({ request, params }) => {
146147export default function Page ( ) {
147148 const { alerts } = useTypedLoaderData < typeof loader > ( ) ;
148149 const [ dollarAmount , setDollarAmount ] = useState ( alerts . amount . toFixed ( 2 ) ) ;
149- const organization = useOrganization ( ) ;
150150
151151 const lastSubmission = useActionData ( ) ;
152152
@@ -162,11 +162,17 @@ export default function Page() {
162162 } ,
163163 } ) ;
164164
165- const fieldValues = useRef < string [ ] > ( [ "" ] ) ;
165+ const fieldValues = useRef < string [ ] > ( alerts . emails ) ;
166166 const emailFields = useFieldList ( form . ref , { ...emails , defaultValue : alerts . emails } ) ;
167167
168168 const checkboxLevels = [ 0.75 , 0.9 , 1.0 ] ;
169169
170+ useEffect ( ( ) => {
171+ if ( alerts . emails . length > 0 ) {
172+ requestIntent ( form . ref . current ?? undefined , list . append ( emails . name ) ) ;
173+ }
174+ } , [ ] ) ;
175+
170176 return (
171177 < PageContainer >
172178 < NavBar >
@@ -180,11 +186,11 @@ export default function Page() {
180186 < div >
181187 < Header2 spacing > Billing alerts</ Header2 >
182188 < Paragraph spacing variant = "small" >
183- Receive emails when your compute spend crosses the thresholds set below .
189+ Receive an email when your compute spend crosses different thresholds.
184190 </ Paragraph >
185191 < Form method = "post" { ...form . props } >
186192 < Fieldset >
187- < InputGroup >
193+ < InputGroup fullWidth >
188194 < Label htmlFor = { amount . id } > Amount</ Label >
189195 < Input
190196 { ...conform . input ( amount , { type : "number" } ) }
@@ -202,32 +208,40 @@ export default function Page() {
202208 placeholder = "Enter an amount"
203209 icon = { < span className = "-mt-0.5 block pl-0.5 text-sm text-text-dimmed" > $</ span > }
204210 className = "pl-px"
211+ fullWidth
205212 />
206213 < FormError id = { amount . errorId } > { amount . error } </ FormError >
207214 </ InputGroup >
208- < InputGroup >
215+ < InputGroup fullWidth >
209216 < Label htmlFor = { alertLevels . id } > Alert me when I reach</ Label >
210217 { checkboxLevels . map ( ( level ) => (
211218 < CheckboxWithLabel
212219 name = { alertLevels . name }
213220 id = { `level_${ level } ` }
214221 value = { level . toString ( ) }
215222 variant = "simple/small"
216- label = { `${ level * 100 } % ($${ ( Number ( dollarAmount ) * level ) . toFixed ( 2 ) } )` }
217- defaultChecked
223+ label = {
224+ < span >
225+ { level * 100 } %{ " " }
226+ < span className = "text-text-dimmed" >
227+ ({ formatCurrency ( Number ( dollarAmount ) * level , false ) } )
228+ </ span >
229+ </ span >
230+ }
231+ defaultChecked = { alerts . alertLevels . includes ( level ) }
218232 className = "pr-0"
233+ readOnly = { level === 1.0 }
219234 />
220235 ) ) }
221236 < FormError id = { alertLevels . errorId } > { alertLevels . error } </ FormError >
222237 </ InputGroup >
223- < InputGroup >
238+ < InputGroup fullWidth >
224239 < Label htmlFor = { emails . id } > Email addresses</ Label >
225240 { emailFields . map ( ( email , index ) => (
226241 < Fragment key = { email . key } >
227242 < Input
228243 { ...conform . input ( email , { type : "email" } ) }
229244 placeholder = { index === 0 ? "Enter an email address" : "Add another email" }
230- icon = { EnvelopeIcon }
231245 autoFocus = { index === 0 }
232246 onChange = { ( e ) => {
233247 fieldValues . current [ index ] = e . target . value ;
@@ -238,6 +252,7 @@ export default function Page() {
238252 requestIntent ( form . ref . current ?? undefined , list . append ( emails . name ) ) ;
239253 }
240254 } }
255+ fullWidth
241256 />
242257 < FormError id = { email . errorId } > { email . error } </ FormError >
243258 </ Fragment >
0 commit comments