Skip to content

Commit 6b15a50

Browse files
authored
improvement(ui): updated subscription and team settings modals to emcn (#2477)
1 parent 65787d7 commit 6b15a50

File tree

6 files changed

+233
-242
lines changed

6 files changed

+233
-242
lines changed

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/components/cancel-subscription/cancel-subscription.tsx

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22

33
import { useEffect, useState } from 'react'
44
import { useQueryClient } from '@tanstack/react-query'
5-
import { Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader } from '@/components/emcn'
5+
import {
6+
Button,
7+
Label,
8+
Modal,
9+
ModalBody,
10+
ModalContent,
11+
ModalFooter,
12+
ModalHeader,
13+
} from '@/components/emcn'
614
import { useSession, useSubscription } from '@/lib/auth/auth-client'
715
import { getSubscriptionStatus } from '@/lib/billing/client/utils'
816
import { cn } from '@/lib/core/utils/cn'
@@ -68,7 +76,6 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
6876

6977
if (subscriptionStatus.isTeam && activeOrgId) {
7078
referenceId = activeOrgId
71-
// Get subscription ID for team/enterprise
7279
subscriptionId = subData?.data?.id
7380
}
7481

@@ -132,14 +139,12 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
132139
referenceId = activeOrgId
133140
subscriptionId = subData?.data?.id
134141
} else {
135-
// For personal subscriptions, use user ID and let better-auth find the subscription
136142
referenceId = session.user.id
137143
subscriptionId = undefined
138144
}
139145

140146
logger.info('Restoring subscription', { referenceId, subscriptionId })
141147

142-
// Build restore params - only include subscriptionId if we have one (team/enterprise)
143148
const restoreParams: any = { referenceId }
144149
if (subscriptionId) {
145150
restoreParams.subscriptionId = subscriptionId
@@ -150,7 +155,6 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
150155
logger.info('Subscription restored successfully', result)
151156
}
152157

