1
+ import React , { useState } from "react" ;
2
+ import {
3
+ Typography ,
4
+ Switch ,
5
+ Button ,
6
+ Tag ,
7
+ Tooltip ,
8
+ Row ,
9
+ Col ,
10
+ Statistic ,
11
+ Avatar ,
12
+ Space ,
13
+ Divider ,
14
+ Card ,
15
+ Dropdown ,
16
+ Menu
17
+ } from "antd" ;
18
+ import {
19
+ CloudUploadOutlined ,
20
+ SettingOutlined ,
21
+ TeamOutlined ,
22
+ AppstoreOutlined ,
23
+ DatabaseOutlined ,
24
+ CodeOutlined ,
25
+ CloudServerOutlined ,
26
+ ClockCircleOutlined ,
27
+ MoreOutlined ,
28
+ StarOutlined ,
29
+ StarFilled
30
+ } from "@ant-design/icons" ;
31
+ import { Environment } from "../types/environment.types" ;
32
+ import { Workspace } from "../types/workspace.types" ;
33
+ import styled from "styled-components" ;
34
+
35
+ const { Title, Text } = Typography ;
36
+
37
+ // Styled components for custom design
38
+ const HeaderWrapper = styled . div `
39
+ border-radius: 12px;
40
+ overflow: hidden;
41
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
42
+ position: relative;
43
+ margin-bottom: 24px;
44
+ ` ;
45
+
46
+ const GradientBanner = styled . div `
47
+ background: linear-gradient(135deg, #2b5876 0%, #4e4376 100%);
48
+ height: 140px;
49
+ position: relative;
50
+ overflow: hidden;
51
+
52
+ &::before {
53
+ content: '';
54
+ position: absolute;
55
+ top: -50%;
56
+ left: -50%;
57
+ width: 200%;
58
+ height: 200%;
59
+ background: repeating-linear-gradient(
60
+ 45deg,
61
+ rgba(255,255,255,0.1),
62
+ rgba(255,255,255,0.1) 1px,
63
+ transparent 1px,
64
+ transparent 10px
65
+ );
66
+ animation: moveBackground 30s linear infinite;
67
+ }
68
+
69
+ @keyframes moveBackground {
70
+ 0% {
71
+ transform: translate(0, 0);
72
+ }
73
+ 100% {
74
+ transform: translate(100px, 100px);
75
+ }
76
+ }
77
+ ` ;
78
+
79
+ const ContentContainer = styled . div `
80
+ background-color: white;
81
+ padding: 24px;
82
+ position: relative;
83
+ ` ;
84
+
85
+ const AvatarContainer = styled . div `
86
+ position: absolute;
87
+ top: -50px;
88
+ left: 24px;
89
+ background: white;
90
+ padding: 4px;
91
+ border-radius: 16px;
92
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
93
+ ` ;
94
+
95
+ const StatusBadge = styled ( Tag ) < { $active ?: boolean } > `
96
+ position: absolute;
97
+ top: 12px;
98
+ right: 12px;
99
+ font-weight: 600;
100
+ font-size: 12px;
101
+ padding: 4px 12px;
102
+ border-radius: 20px;
103
+ border: none;
104
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
105
+ background: ${ props => props . $active ? 'linear-gradient(135deg, #52c41a, #389e0d)' : '#f0f0f0' } ;
106
+ color: ${ props => props . $active ? 'white' : '#666' } ;
107
+ ` ;
108
+
109
+ const StatCard = styled ( Card ) `
110
+ border-radius: 8px;
111
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
112
+ transition: all 0.3s;
113
+
114
+ &:hover {
115
+ transform: translateY(-3px);
116
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
117
+ }
118
+ ` ;
119
+
120
+ const ActionButton = styled ( Button ) `
121
+ border-radius: 8px;
122
+ display: flex;
123
+ align-items: center;
124
+ justify-content: center;
125
+ height: 38px;
126
+ ` ;
127
+
128
+ const FavoriteButton = styled ( Button ) `
129
+ position: absolute;
130
+ top: 12px;
131
+ right: 80px;
132
+ border: none;
133
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
134
+ ` ;
135
+
136
+ interface WorkspaceHeaderProps {
137
+ workspace : Workspace ;
138
+ environment : Environment ;
139
+ isToggling : boolean ;
140
+ onToggleManagedStatus : ( checked : boolean ) => Promise < void > ;
141
+ onDeploy : ( ) => void ;
142
+ }
143
+
144
+ const WorkspaceHeader : React . FC < WorkspaceHeaderProps > = ( {
145
+ workspace,
146
+ environment,
147
+ isToggling,
148
+ onToggleManagedStatus,
149
+ onDeploy
150
+ } ) => {
151
+
152
+ // Generate a consistent color for the workspace avatar
153
+ const getAvatarColor = ( name : string ) => {
154
+ let hash = 0 ;
155
+ for ( let i = 0 ; i < name . length ; i ++ ) {
156
+ hash = name . charCodeAt ( i ) + ( ( hash << 5 ) - hash ) ;
157
+ }
158
+ const hue = Math . abs ( hash % 360 ) ;
159
+ return `hsl(${ hue } , 70%, 50%)` ;
160
+ } ;
161
+
162
+ // Format date for last updated
163
+ const formatDate = ( date : number | undefined ) => {
164
+ if ( ! date ) return "N/A" ;
165
+ return new Date ( date ) . toLocaleDateString ( "en-US" , {
166
+ month : "short" ,
167
+ day : "numeric" ,
168
+ year : "numeric"
169
+ } ) ;
170
+ } ;
171
+
172
+ // Mock data - in a real app this would come from props
173
+ const stats = {
174
+ users : 12 ,
175
+ apps : 24 ,
176
+ datasources : 8 ,
177
+ queries : 15 ,
178
+ lastUpdated : "2023-08-15T10:30:00Z"
179
+ } ;
180
+
181
+
182
+
183
+ return (
184
+ < HeaderWrapper >
185
+ < GradientBanner >
186
+ < StatusBadge $active = { workspace . managed } >
187
+ { workspace . managed ? "Managed" : "Unmanaged" }
188
+ </ StatusBadge >
189
+
190
+ </ GradientBanner >
191
+
192
+ < ContentContainer >
193
+ < AvatarContainer >
194
+ < Avatar
195
+ size = { 80 }
196
+ style = { { backgroundColor : getAvatarColor ( workspace . name ) } }
197
+ >
198
+ { workspace . name . charAt ( 0 ) . toUpperCase ( ) }
199
+ </ Avatar >
200
+ </ AvatarContainer >
201
+
202
+ < Row >
203
+ < Col xs = { 24 } md = { 14 } style = { { paddingLeft : '90px' , marginBottom : '20px' } } >
204
+ < Title level = { 3 } style = { { margin : "0 0 8px 0" } } >
205
+ { workspace . name }
206
+ </ Title >
207
+ < Space size = { 16 } wrap >
208
+ < Text type = "secondary" > ID: { workspace . id } </ Text >
209
+ < Text type = "secondary" >
210
+ < ClockCircleOutlined style = { { marginRight : 4 } } />
211
+ created on { formatDate ( workspace . creationDate ) }
212
+ </ Text >
213
+ < Tag color = "blue" >
214
+ < CloudServerOutlined /> { environment . environmentName }
215
+ </ Tag >
216
+ </ Space >
217
+ </ Col >
218
+
219
+ < Col xs = { 24 } md = { 10 } >
220
+ < div style = { { display : "flex" , justifyContent : "flex-end" , gap : "12px" , flexWrap : "wrap" } } >
221
+ < div style = { { display : "flex" , alignItems : "center" } } >
222
+ < Text style = { { marginRight : "8px" } } > Managed:</ Text >
223
+ < Switch
224
+ checked = { ! ! workspace . managed }
225
+ onChange = { onToggleManagedStatus }
226
+ loading = { isToggling }
227
+ style = { { marginRight : 16 } }
228
+ />
229
+ </ div >
230
+ < Tooltip
231
+ title = {
232
+ ! workspace . managed
233
+ ? "Workspace must be managed before it can be deployed"
234
+ : "Deploy this workspace to another environment"
235
+ }
236
+ >
237
+ < ActionButton
238
+ type = "primary"
239
+ icon = { < CloudUploadOutlined /> }
240
+ onClick = { onDeploy }
241
+ disabled = { ! workspace . managed }
242
+ >
243
+ Deploy
244
+ </ ActionButton >
245
+ </ Tooltip >
246
+ </ div >
247
+ </ Col >
248
+ </ Row >
249
+
250
+
251
+
252
+ </ ContentContainer >
253
+ </ HeaderWrapper >
254
+ ) ;
255
+ } ;
256
+
257
+ export default WorkspaceHeader ;
0 commit comments