PromoteInstallationModal.tsx86 lines · main
1import { toast } from 'sonner'
2import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
3
4import { Installation, PrivateApp, usePrivateApps } from '../PrivateAppsContext'
5import { usePlatformAppInstallationCreateMutation } from '@/data/platform-apps/platform-app-installation-create-mutation'
6import { usePlatformAppInstallationDeleteMutation } from '@/data/platform-apps/platform-app-installation-delete-mutation'
7
8interface PromoteInstallationModalProps {
9 appToPromote: PrivateApp | undefined
10 currentInstallation: Installation | undefined
11 onClose: () => void
12 onSuccess: () => void
13}
14
15export function PromoteInstallationModal({
16 appToPromote,
17 currentInstallation,
18 onClose,
19 onSuccess,
20}: PromoteInstallationModalProps) {
21 const { slug, apps, addInstallation, removeInstallation } = usePrivateApps()
22
23 const currentApp = apps.find((a) => a.id === currentInstallation?.app_id)
24
25 const { mutate: installApp, isPending: isInstalling } = usePlatformAppInstallationCreateMutation({
26 onSuccess: (data) => {
27 if (data) addInstallation(data, 'all')
28 toast.success(`"${appToPromote?.name}" is now the installed app`)
29 onSuccess()
30 onClose()
31 },
32 onError: (error) => {
33 toast.error(`Failed to install app: ${error.message}`)
34 },
35 })
36
37 const { mutate: uninstallApp, isPending: isUninstalling } =
38 usePlatformAppInstallationDeleteMutation({
39 onSuccess: (_, vars) => {
40 removeInstallation(vars.installationId)
41 if (!slug || !appToPromote) return
42 installApp({ slug, app_id: appToPromote.id })
43 },
44 onError: (error) => {
45 toast.error(`Failed to uninstall current app: ${error.message}`)
46 },
47 })
48
49 function handleConfirm() {
50 if (!slug || !appToPromote) return
51
52 if (currentInstallation) {
53 uninstallApp({ slug, installationId: currentInstallation.id })
54 } else {
55 installApp({ slug, app_id: appToPromote.id })
56 }
57 }
58
59 const isLoading = isUninstalling || isInstalling
60
61 return (
62 <ConfirmationModal
63 visible={appToPromote !== undefined}
64 title={currentInstallation ? 'Replace installed app?' : `Install "${appToPromote?.name}"?`}
65 confirmLabel={currentInstallation ? 'Replace' : 'Install'}
66 confirmLabelLoading={currentInstallation ? 'Replacing...' : 'Installing...'}
67 onCancel={onClose}
68 onConfirm={handleConfirm}
69 loading={isLoading}
70 >
71 <p className="text-sm text-foreground-light py-2">
72 {currentInstallation ? (
73 <>
74 This will replace <strong>{currentApp?.name ?? currentInstallation.app_id}</strong> with{' '}
75 <strong>{appToPromote?.name}</strong> as the installed app. Any tokens generated through
76 the current installation will stop working.
77 </>
78 ) : (
79 <>
80 <strong>{appToPromote?.name}</strong> will be installed for this organization.
81 </>
82 )}
83 </p>
84 </ConfirmationModal>
85 )
86}