1+ export default function FailoverPage ( ) {
2+ const recoveryEvents = [
3+ {
4+ id : 1 ,
5+ type : 'failover' ,
6+ provider : 'Forgejo' ,
7+ fallbackProvider : 'GitHub' ,
8+ reason : 'Connection timeout' ,
9+ affectedRepos : 12 ,
10+ timestamp : '2 hours ago' ,
11+ status : 'resolved' ,
12+ duration : '15 minutes'
13+ } ,
14+ {
15+ id : 2 ,
16+ type : 'recovery' ,
17+ provider : 'GitLab' ,
18+ fallbackProvider : null ,
19+ reason : 'Service restored' ,
20+ affectedRepos : 45 ,
21+ timestamp : '6 hours ago' ,
22+ status : 'completed' ,
23+ duration : '2 minutes'
24+ } ,
25+ {
26+ id : 3 ,
27+ type : 'failover' ,
28+ provider : 'Custom Git Server' ,
29+ fallbackProvider : 'GitLab' ,
30+ reason : 'HTTP 503 Service Unavailable' ,
31+ affectedRepos : 8 ,
32+ timestamp : '1 day ago' ,
33+ status : 'resolved' ,
34+ duration : '45 minutes'
35+ }
36+ ] ;
37+
38+ const backupStatus = {
39+ lastBackup : '30 minutes ago' ,
40+ backupSize : '2.4 GB' ,
41+ totalRepos : 156 ,
42+ incrementalEnabled : true ,
43+ nextScheduled : 'in 30 minutes'
44+ } ;
45+
46+ return (
47+ < div >
48+ < div className = "mb-8" >
49+ < h1 className = "text-2xl font-bold text-gray-900 dark:text-white" >
50+ Failover & Recovery
51+ </ h1 >
52+ < p className = "mt-1 text-sm text-gray-500 dark:text-gray-400" >
53+ Monitor failover events and manage recovery procedures
54+ </ p >
55+ </ div >
56+
57+ { /* Alert Banner */ }
58+ < div className = "mb-6 rounded-md bg-yellow-50 dark:bg-yellow-900/20 p-4" >
59+ < div className = "flex" >
60+ < div className = "flex-shrink-0" >
61+ < svg className = "h-5 w-5 text-yellow-400" fill = "none" viewBox = "0 0 24 24" stroke = "currentColor" >
62+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = "2" d = "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
63+ </ svg >
64+ </ div >
65+ < div className = "ml-3" >
66+ < h3 className = "text-sm font-medium text-yellow-800 dark:text-yellow-200" >
67+ Failover Configuration Active
68+ </ h3 >
69+ < div className = "mt-2 text-sm text-yellow-700 dark:text-yellow-300" >
70+ < p >
71+ Automatic failover is enabled. Failed syncs will be redirected to available providers.
72+ </ p >
73+ </ div >
74+ </ div >
75+ </ div >
76+ </ div >
77+
78+ { /* Failover Configuration */ }
79+ < div className = "mb-8 grid grid-cols-1 gap-6 lg:grid-cols-2" >
80+ { /* Failover Rules */ }
81+ < div className = "overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow" >
82+ < div className = "p-6" >
83+ < h3 className = "text-lg font-medium text-gray-900 dark:text-white" >
84+ Failover Rules
85+ </ h3 >
86+ < div className = "mt-4 space-y-4" >
87+ < div className = "flex items-center justify-between" >
88+ < div >
89+ < p className = "text-sm font-medium text-gray-900 dark:text-white" >
90+ Primary → Fallback Priority
91+ </ p >
92+ < p className = "text-sm text-gray-500 dark:text-gray-400" >
93+ GitHub → GitLab → Forgejo → Local Backup
94+ </ p >
95+ </ div >
96+ < button className = "text-sm text-blue-600 hover:text-blue-500" >
97+ Edit
98+ </ button >
99+ </ div >
100+ < div className = "flex items-center justify-between" >
101+ < div >
102+ < p className = "text-sm font-medium text-gray-900 dark:text-white" >
103+ Retry Attempts
104+ </ p >
105+ < p className = "text-sm text-gray-500 dark:text-gray-400" >
106+ 3 attempts with exponential backoff
107+ </ p >
108+ </ div >
109+ < button className = "text-sm text-blue-600 hover:text-blue-500" >
110+ Edit
111+ </ button >
112+ </ div >
113+ < div className = "flex items-center justify-between" >
114+ < div >
115+ < p className = "text-sm font-medium text-gray-900 dark:text-white" >
116+ Health Check Interval
117+ </ p >
118+ < p className = "text-sm text-gray-500 dark:text-gray-400" >
119+ Every 60 seconds
120+ </ p >
121+ </ div >
122+ < button className = "text-sm text-blue-600 hover:text-blue-500" >
123+ Edit
124+ </ button >
125+ </ div >
126+ </ div >
127+ </ div >
128+ </ div >
129+
130+ { /* Backup Status */ }
131+ < div className = "overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow" >
132+ < div className = "p-6" >
133+ < h3 className = "text-lg font-medium text-gray-900 dark:text-white" >
134+ Local Backup Status
135+ </ h3 >
136+ < div className = "mt-4 space-y-3" >
137+ < div className = "flex justify-between" >
138+ < span className = "text-sm text-gray-500 dark:text-gray-400" > Last Backup</ span >
139+ < span className = "text-sm font-medium text-gray-900 dark:text-white" >
140+ { backupStatus . lastBackup }
141+ </ span >
142+ </ div >
143+ < div className = "flex justify-between" >
144+ < span className = "text-sm text-gray-500 dark:text-gray-400" > Backup Size</ span >
145+ < span className = "text-sm font-medium text-gray-900 dark:text-white" >
146+ { backupStatus . backupSize }
147+ </ span >
148+ </ div >
149+ < div className = "flex justify-between" >
150+ < span className = "text-sm text-gray-500 dark:text-gray-400" > Total Repositories</ span >
151+ < span className = "text-sm font-medium text-gray-900 dark:text-white" >
152+ { backupStatus . totalRepos }
153+ </ span >
154+ </ div >
155+ < div className = "flex justify-between" >
156+ < span className = "text-sm text-gray-500 dark:text-gray-400" > Next Scheduled</ span >
157+ < span className = "text-sm font-medium text-gray-900 dark:text-white" >
158+ { backupStatus . nextScheduled }
159+ </ span >
160+ </ div >
161+ < div className = "mt-4 flex space-x-3" >
162+ < button className = "flex-1 rounded-md bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-500" >
163+ Run Backup Now
164+ </ button >
165+ < button className = "flex-1 rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-600" >
166+ View Backups
167+ </ button >
168+ </ div >
169+ </ div >
170+ </ div >
171+ </ div >
172+ </ div >
173+
174+ { /* Recovery Events */ }
175+ < div >
176+ < h3 className = "text-lg font-medium text-gray-900 dark:text-white mb-4" >
177+ Recent Failover Events
178+ </ h3 >
179+ < div className = "overflow-hidden bg-white dark:bg-gray-800 shadow sm:rounded-md" >
180+ < ul className = "divide-y divide-gray-200 dark:divide-gray-700" >
181+ { recoveryEvents . map ( ( event ) => (
182+ < li key = { event . id } className = "px-4 py-4 sm:px-6" >
183+ < div className = "flex items-center justify-between" >
184+ < div className = "flex items-center" >
185+ < div className = "flex-shrink-0" >
186+ { event . type === 'failover' ? (
187+ < div className = "h-10 w-10 rounded-full bg-red-100 dark:bg-red-900 flex items-center justify-center" >
188+ < svg className = "h-6 w-6 text-red-600 dark:text-red-400" fill = "none" stroke = "currentColor" strokeWidth = "2" >
189+ < path strokeLinecap = "round" strokeLinejoin = "round" d = "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
190+ </ svg >
191+ </ div >
192+ ) : (
193+ < div className = "h-10 w-10 rounded-full bg-green-100 dark:bg-green-900 flex items-center justify-center" >
194+ < svg className = "h-6 w-6 text-green-600 dark:text-green-400" fill = "none" stroke = "currentColor" strokeWidth = "2" >
195+ < path strokeLinecap = "round" strokeLinejoin = "round" d = "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
196+ </ svg >
197+ </ div >
198+ ) }
199+ </ div >
200+ < div className = "ml-4" >
201+ < p className = "text-sm font-medium text-gray-900 dark:text-white" >
202+ { event . type === 'failover' ? 'Failover triggered' : 'Recovery completed' } for { event . provider }
203+ </ p >
204+ < p className = "text-sm text-gray-500 dark:text-gray-400" >
205+ { event . reason } • { event . affectedRepos } repositories affected
206+ { event . fallbackProvider && ` • Fallback: ${ event . fallbackProvider } ` }
207+ </ p >
208+ < p className = "text-xs text-gray-500 dark:text-gray-400 mt-1" >
209+ { event . timestamp } • Duration: { event . duration }
210+ </ p >
211+ </ div >
212+ </ div >
213+ < div className = "ml-2 flex-shrink-0" >
214+ < span className = { `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
215+ event . status === 'resolved'
216+ ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
217+ : 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200'
218+ } `} >
219+ { event . status . charAt ( 0 ) . toUpperCase ( ) + event . status . slice ( 1 ) }
220+ </ span >
221+ </ div >
222+ </ div >
223+ </ li >
224+ ) ) }
225+ </ ul >
226+ </ div >
227+ </ div >
228+ </ div >
229+ ) ;
230+ }
0 commit comments