1
1
import React , { Component , Fragment } from "react"
2
+ import { Redirect , Link } from 'react-router-dom' ;
3
+ import axios from 'axios'
2
4
3
5
import 'bootstrap/dist/css/bootstrap.min.css'
6
+ import { Input , Button , Popover , PopoverHeader , PopoverBody } from 'reactstrap' ;
7
+
4
8
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
5
9
import { faTimes } from '@fortawesome/free-solid-svg-icons'
6
10
import './styles/app.css'
@@ -10,23 +14,41 @@ import AsyncSelect from 'react-select/async'
10
14
import moment from 'moment-timezone'
11
15
12
16
import countriesData from '../data/country.json'
13
-
14
- // import countriesV2 from '../timezone-data/output.json'
15
17
import countriesV2 from '../data/output_15k.json'
16
18
17
- const setLocal = ( key , value ) => {
18
- localStorage . setItem ( key , JSON . stringify ( value ) )
19
- }
19
+ import { setLocal , makeUnique , isValidName , isNameValid } from './helpers'
20
20
21
- const makeUnique = ( items ) => {
22
- const arr = [ ]
23
- return items . filter ( ( i ) => {
24
- if ( ! arr . includes ( i . country ) ) {
25
- arr . push ( i . country )
26
- return true
21
+ const saveData = async ( teamName , data ) => {
22
+ const options = {
23
+ method : 'POST' ,
24
+ url : `https://f23le7ruh6.execute-api.ap-south-1.amazonaws.com/dev/write-doc?name=${ teamName } ` ,
25
+ data : data
27
26
}
28
- return false
29
- } )
27
+
28
+ return axios ( options ) . then ( ( res ) => {
29
+ console . log ( res . data )
30
+ return true
31
+ } ) . catch ( ( e ) => {
32
+ console . log ( 'Error in saving ' , e )
33
+ return false
34
+ } )
35
+ }
36
+
37
+ const readLists = async ( teamName ) => {
38
+ return axios . get ( `https://f23le7ruh6.execute-api.ap-south-1.amazonaws.com/dev/read-doc?name=${ teamName } ` )
39
+ . then ( ( res ) => {
40
+ if ( res . status === 200 ) {
41
+ if ( res . data && res . data . response && res . data . response . zones ) {
42
+ console . log ( res . data . response . zones )
43
+ return res . data . response . zones
44
+ }
45
+ return null
46
+ }
47
+ return null
48
+ } )
49
+ . catch ( ( e ) => {
50
+ return null
51
+ } )
30
52
}
31
53
32
54
const countryName = ( code = "IN" ) => countriesData . countries [ code . toUpperCase ( ) ] . name
@@ -35,26 +57,31 @@ const countryName = (code = "IN") => countriesData.countries[code.toUpperCase()]
35
57
class App extends Component {
36
58
constructor ( props ) {
37
59
super ( props )
38
- const listsFromLocal = localStorage . getItem ( 'items' )
39
- const lists = listsFromLocal ? JSON . parse ( listsFromLocal ) : [ { "country" : "Chennai - India" , "timeZone" : "Asia/Kolkata" } ]
60
+
61
+ const lists = [ ]
40
62
const countries = countriesV2
41
63
const options = [ ]
42
- // const options = Object.values(countries.countries).map((country) => {
43
- // return {
44
- // value: `${country.abbr} - ${country.code}`,
45
- // label: country.name,
46
- // timeZone: country.zones[0],
47
- // }
48
- // })
49
64
50
65
this . state = {
51
66
options : options ,
52
67
lists : lists ,
53
- value : ""
68
+ value : "" ,
69
+ popover : false ,
70
+ shareButton : false ,
71
+ shareButtonText : "Share" ,
72
+ shareError : "" ,
73
+ redirect : false ,
54
74
}
75
+
55
76
this . handleCountry = this . handleCountry . bind ( this )
56
77
this . loadOptions = this . loadOptions . bind ( this )
57
78
this . deleteCountry = this . deleteCountry . bind ( this )
79
+ this . handleForm = this . handleForm . bind ( this )
80
+ this . toggle = this . toggle . bind ( this )
81
+ }
82
+
83
+ toggle ( ) {
84
+ this . setState ( { popover : ! this . state . popover } )
58
85
}
59
86
60
87
handleCountry ( e ) {
@@ -65,17 +92,71 @@ class App extends Component {
65
92
lists : [ ...new Set ( this . state . lists ) ] ,
66
93
value : ""
67
94
} , ( ) => {
68
- setLocal ( 'items' , this . state . lists )
95
+ if ( this . props . fromTeam &&
96
+ this . props . match &&
97
+ this . props . match . params &&
98
+ this . props . match . params . id ) {
99
+ const teamName = this . props . match . params . id
100
+ saveData ( teamName , this . state . lists )
101
+ . catch ( e => console . log ( e ) )
102
+ } else if ( ! this . props . fromTeam ) {
103
+ setLocal ( 'items' , this . state . lists )
104
+ }
69
105
} )
70
106
}
71
107
72
108
deleteCountry ( name ) {
73
109
const lists = this . state . lists . filter ( l => l . country != name )
74
110
this . setState ( { lists : lists } , ( ) => {
75
- setLocal ( 'items' , this . state . lists )
111
+ if ( this . props . fromTeam &&
112
+ this . props . match &&
113
+ this . props . match . params &&
114
+ this . props . match . params . id ) {
115
+ const teamName = this . props . match . params . id
116
+ saveData ( teamName , this . state . lists )
117
+ . catch ( e => console . log ( e ) )
118
+ } else if ( ! this . props . fromTeam ) {
119
+ setLocal ( 'items' , this . state . lists )
120
+ }
76
121
} )
77
122
}
78
123
124
+ async handleForm ( e ) {
125
+ e . preventDefault ( )
126
+ this . setState ( { shareButton : true , shareButtonText : "Creating link..!" } )
127
+
128
+ const formData = new FormData ( e . target )
129
+ const teamName = formData . get ( 'teamName' )
130
+
131
+ const isRegexValid = isNameValid ( teamName )
132
+
133
+ if ( ! isRegexValid ) {
134
+ this . setState ( { shareError : "Name can only be alpha numeric..!" , shareButton : false , shareButtonText : "Share" } )
135
+ return
136
+ }
137
+
138
+ const isValid = await isValidName ( teamName )
139
+
140
+ if ( ! isValid ) {
141
+ this . setState ( { shareError : "Name is already taken. Please try someother name" , shareButton : false , shareButtonText : "Share" } )
142
+ return
143
+ }
144
+
145
+ const listsFromLocal = localStorage . getItem ( 'items' )
146
+ const lists = listsFromLocal ? JSON . parse ( listsFromLocal ) : [ { "country" :"Chennai - India" , "timeZone" :"Asia/Kolkata" } ]
147
+
148
+ console . log ( 'Share with others' , teamName )
149
+
150
+ const isSaveData = await saveData ( teamName , lists )
151
+
152
+ if ( ! isSaveData ) {
153
+ this . setState ( { shareError : "Some other occured. Please try again later..!" , shareButton : false , shareButtonText : "Share" } )
154
+ return
155
+ }
156
+
157
+ this . setState ( { redirect : true , teamName : teamName } )
158
+ }
159
+
79
160
loadOptions ( input , callback ) {
80
161
const countries = countriesV2
81
162
const reg = new RegExp ( `^${ input } ` , "gi" )
@@ -89,7 +170,18 @@ class App extends Component {
89
170
callback ( output )
90
171
}
91
172
92
- componentDidMount ( ) {
173
+ async componentDidMount ( ) {
174
+ let lists = [ ]
175
+ if ( this . props . match && this . props . match . params && this . props . match . params . id ) {
176
+ const savedData = await readLists ( this . props . match . params . id )
177
+ if ( savedData ) lists = savedData
178
+ } else {
179
+ const listsFromLocal = localStorage . getItem ( 'items' )
180
+ lists = listsFromLocal ? JSON . parse ( listsFromLocal ) : [ { "country" :"Chennai - India" , "timeZone" :"Asia/Kolkata" } ]
181
+ }
182
+
183
+ this . setState ( { lists : lists } )
184
+
93
185
this . interval = setInterval ( ( ) => {
94
186
this . setState ( { lists : this . state . lists } )
95
187
} , 1000 )
@@ -100,12 +192,34 @@ class App extends Component {
100
192
}
101
193
102
194
render ( ) {
195
+ if ( this . state . redirect ) {
196
+ window . location = `/team/${ this . state . teamName } `
197
+ }
103
198
return (
104
199
< div className = "container" >
105
200
< div className = "row" >
106
201
< div className = "col-md-10 offset-md-1" >
107
202
< h3 className = "text-center" id = "title" > TimeZone Track </ h3 >
108
- < AsyncSelect id = "country" className = "text-center" cacheOptions loadOptions = { this . loadOptions } placeholder = { "Search for your City" } onChange = { this . handleCountry } noOptionsMessage = { ( ) => "Search for your City" } value = { this . state . value } />
203
+
204
+ < div id = "country" className = "" >
205
+ < Button id = "share" type = "button" color = "primary" className = { `${ this . props . fromTeam ? 'd-none' : '' } ` } >
206
+ Share this page with your team
207
+ </ Button >
208
+
209
+ < Popover placement = "bottom" isOpen = { this . state . popover } target = "share" fade = { false } toggle = { this . toggle } >
210
+ < PopoverHeader > Share with your team</ PopoverHeader >
211
+ < PopoverBody >
212
+ < form onSubmit = { this . handleForm } >
213
+ < Input type = "text" placeholder = "Enter some unique name" name = "teamName" autoFocus = { true } />
214
+ < p id = "share-error-red" > { this . state . shareError } </ p >
215
+ < Input type = "submit" value = { this . state . shareButtonText } className = "btn btn-outline-primary" disabled = { this . state . shareButton } />
216
+ </ form >
217
+ </ PopoverBody >
218
+ </ Popover >
219
+
220
+ < AsyncSelect className = "text-center" cacheOptions loadOptions = { this . loadOptions } placeholder = { "Search for your City" } onChange = { this . handleCountry } noOptionsMessage = { ( ) => "Search for your City" } value = { this . state . value } />
221
+ </ div >
222
+
109
223
< List lists = { this . state . lists } deleteCountry = { this . deleteCountry } />
110
224
</ div >
111
225
</ div >
@@ -128,11 +242,18 @@ class List extends Component {
128
242
< Card countryName = { list . country } timezone = { list . timeZone } deleteCountry = { this . props . deleteCountry } key = { list . country } />
129
243
)
130
244
} )
131
- return (
132
- < div className = "cards" >
133
- { lists }
134
- </ div >
135
- )
245
+
246
+ if ( lists . length > 0 ) {
247
+ return (
248
+ < div className = "cards" >
249
+ { lists }
250
+ </ div >
251
+ )
252
+ } else {
253
+ return (
254
+ < h5 className = "text-center" id = "loading" > Loading..! </ h5 >
255
+ )
256
+ }
136
257
}
137
258
}
138
259
0 commit comments