1- import { useEffect , useState } from 'react' ;
1+ import { useEffect , useState , MouseEvent } from 'react' ;
2+ import styled from 'styled-components' ;
23import {
34 CssBaseline ,
45 Container ,
56 Box ,
67 AppBar ,
78 Toolbar ,
9+ Menu ,
10+ MenuItem ,
811 Typography ,
912 Button ,
13+ IconButton ,
14+ FormControl ,
15+ InputLabel ,
16+ TextField ,
17+ Select ,
18+ Backdrop ,
19+ Dialog ,
20+ DialogActions ,
21+ DialogContent ,
22+ DialogTitle ,
23+ Fade ,
1024} from '@mui/material' ;
1125import { makeStyles } from '@mui/styles'
26+ import AddIcon from '@mui/icons-material/Add' ;
27+ import AccountCircleIcon from '@mui/icons-material/AccountCircle' ;
1228import { User } from '@firebase/auth' ;
13- import { ref , onValue , DataSnapshot } from '@firebase/database' ;
29+ import { ref , set , onValue , DataSnapshot } from '@firebase/database' ;
1430
1531import { AuthProvider } from '@/lib/AuthProvider' ;
1632import { auth , db } from '@/lib/firebase' ;
@@ -72,11 +88,86 @@ const Widgets = () => {
7288 }
7389 </ div >
7490 ) ;
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+ } ;
76164
77165const AdminIndexPage = ( ) => {
78166 const classes = useStyles ( ) ;
79167 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 ) ;
80171
81172 useEffect ( ( ) => {
82173 auth . onAuthStateChanged ( ( user ) => {
@@ -85,13 +176,22 @@ const AdminIndexPage = () => {
85176 } ) ;
86177
87178 const signout = async ( ) => {
179+ setAnchorEl ( null ) ;
88180 try {
89181 await auth . signOut ( ) ;
90182 } catch ( err ) {
91183 alert ( err . message ) ;
92184 }
93185 } ;
94186
187+ const userMenuId = 'user-menu' ;
188+ const handleUserMenuOpen = ( event : MouseEvent < HTMLElement > ) => {
189+ setAnchorEl ( event . currentTarget ) ;
190+ } ;
191+ const handleUserMenuClose = ( ) => {
192+ setAnchorEl ( null ) ;
193+ } ;
194+
95195 return currentUser !== null ? (
96196 < AuthProvider >
97197 < CssBaseline />
@@ -101,12 +201,42 @@ const AdminIndexPage = () => {
101201 < Typography variant = "h6" className = { classes . title } >
102202 Admin
103203 </ 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 >
108224 </ Toolbar >
109225 </ 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+ />
110240
111241 < Container className = { classes . content } >
112242 < Box my = { 4 } >
0 commit comments