11import { Loader2 } from "lucide-react" ;
2- import { useState } from "react" ;
2+ import { useCallback , useState } from "react" ;
33
44import { Button } from "@/components/ui/button" ;
5- import { Dialog , DialogContent , DialogFooter , DialogHeader , DialogTitle , DialogTrigger } from "@/components/ui/dialog" ;
5+ import {
6+ Dialog ,
7+ DialogContent ,
8+ DialogDescription ,
9+ DialogFooter ,
10+ DialogHeader ,
11+ DialogTitle ,
12+ DialogTrigger ,
13+ } from "@/components/ui/dialog" ;
614
715import { Input } from "../ui/input" ;
816import { Label } from "../ui/label" ;
@@ -23,6 +31,20 @@ export default function PurchaseSeatsDialog({
2331 const [ quantity , setQuantity ] = useState < number | null > ( 0 ) ;
2432 const [ isLoading , setIsLoading ] = useState ( false ) ;
2533 const [ isOpen , setIsOpen ] = useState ( false ) ;
34+
35+ const handleUpdateSeats = useCallback ( async ( ) => {
36+ setIsLoading ( true ) ;
37+ await fetch ( `/api/workspaces/${ workspaceId } /update-seats` , {
38+ method : "POST" ,
39+ body : JSON . stringify ( {
40+ quantity : quantity ,
41+ } ) ,
42+ } ) ;
43+ setIsLoading ( false ) ;
44+ setIsOpen ( false ) ;
45+ onUpdate ?.( ) ;
46+ } , [ onUpdate , quantity , workspaceId ] ) ;
47+
2648 return (
2749 < Dialog
2850 onOpenChange = { ( open ) => {
@@ -38,38 +60,29 @@ export default function PurchaseSeatsDialog({
3860 Add seats
3961 </ Button >
4062 </ DialogTrigger >
41- < DialogContent >
63+ < DialogContent className = "sm:max-w-md" >
4264 < DialogHeader >
4365 < DialogTitle > Add seats</ DialogTitle >
66+ < DialogDescription > Purchase additional seats for your workspace.</ DialogDescription >
4467 </ DialogHeader >
45- < p > Purchase additional seats for your workspace.</ p >
46- < Label className = "text-sm text-secondary-foreground" >
47- Your current tier includes { seatsIncludedInTier } seats. You have { currentQuantity - seatsIncludedInTier } { " " }
48- additional seats. Purchasing seats will charge your payment method on file.
49- </ Label >
50- < Input
51- type = "number"
52- onChange = { ( e ) =>
53- e . target . value === "" ? setQuantity ( null ) : setQuantity ( Math . max ( 0 , parseInt ( e . target . value ) ) )
54- }
55- value = { quantity ?. toString ( ) ?? "" }
56- />
68+ < div className = "grid gap-2" >
69+ < Label className = "text-secondary-foreground text-xs" >
70+ Your current tier includes { seatsIncludedInTier } seats. You have { currentQuantity - seatsIncludedInTier } { " " }
71+ additional seats. Purchasing seats will charge your payment method on file.
72+ </ Label >
73+ < Input
74+ type = "number"
75+ onChange = { ( e ) =>
76+ e . target . value === "" ? setQuantity ( null ) : setQuantity ( Math . max ( 0 , parseInt ( e . target . value ) ) )
77+ }
78+ value = { quantity ?. toString ( ) ?? "" }
79+ />
80+ </ div >
5781 < DialogFooter >
5882 < Button
5983 className = "flex flex-row items-center"
6084 disabled = { isLoading || quantity === null || quantity <= 0 }
61- onClick = { async ( ) => {
62- setIsLoading ( true ) ;
63- await fetch ( `/api/workspaces/${ workspaceId } /update-seats` , {
64- method : "POST" ,
65- body : JSON . stringify ( {
66- quantity : quantity ,
67- } ) ,
68- } ) ;
69- setIsLoading ( false ) ;
70- setIsOpen ( false ) ;
71- onUpdate ?.( ) ;
72- } }
85+ onClick = { handleUpdateSeats }
7386 >
7487 { isLoading && < Loader2 className = "w-4 h-4 mr-2 animate-spin" /> }
7588 Purchase
0 commit comments