153-
// Invalidate queries to refresh data
154158
await queryClient.invalidateQueries({ queryKey: subscriptionKeys.user() })
155159
if (activeOrgId) {
156160
await queryClient.invalidateQueries({ queryKey: organizationKeys.detail(activeOrgId) })
@@ -175,10 +179,8 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
175179
if (!date) return 'end of current billing period'
176180

177181
try {
178-
// Ensure we have a valid Date object
179182
const dateObj = date instanceof Date ? date : new Date(date)
180183

181-
// Check if the date is valid
182184
if (Number.isNaN(dateObj.getTime())) {
183185
return 'end of current billing period'
184186
}
@@ -196,28 +198,25 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
196198

197199
const periodEndDate = getPeriodEndDate()
198200

199-
// Check if subscription is set to cancel at period end
200201
const isCancelAtPeriodEnd = subscriptionData?.cancelAtPeriodEnd === true
201202

202203
return (
203204
<>
204205
<div className='flex items-center justify-between'>
205-
<div>
206-
<span className='font-medium text-[13px]'>
207-
{isCancelAtPeriodEnd ? 'Restore Subscription' : 'Manage Subscription'}
208-
</span>
206+
<div className='flex flex-col gap-[2px]'>
207+
<Label>{isCancelAtPeriodEnd ? 'Restore Subscription' : 'Manage Subscription'}</Label>
209208
{isCancelAtPeriodEnd && (
210-
<p className='mt-1 text-[var(--text-muted)] text-xs'>
209+
<span className='text-[12px] text-[var(--text-muted)]'>
211210
You'll keep access until {formatDate(periodEndDate)}
212-
</p>
211+
</span>
213212
)}
214213
</div>
215214
<Button
216215
variant='outline'
217216
onClick={() => setIsDialogOpen(true)}
218217
disabled={isLoading}
219218
className={cn(
220-
'h-8 rounded-[8px] font-medium text-xs',
219+
'h-8 rounded-[8px] text-[13px]',
221220
error && 'border-[var(--text-error)] text-[var(--text-error)]'
222221
)}
223222
>
@@ -231,7 +230,7 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
231230
{isCancelAtPeriodEnd ? 'Restore' : 'Cancel'} {subscription.plan} Subscription
232231
</ModalHeader>
233232
<ModalBody>
234-
<p className='text-[12px] text-[var(--text-tertiary)]'>
233+
<p className='text-[12px] text-[var(--text-muted)]'>
235234
{isCancelAtPeriodEnd
236235
? 'Your subscription is set to cancel at the end of the billing period. Would you like to keep your subscription active?'
237236
: `You'll be redirected to Stripe to manage your subscription. You'll keep access until ${formatDate(
@@ -244,8 +243,8 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
244243

245244
{!isCancelAtPeriodEnd && (
246245
<div className='mt-3'>
247-
<div className='rounded-[8px] bg-[var(--surface-3)] p-3 text-sm'>
248-
<ul className='space-y-1 text-[var(--text-muted)] text-xs'>
246+
<div className='rounded-[8px] bg-[var(--surface-5)] p-3'>
247+
<ul className='space-y-1 text-[12px] text-[var(--text-muted)]'>
249248
<li>• Keep all features until {formatDate(periodEndDate)}</li>
250249
<li>• No more charges</li>
251250
<li>• Data preserved</li>

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/components/credit-balance/credit-balance.tsx

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import { useState } from 'react'
44
import {
55
Button,
66
Input,
7+
Label,
78
Modal,
9+
ModalBody,
810
ModalClose,
911
ModalContent,
1012
ModalFooter,
@@ -90,7 +92,6 @@ export function CreditBalance({
9092
const handleOpenChange = (open: boolean) => {
9193
setIsOpen(open)
9294
if (open) {
93-
// Generate new requestId when modal opens - same ID used for entire session
9495
setRequestId(crypto.randomUUID())
9596
} else {
9697
setAmount('')
@@ -102,72 +103,66 @@ export function CreditBalance({
102103

103104
return (
104105
<div className='flex items-center justify-between'>
105-
<div className='flex items-center gap-2'>
106-
<span className='text-muted-foreground text-sm'>Credit Balance</span>
107-
<span className='font-medium text-sm'>{isLoading ? '...' : `$${balance.toFixed(2)}`}</span>
106+
<div className='flex items-center gap-[8px]'>
107+
<Label>Credit Balance</Label>
108+
<span className='text-[13px] text-[var(--text-secondary)]'>
109+
{isLoading ? '...' : `$${balance.toFixed(2)}`}
110+
</span>
108111
</div>
109112

110113
{canPurchase && (
111114
<Modal open={isOpen} onOpenChange={handleOpenChange}>
112115
<ModalTrigger asChild>
113-
<Button variant='outline'>Add Credits</Button>
116+
<Button variant='outline' className='h-8 rounded-[8px] text-[13px]'>
117+
Add Credits
118+
</Button>
114119
</ModalTrigger>
115-
<ModalContent>
120+
<ModalContent size='sm'>
116121
<ModalHeader>Add Credits</ModalHeader>
117-
<div className='px-4'>
118-
<p className='text-[13px] text-[var(--text-secondary)]'>
119-
Credits are used before overage charges. Min $10, max $1,000.
120-
</p>
121-
</div>
122-
123-
{success ? (
124-
<div className='py-4 text-center'>
125-
<p className='text-[14px] text-[var(--text-primary)]'>
122+
<ModalBody>
123+
{success ? (
124+
<p className='text-center text-[13px] text-[var(--text-primary)]'>
126125
Credits added successfully!
127126
</p>
128-
</div>
129-
) : (
130-
<div className='flex flex-col gap-3 py-2'>
131-
<div className='flex flex-col gap-1'>
132-
<label
133-
htmlFor='credit-amount'
134-
className='text-[12px] text-[var(--text-secondary)]'
135-
>
136-
Amount (USD)
137-
</label>
138-
<div className='relative'>
139-
<span className='-translate-y-1/2 absolute top-1/2 left-3 text-[var(--text-secondary)]'>
140-
$
141-
</span>
142-
<Input
143-
id='credit-amount'
144-
type='text'
145-
inputMode='numeric'
146-
value={amount}
147-
onChange={(e) => handleAmountChange(e.target.value)}
148-
placeholder='50'
149-
className='pl-7'
150-
disabled={isPurchasing}
151-
/>
152-
</div>
153-
{error && <span className='text-[11px] text-red-500'>{error}</span>}
154-
</div>
155-
156-
<div className='rounded-[4px] bg-[var(--surface-5)] p-2'>
157-
<p className='text-[11px] text-[var(--text-tertiary)]'>
158-
Credits are non-refundable and don't expire. They'll be applied automatically to
159-
your {entityType === 'organization' ? 'team' : ''} usage.
127+
) : (
128+
<>
129+
<p className='text-[12px] text-[var(--text-muted)]'>
130+
Credits are used before overage charges. Min $10, max $1,000.
160131
</p>
161-
</div>
162-
</div>
163-
)}
164132

133+
<div className='mt-4 flex flex-col gap-[4px]'>
134+
<Label htmlFor='credit-amount'>Amount (USD)</Label>
135+
<div className='relative'>
136+
<span className='-translate-y-1/2 absolute top-1/2 left-3 text-[13px] text-[var(--text-secondary)]'>
137+
$
138+
</span>
139+
<Input
140+
id='credit-amount'
141+
type='text'
142+
inputMode='numeric'
143+
value={amount}
144+
onChange={(e) => handleAmountChange(e.target.value)}
145+
placeholder='50'
146+
className='pl-7'
147+
disabled={isPurchasing}
148+
/>
149+
</div>
150+
{error && <span className='text-[12px] text-[var(--text-error)]'>{error}</span>}
151+
</div>
152+
153+
<div className='mt-4 rounded-[6px] bg-[var(--surface-5)] p-3'>
154+
<p className='text-[12px] text-[var(--text-muted)]'>
155+
Credits are non-refundable and don't expire. They'll be applied automatically
156+
to your {entityType === 'organization' ? 'team' : ''} usage.
157+
</p>
158+
</div>
159+
</>
160+
)}
161+
</ModalBody>
165162
{!success && (
166163
<ModalFooter>
167164
<ModalClose asChild>
168-
<Button variant='ghost' disabled={isPurchasing}>
169-
Cancel
170-
</Button>
165+
<Button disabled={isPurchasing}>Cancel</Button>
171166
</ModalClose>
172167
<Button
173168
variant='primary'

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/components/plan-card/plan-card.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ export function PlanCard({
4545
if (typeof price === 'string') {
4646
return (
4747
<>
48-
<span className='font-semibold text-xl'>{price}</span>
48+
<span className='font-semibold text-[20px]'>{price}</span>
4949
{priceSubtext && (
50-
<span className='ml-1 text-[var(--text-muted)] text-xs'>{priceSubtext}</span>
50+
<span className='ml-1 text-[12px] text-[var(--text-muted)]'>{priceSubtext}</span>
5151
)}
5252
</>
5353
)
@@ -58,13 +58,13 @@ export function PlanCard({
5858
const renderFeatures = () => {
5959
if (isHorizontal) {
6060
return (
61-
<div className='mt-3 flex flex-wrap items-center gap-4'>
61+
<div className='mt-3 flex flex-wrap items-center gap-3'>
6262
{features.map((feature, index) => (
63-
<div key={`${feature.text}-${index}`} className='flex items-center gap-2 text-xs'>
64-
<feature.icon className='h-3 w-3 flex-shrink-0 text-[var(--text-muted)]' />
65-
<span className='text-[var(--text-muted)]'>{feature.text}</span>
63+
<div key={`${feature.text}-${index}`} className='flex items-center gap-2 text-[12px]'>
64+
<feature.icon className='h-3 w-3 flex-shrink-0 text-[var(--text-secondary)]' />
65+
<span className='text-[var(--text-secondary)]'>{feature.text}</span>
6666
{index < features.length - 1 && (
67-
<div className='ml-4 h-4 w-px bg-[var(--border)]' aria-hidden='true' />
67+
<div className='ml-3 h-4 w-px bg-[var(--border)]' aria-hidden='true' />
6868
)}
6969
</div>
7070
))}
@@ -75,12 +75,12 @@ export function PlanCard({
7575
return (
7676
<ul className='mb-4 flex-1 space-y-2'>
7777
{features.map((feature, index) => (
78-
<li key={`${feature.text}-${index}`} className='flex items-start gap-2 text-xs'>
78+
<li key={`${feature.text}-${index}`} className='flex items-start gap-2 text-[12px]'>
7979
<feature.icon
80-
className='mt-0.5 h-3 w-3 flex-shrink-0 text-[var(--text-muted)]'
80+
className='mt-0.5 h-3 w-3 flex-shrink-0 text-[var(--text-secondary)]'
8181
aria-hidden='true'
8282
/>
83-
<span className='text-[var(--text-muted)]'>{feature.text}</span>
83+
<span className='text-[var(--text-secondary)]'>{feature.text}</span>
8484
</li>
8585
))}
8686
</ul>
@@ -91,24 +91,24 @@ export function PlanCard({
9191
<article
9292
className={cn(
9393
'relative flex rounded-[8px] border p-4 transition-colors hover:border-[var(--border-hover)]',
94-
isHorizontal ? 'flex-row items-center justify-between' : 'flex-col',
94+
isHorizontal ? 'flex-row items-center justify-between gap-6' : 'flex-col',
9595
className
9696
)}
9797
>
98-
<header className={isHorizontal ? undefined : 'mb-4'}>
99-
<h3 className='mb-2 font-semibold text-sm'>{name}</h3>
98+
<header className={isHorizontal ? 'flex-1' : 'mb-4'}>
99+
<h3 className='mb-2 font-semibold text-[14px]'>{name}</h3>
100100
<div className='flex items-baseline'>{renderPrice()}</div>
101101
{isHorizontal && renderFeatures()}
102102
</header>
103103

104104
{!isHorizontal && renderFeatures()}
105105

106-
<div className={isHorizontal ? 'ml-auto' : undefined}>
106+
<div className={isHorizontal ? 'flex-shrink-0' : undefined}>
107107
<Button
108108
onClick={onButtonClick}
109109
className={cn(
110-
'h-9 rounded-[8px] text-xs',
111-
isHorizontal ? 'px-4' : 'w-full',
110+
'h-9 rounded-[8px] text-[13px]',
111+
isHorizontal ? 'min-w-[100px] px-6' : 'w-full',
112112
isError && 'border-[var(--text-error)] text-[var(--text-error)]'
113113
)}
114114
variant='outline'

0 commit comments

Comments
 (0)