PromoteInstallationModal.tsx 2.9 KB

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