refactor: enforce shared Modal component (#100)
* refactor: enforce shared Modal component in remaining custom modals - ShareSessionModal: replaced custom modal markup with <Modal> - CreateCategoryModal: replaced custom modal markup with <Modal> - EditCategoryModal: replaced custom modal markup with <Modal> - All now get focus trapping, Escape close, body scroll lock for free Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: adopt shared Button component in 18 modal components Replace raw <button> elements with <Button> from ui/Button.tsx: - Primary buttons (bg-gradient-brand) → <Button variant="primary"> - Secondary buttons (border-border) → <Button variant="secondary"> - Ghost buttons → <Button variant="ghost"> - Loading states use loading prop instead of manual Loader2 spinner Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: adopt shared Button component in 20 page/component files Replace raw <button> elements with <Button> across pages and remaining components. 38 total files now use the shared Button component consistently. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit was merged in pull request #100.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { Plus, Trash2, ToggleLeft } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { DataTable, PageHeader, StatusBadge, ActionMenu, EmptyState } from '@/components/admin'
|
||||
import type { Column } from '@/components/admin'
|
||||
import { Modal } from '@/components/common/Modal'
|
||||
@@ -153,10 +154,10 @@ export function FeatureFlagsPage() {
|
||||
title="Feature Flags"
|
||||
description="Manage feature availability per plan and account"
|
||||
action={
|
||||
<button onClick={() => setCreateOpen(true)} className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}>
|
||||
<Button onClick={() => setCreateOpen(true)}>
|
||||
<Plus className="h-4 w-4" />
|
||||
Create Flag
|
||||
</button>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -172,10 +173,10 @@ export function FeatureFlagsPage() {
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-lg font-semibold text-foreground">Account Overrides</h2>
|
||||
<button onClick={() => setOverrideOpen(true)} className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}>
|
||||
<Button onClick={() => setOverrideOpen(true)}>
|
||||
<Plus className="h-4 w-4" />
|
||||
Add Override
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<DataTable columns={overrideColumns} data={overrides} keyExtractor={(o) => o.id} isLoading={loading}
|
||||
@@ -188,8 +189,8 @@ export function FeatureFlagsPage() {
|
||||
<Modal isOpen={createOpen} onClose={() => setCreateOpen(false)} title="Create Feature Flag" size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button onClick={() => setCreateOpen(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel</button>
|
||||
<button onClick={handleCreate} disabled={!createForm.flag_key || !createForm.display_name} className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50">Create</button>
|
||||
<Button variant="secondary" onClick={() => setCreateOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleCreate} disabled={!createForm.flag_key || !createForm.display_name}>Create</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -213,8 +214,8 @@ export function FeatureFlagsPage() {
|
||||
<Modal isOpen={overrideOpen} onClose={() => setOverrideOpen(false)} title="Add Account Override" size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button onClick={() => setOverrideOpen(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel</button>
|
||||
<button onClick={handleCreateOverride} disabled={!overrideForm.account_display_code || !overrideForm.flag_id} className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50">Create</button>
|
||||
<Button variant="secondary" onClick={() => setOverrideOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleCreateOverride} disabled={!overrideForm.account_display_code || !overrideForm.flag_id}>Create</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { Plus, Trash2, Pencil, FolderTree } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { DataTable, PageHeader, ActionMenu, EmptyState } from '@/components/admin'
|
||||
import type { Column } from '@/components/admin'
|
||||
import { Modal } from '@/components/common/Modal'
|
||||
@@ -95,10 +96,10 @@ export function GlobalCategoriesPage() {
|
||||
title="Global Categories"
|
||||
description="Manage tree categories available to all accounts"
|
||||
action={
|
||||
<button onClick={() => setCreateOpen(true)} className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}>
|
||||
<Button onClick={() => setCreateOpen(true)}>
|
||||
<Plus className="h-4 w-4" />
|
||||
Create Category
|
||||
</button>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -118,8 +119,8 @@ export function GlobalCategoriesPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button onClick={() => setCreateOpen(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel</button>
|
||||
<button onClick={handleCreate} disabled={!form.name || !form.slug} className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50">Create</button>
|
||||
<Button variant="secondary" onClick={() => setCreateOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleCreate} disabled={!form.name || !form.slug}>Create</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -147,8 +148,8 @@ export function GlobalCategoriesPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button onClick={() => setEditCategory(null)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel</button>
|
||||
<button onClick={handleUpdate} disabled={!form.name || !form.slug} className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50">Save</button>
|
||||
<Button variant="secondary" onClick={() => setEditCategory(null)}>Cancel</Button>
|
||||
<Button onClick={handleUpdate} disabled={!form.name || !form.slug}>Save</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { Plus, Copy, Trash2, Ticket, Mail, MailCheck, RefreshCw } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { DataTable, PageHeader, StatusBadge, ActionMenu, EmptyState } from '@/components/admin'
|
||||
import type { Column } from '@/components/admin'
|
||||
import { Modal } from '@/components/common/Modal'
|
||||
@@ -215,16 +216,10 @@ export function InviteCodesPage() {
|
||||
title="Invite Codes"
|
||||
description="Create and manage registration invite codes with plan assignment"
|
||||
action={
|
||||
<button
|
||||
onClick={() => setCreateOpen(true)}
|
||||
className={cn(
|
||||
'flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium',
|
||||
'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90'
|
||||
)}
|
||||
>
|
||||
<Button onClick={() => setCreateOpen(true)}>
|
||||
<Plus className="h-4 w-4" />
|
||||
Create Code
|
||||
</button>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -249,19 +244,10 @@ export function InviteCodesPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => { setCreateOpen(false); resetForm() }}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCreate}
|
||||
disabled={creating}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50"
|
||||
>
|
||||
<Button variant="secondary" onClick={() => { setCreateOpen(false); resetForm() }}>Cancel</Button>
|
||||
<Button onClick={handleCreate} loading={creating}>
|
||||
{creating ? 'Creating...' : 'Create'}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { Plus, Trash2, Gauge } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { DataTable, PageHeader, ActionMenu, EmptyState } from '@/components/admin'
|
||||
import type { Column } from '@/components/admin'
|
||||
import { Modal } from '@/components/common/Modal'
|
||||
@@ -127,13 +128,10 @@ export function PlanLimitsPage() {
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-lg font-semibold text-foreground">Account Overrides</h2>
|
||||
<button
|
||||
onClick={() => setCreateOverride(true)}
|
||||
className={cn('flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium', 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90')}
|
||||
>
|
||||
<Button onClick={() => setCreateOverride(true)}>
|
||||
<Plus className="h-4 w-4" />
|
||||
Add Override
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<DataTable
|
||||
@@ -154,8 +152,8 @@ export function PlanLimitsPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button onClick={() => setEditPlan(null)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel</button>
|
||||
<button onClick={handleSavePlan} className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90">Save</button>
|
||||
<Button variant="secondary" onClick={() => setEditPlan(null)}>Cancel</Button>
|
||||
<Button onClick={handleSavePlan}>Save</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -185,8 +183,8 @@ export function PlanLimitsPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button onClick={() => setCreateOverride(false)} className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground">Cancel</button>
|
||||
<button onClick={handleCreateOverride} disabled={!overrideForm.account_display_code} className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50">Create</button>
|
||||
<Button variant="secondary" onClick={() => setCreateOverride(false)}>Cancel</Button>
|
||||
<Button onClick={handleCreateOverride} disabled={!overrideForm.account_display_code}>Create</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { ArrowLeft, Shield, Crown, UserCheck, UserX, Clock, Ticket, KeyRound, Copy, Check, Archive, ArchiveRestore, Trash2 } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { StatusBadge } from '@/components/admin'
|
||||
import { Modal } from '@/components/common/Modal'
|
||||
import { Spinner } from '@/components/common/Spinner'
|
||||
@@ -205,12 +206,9 @@ export function UserDetailPage() {
|
||||
title="User not found"
|
||||
description="This user may have been removed or is unavailable."
|
||||
action={(
|
||||
<button
|
||||
onClick={() => navigate('/admin/users')}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
<Button variant="secondary" onClick={() => navigate('/admin/users')}>
|
||||
Back to Users
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
@@ -525,18 +523,8 @@ export function UserDetailPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setPlanModalOpen(false)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleChangePlan}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
|
||||
>
|
||||
Update Plan
|
||||
</button>
|
||||
<Button variant="secondary" onClick={() => setPlanModalOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleChangePlan}>Update Plan</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -563,19 +551,10 @@ export function UserDetailPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setResetModalOpen(false)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleResetPassword}
|
||||
disabled={resetLoading}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50"
|
||||
>
|
||||
<Button variant="secondary" onClick={() => setResetModalOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleResetPassword} loading={resetLoading}>
|
||||
{resetLoading ? 'Resetting...' : 'Reset Password'}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -624,12 +603,7 @@ export function UserDetailPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
onClick={() => { setResetTempPassword(null); setResetModalOpen(false) }}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
|
||||
>
|
||||
Done
|
||||
</button>
|
||||
<Button onClick={() => { setResetTempPassword(null); setResetModalOpen(false) }}>Done</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -663,18 +637,10 @@ export function UserDetailPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setTrialModalOpen(false)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleExtendTrial}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
|
||||
>
|
||||
<Button variant="secondary" onClick={() => setTrialModalOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleExtendTrial}>
|
||||
{user.subscription?.status === 'trialing' ? 'Extend' : 'Start Trial'}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -700,23 +666,13 @@ export function UserDetailPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setSuperAdminModalOpen(false)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
<Button variant="secondary" onClick={() => setSuperAdminModalOpen(false)}>Cancel</Button>
|
||||
<Button
|
||||
onClick={handleToggleSuperAdmin}
|
||||
className={cn(
|
||||
'rounded-md px-4 py-2 text-sm font-medium text-white',
|
||||
user.is_super_admin
|
||||
? 'bg-yellow-600 hover:bg-yellow-700'
|
||||
: 'bg-gradient-brand shadow-lg shadow-primary/20 hover:opacity-90'
|
||||
)}
|
||||
className={user.is_super_admin ? 'bg-yellow-600 hover:bg-yellow-700 shadow-none' : ''}
|
||||
>
|
||||
{user.is_super_admin ? 'Remove Access' : 'Promote'}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -741,19 +697,11 @@ export function UserDetailPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setHardDeleteModalOpen(false)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<Button variant="secondary" onClick={() => setHardDeleteModalOpen(false)}>Cancel</Button>
|
||||
{hardDeleteBlockers && Object.keys(hardDeleteBlockers).length === 0 && (
|
||||
<button
|
||||
onClick={handleHardDelete}
|
||||
className="rounded-md bg-red-600 px-4 py-2 text-sm font-medium text-foreground hover:bg-red-700"
|
||||
>
|
||||
<Button variant="destructive" onClick={handleHardDelete}>
|
||||
Delete Permanently
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { UserCheck, UserX, Shield, ArrowRightLeft, ExternalLink, UserPlus, Copy, Check, Mail } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { DataTable, Pagination, SearchInput, PageHeader, StatusBadge, ActionMenu } from '@/components/admin'
|
||||
import type { Column } from '@/components/admin'
|
||||
import { Modal } from '@/components/common/Modal'
|
||||
@@ -266,20 +267,14 @@ export function UsersPage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<PageHeader title="Users" description="Manage platform users and roles" />
|
||||
<div className="flex items-center gap-3">
|
||||
<button
|
||||
onClick={() => setShowInviteModal(true)}
|
||||
className="flex items-center gap-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-accent transition-colors"
|
||||
>
|
||||
<Button variant="secondary" onClick={() => setShowInviteModal(true)}>
|
||||
<Mail className="h-4 w-4" />
|
||||
Invite User
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowCreateModal(true)}
|
||||
className="flex items-center gap-2 rounded-lg bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 transition-colors"
|
||||
>
|
||||
</Button>
|
||||
<Button onClick={() => setShowCreateModal(true)}>
|
||||
<UserPlus className="h-4 w-4" />
|
||||
Create User
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -324,18 +319,8 @@ export function UsersPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setRoleModalUser(null)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground/60 hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleRoleChange}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
<Button variant="secondary" onClick={() => setRoleModalUser(null)}>Cancel</Button>
|
||||
<Button onClick={handleRoleChange}>Save</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -365,19 +350,8 @@ export function UsersPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setMoveModalUser(null)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground/60 hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleMoveAccount}
|
||||
disabled={!displayCode}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50"
|
||||
>
|
||||
Move
|
||||
</button>
|
||||
<Button variant="secondary" onClick={() => setMoveModalUser(null)}>Cancel</Button>
|
||||
<Button onClick={handleMoveAccount} disabled={!displayCode}>Move</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -409,19 +383,10 @@ export function UsersPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setShowCreateModal(false)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground/60 hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCreateUser}
|
||||
disabled={createLoading || !createForm.email || !createForm.name}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50"
|
||||
>
|
||||
<Button variant="secondary" onClick={() => setShowCreateModal(false)}>Cancel</Button>
|
||||
<Button onClick={handleCreateUser} disabled={!createForm.email || !createForm.name} loading={createLoading}>
|
||||
{createLoading ? 'Creating...' : 'Create User'}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -520,12 +485,7 @@ export function UsersPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
onClick={() => setTempPassword(null)}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
|
||||
>
|
||||
Done
|
||||
</button>
|
||||
<Button onClick={() => setTempPassword(null)}>Done</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -562,19 +522,10 @@ export function UsersPage() {
|
||||
size="sm"
|
||||
footer={
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setShowInviteModal(false)}
|
||||
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground/60 hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleInviteUser}
|
||||
disabled={inviteLoading || !inviteForm.email || !inviteForm.account_display_code}
|
||||
className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50"
|
||||
>
|
||||
<Button variant="secondary" onClick={() => setShowInviteModal(false)}>Cancel</Button>
|
||||
<Button onClick={handleInviteUser} disabled={!inviteForm.email || !inviteForm.account_display_code} loading={inviteLoading}>
|
||||
{inviteLoading ? 'Sending...' : 'Send Invite'}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user