1
- import { useEffect , useState } from 'react' ;
1
+ import { useEffect , useState , MouseEvent } from 'react' ;
2
+ import styled from 'styled-components' ;
2
3
import {
3
4
CssBaseline ,
4
5
Container ,
5
6
Box ,
6
7
AppBar ,
7
8
Toolbar ,
9
+ Menu ,
10
+ MenuItem ,
8
11
Typography ,
9
12
Button ,
13
+ IconButton ,
14
+ FormControl ,
15
+ InputLabel ,
16
+ TextField ,
17
+ Select ,
18
+ Backdrop ,
19
+ Dialog ,
20
+ DialogActions ,
21
+ DialogContent ,
22
+ DialogTitle ,
23
+ Fade ,
10
24
} from '@mui/material' ;
11
25
import { makeStyles } from '@mui/styles'
26
+ import AddIcon from '@mui/icons-material/Add' ;
27
+ import AccountCircleIcon from '@mui/icons-material/AccountCircle' ;
12
28
import { User } from '@firebase/auth' ;
13
- import { ref , onValue , DataSnapshot } from '@firebase/database' ;
29
+ import { ref , set , onValue , DataSnapshot } from '@firebase/database' ;
14
30
15
31
import { AuthProvider } from '@/lib/AuthProvider' ;
16
32
import { auth , db } from '@/lib/firebase' ;
@@ -72,11 +88,86 @@ const Widgets = () => {
72
88
}
73
89
</ div >
74
90
) ;
75
- }
91
+ } ;
92
+
93
+ const AddWidgetModel = ( { open, onClose } : { open : boolean , onClose : ( ) => void } ) => {
94
+ const [ widgetId , setWidgetId ] = useState ( "" ) ;
95
+ const [ widgetType , setWidgetType ] = useState ( "text" ) ;
96
+
97
+ const FormGroup = styled . div `
98
+ display: flex;
99
+ margin-bottom: 1rem;
100
+ & > div {
101
+ flex-grow: 1;
102
+ margin-left: 0.25rem;
103
+ }
104
+ ` ;
105
+
106
+ const style = {
107
+ display : 'flex' ,
108
+ flexDirection : 'column' ,
109
+ position : 'absolute' as 'absolute' ,
110
+ top : '50%' ,
111
+ left : '50%' ,
112
+ transform : 'translate(-50%, -50%)' ,
113
+ width : 640 ,
114
+ bgcolor : 'background.paper' ,
115
+ border : '1px solid #ddd' ,
116
+ borderRadius : '4px' ,
117
+ boxShadow : 24 ,
118
+ pt : 4 ,
119
+ px : 4 ,
120
+ pb : 3 ,
121
+ } ;
122
+
123
+ return (
124
+ < Dialog
125
+ open = { open }
126
+ onClose = { onClose }
127
+ >
128
+ < DialogTitle > Add Widget</ DialogTitle >
129
+ < DialogContent >
130
+ < FormGroup >
131
+ < FormControl variant = "standard" >
132
+ < TextField autoFocus fullWidth label = "ID" value = { widgetId } variant = "standard" onChange = { ( e ) => { setWidgetId ( e . target . value ) ; } } />
133
+ </ FormControl >
134
+ </ FormGroup >
135
+
136
+ < FormGroup >
137
+ < FormControl variant = "standard" >
138
+ < InputLabel id = "widget-type-label" > Widget</ InputLabel >
139
+ < Select
140
+ labelId = "widget-type-label"
141
+ id = "widget-type"
142
+ value = { widgetType }
143
+ label = "Widget"
144
+ onChange = { ( e ) => { setWidgetType ( e . target . value ) ; } }
145
+ >
146
+ < MenuItem value = { "text" } > Text</ MenuItem >
147
+ < MenuItem value = { "time" } > Time</ MenuItem >
148
+ < MenuItem value = { "iframe" } > IFrame</ MenuItem >
149
+ </ Select >
150
+ </ FormControl >
151
+ </ FormGroup >
152
+ </ DialogContent >
153
+ < DialogActions >
154
+ < Button color = "primary" variant = "contained" onClick = { ( ) => {
155
+ set ( ref ( db , `/widgets/${ widgetId } ` ) , {
156
+ name : widgetType ,
157
+ props : Editors [ widgetType ] . defaultProps
158
+ } ) ;
159
+ } } > Add</ Button >
160
+ </ DialogActions >
161
+ </ Dialog >
162
+ ) ;
163
+ } ;
76
164
77
165
const AdminIndexPage = ( ) => {
78
166
const classes = useStyles ( ) ;
79
167
const [ currentUser , setCurrentUser ] = useState < User | null > ( null ) ;
168
+ const [ anchorEl , setAnchorEl ] = useState < HTMLElement | null > ( null ) ;
169
+ const [ addWidgetModalOpened , setAddWidgetModalOpened ] = useState ( false ) ;
170
+ const isUserMenuOpen = Boolean ( anchorEl ) ;
80
171
81
172
useEffect ( ( ) => {
82
173
auth . onAuthStateChanged ( ( user ) => {
@@ -85,13 +176,22 @@ const AdminIndexPage = () => {
85
176
} ) ;
86
177
87
178
const signout = async ( ) => {
179
+ setAnchorEl ( null ) ;
88
180
try {
89
181
await auth . signOut ( ) ;
90
182
} catch ( err ) {
91
183
alert ( err . message ) ;
92
184
}
93
185
} ;
94
186
187
+ const userMenuId = 'user-menu' ;
188
+ const handleUserMenuOpen = ( event : MouseEvent < HTMLElement > ) => {
189
+ setAnchorEl ( event . currentTarget ) ;
190
+ } ;
191
+ const handleUserMenuClose = ( ) => {
192
+ setAnchorEl ( null ) ;
193
+ } ;
194
+
95
195
return currentUser !== null ? (
96
196
< AuthProvider >
97
197
< CssBaseline />
@@ -101,12 +201,42 @@ const AdminIndexPage = () => {
101
201
< Typography variant = "h6" className = { classes . title } >
102
202
Admin
103
203
</ Typography >
104
- < Typography > { currentUser . email } </ Typography >
105
- < Button color = "inherit" onClick = { signout } >
106
- Logout
107
- </ Button >
204
+ < Box sx = { { flexGrow : 1 } } />
205
+ < Box sx = { { display : { xs : 'none' , md : 'flex' } } } >
206
+ < IconButton
207
+ size = "large"
208
+ color = "inherit"
209
+ onClick = { ( ) => { setAddWidgetModalOpened ( true ) ; } }
210
+ >
211
+ < AddIcon />
212
+ </ IconButton >
213
+ < IconButton
214
+ size = "large"
215
+ color = "inherit"
216
+ edge = "end"
217
+ aria-controls = { userMenuId }
218
+ aria-haspopup = "true"
219
+ onClick = { handleUserMenuOpen }
220
+ >
221
+ < AccountCircleIcon />
222
+ </ IconButton >
223
+ </ Box >
108
224
</ Toolbar >
109
225
</ AppBar >
226
+ < Menu
227
+ id = { userMenuId }
228
+ anchorEl = { anchorEl }
229
+ open = { isUserMenuOpen }
230
+ onClose = { handleUserMenuClose }
231
+ >
232
+ < MenuItem color = "inherit" onClick = { signout } > Logout</ MenuItem >
233
+ </ Menu >
234
+ < AddWidgetModel
235
+ open = { addWidgetModalOpened }
236
+ onClose = { ( ) => {
237
+ setAddWidgetModalOpened ( false ) ;
238
+ } }
239
+ />
110
240
111
241
< Container className = { classes . content } >
112
242
< Box my = { 4 } >
0 commit comments