11import React , { useState , useEffect , useCallback } from "react" ;
22import { useWizard } from "../../../../contexts/WizardModeContext" ;
3- import AppInstallationStatus from "./AppInstallationStatus" ;
3+ import { useSettings } from "../../../../contexts/SettingsContext" ;
4+ import { useAuth } from "../../../../contexts/AuthContext" ;
5+ import { useQuery } from "@tanstack/react-query" ;
6+ import { XCircle , CheckCircle , Loader2 } from "lucide-react" ;
47import { NextButtonConfig } from "../types" ;
5- import { State } from "../../../../types" ;
8+ import { State , AppInstallStatus } from "../../../../types" ;
9+ import ErrorMessage from "../shared/ErrorMessage" ;
610
711interface AppInstallationPhaseProps {
812 onNext : ( ) => void ;
@@ -11,13 +15,38 @@ interface AppInstallationPhaseProps {
1115}
1216
1317const AppInstallationPhase : React . FC < AppInstallationPhaseProps > = ( { onNext, setNextButtonConfig, onStateChange } ) => {
14- const { text } = useWizard ( ) ;
18+ const { text, target } = useWizard ( ) ;
19+ const { settings } = useSettings ( ) ;
20+ const { token } = useAuth ( ) ;
21+ const [ isPolling , setIsPolling ] = useState ( true ) ;
1522 const [ installationComplete , setInstallationComplete ] = useState ( false ) ;
1623 const [ installationSuccess , setInstallationSuccess ] = useState ( false ) ;
24+ const themeColor = settings . themeColor ;
25+
26+ // Query to poll app installation status
27+ const { data : appInstallStatus , error : appStatusError } = useQuery < AppInstallStatus , Error > ( {
28+ queryKey : [ "appInstallationStatus" ] ,
29+ queryFn : async ( ) => {
30+ const response = await fetch ( `/api/${ target } /install/app/status` , {
31+ headers : {
32+ "Content-Type" : "application/json" ,
33+ Authorization : `Bearer ${ token } ` ,
34+ } ,
35+ } ) ;
36+ if ( ! response . ok ) {
37+ const errorData = await response . json ( ) . catch ( ( ) => ( { } ) ) ;
38+ throw new Error ( errorData . message || "Failed to get app installation status" ) ;
39+ }
40+ return response . json ( ) as Promise < AppInstallStatus > ;
41+ } ,
42+ enabled : isPolling ,
43+ refetchInterval : 2000 ,
44+ } ) ;
1745
1846 const handleInstallationComplete = useCallback ( ( success : boolean ) => {
1947 setInstallationComplete ( true ) ;
2048 setInstallationSuccess ( success ) ;
49+ setIsPolling ( false ) ;
2150 onStateChange ( success ? 'Succeeded' : 'Failed' ) ;
2251 } , [ ] ) ;
2352
@@ -26,6 +55,15 @@ const AppInstallationPhase: React.FC<AppInstallationPhaseProps> = ({ onNext, set
2655 onStateChange ( 'Running' ) ;
2756 } , [ ] ) ;
2857
58+ // Handle status changes
59+ useEffect ( ( ) => {
60+ if ( appInstallStatus ?. status ?. state === "Succeeded" ) {
61+ handleInstallationComplete ( true ) ;
62+ } else if ( appInstallStatus ?. status ?. state === "Failed" ) {
63+ handleInstallationComplete ( false ) ;
64+ }
65+ } , [ appInstallStatus , handleInstallationComplete ] ) ;
66+
2967 // Update next button configuration
3068 useEffect ( ( ) => {
3169 setNextButtonConfig ( {
@@ -34,16 +72,72 @@ const AppInstallationPhase: React.FC<AppInstallationPhaseProps> = ({ onNext, set
3472 } ) ;
3573 } , [ installationComplete , installationSuccess ] ) ;
3674
75+ const renderInstallationStatus = ( ) => {
76+ // Loading state
77+ if ( isPolling ) {
78+ return (
79+ < div className = "flex flex-col items-center justify-center py-12" data-testid = "app-installation-loading" >
80+ < Loader2 className = "w-8 h-8 animate-spin mb-4" style = { { color : themeColor } } />
81+ < p className = "text-lg font-medium text-gray-900" > Installing application...</ p >
82+ < p className = "text-sm text-gray-500 mt-2" data-testid = "app-installation-loading-description" >
83+ { appInstallStatus ?. status ?. description || "Please wait while we install your application." }
84+ </ p >
85+ </ div >
86+ ) ;
87+ }
88+
89+ // Success state
90+ if ( appInstallStatus ?. status ?. state === "Succeeded" ) {
91+ return (
92+ < div className = "flex flex-col items-center justify-center py-12" data-testid = "app-installation-success" >
93+ < div
94+ className = "w-12 h-12 rounded-full flex items-center justify-center mb-4"
95+ style = { { backgroundColor : `${ themeColor } 1A` } }
96+ >
97+ < CheckCircle className = "w-6 h-6" style = { { color : themeColor } } />
98+ </ div >
99+ < p className = "text-lg font-medium text-gray-900" > Application installed successfully!</ p >
100+ < p className = "text-sm text-gray-500 mt-2" > Your application is now ready to use.</ p >
101+ </ div >
102+ ) ;
103+ }
104+
105+ // Error state
106+ if ( appInstallStatus ?. status ?. state === "Failed" ) {
107+ return (
108+ < div className = "flex flex-col items-center justify-center py-12" data-testid = "app-installation-error" >
109+ < div className = "w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mb-4" >
110+ < XCircle className = "w-6 h-6 text-red-600" />
111+ </ div >
112+ < p className = "text-lg font-medium text-gray-900" > Application installation failed</ p >
113+ < p className = "text-sm text-gray-500 mt-2" data-testid = "app-installation-error-message" >
114+ { appInstallStatus ?. status ?. description || "An error occurred during installation." }
115+ </ p >
116+ </ div >
117+ ) ;
118+ }
119+
120+ // Default loading state
121+ return (
122+ < div className = "flex flex-col items-center justify-center py-12" >
123+ < Loader2 className = "w-8 h-8 animate-spin mb-4" style = { { color : themeColor } } />
124+ < p className = "text-lg font-medium text-gray-900" > Preparing installation...</ p >
125+ </ div >
126+ ) ;
127+ } ;
128+
37129 return (
38130 < div className = "space-y-6" >
39131 < div className = "mb-6" >
40132 < h2 className = "text-2xl font-bold text-gray-900" > { text . appInstallationTitle } </ h2 >
41133 < p className = "text-gray-600 mt-1" > { text . appInstallationDescription } </ p >
42134 </ div >
43135
44- < AppInstallationStatus onComplete = { handleInstallationComplete } />
136+ { renderInstallationStatus ( ) }
137+
138+ { appStatusError && < ErrorMessage error = { appStatusError ?. message } /> }
45139 </ div >
46140 ) ;
47141} ;
48142
49- export default AppInstallationPhase ;
143+ export default AppInstallationPhase ;
0 commit comments