Skip to content

Commit 5fcf1d3

Browse files
committed
Modal windows remake & Data service update
1 parent 2b2f125 commit 5fcf1d3

File tree

7 files changed

+360
-194
lines changed

7 files changed

+360
-194
lines changed

src/App.css

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,3 @@
5050
transform: rotate(360deg);
5151
}
5252
}
53-
54-
.show_login {
55-
position:absolute;
56-
top:1em;
57-
right: 1em;
58-
font-size:small;
59-
color:lightgray;
60-
transition: 1s;
61-
}
62-

src/App.js

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ import Context from './context'
77
import Loader from './Content/Loader'
88
import ModalCardEdit from './Modal/ModalCardEdit'
99
import ModalLogin from './Modal/ModalLogin'
10-
import Modal from './Modal/Modal'
1110
import DataService from './DataService'
1211

13-
const { loadData, postData, setLogin } = DataService()
14-
12+
const { loadData, postData, setDataServLogin } = DataService()
1513
const testText = "My little cards-app c:"
1614

1715
var cardCount = 0
@@ -55,49 +53,69 @@ function checkCardFields(card) {
5553
return res
5654
}
5755

56+
var timer
57+
5858
function App() {
5959
const [cardsArr, setCards] = useCardsArr([])
6060
const [editCardId, setEditCardId] = React.useState(null)
61-
const [loading, setLoading] = React.useState(true)
61+
const [loading, setLoading] = React.useState(false)
6262
const [logged, setLogged] = React.useState(false)
63-
const [userName, setUserName] = React.useState(null)
64-
React.useEffect(clearIfUnlogged, [logged]) // eslint-disable-line react-hooks/exhaustive-deps
65-
React.useEffect(loadDataFromServer, [logged]) // eslint-disable-line react-hooks/exhaustive-deps
63+
const [userName, setUserName] = React.useState(undefined)
64+
65+
const [timerVal, setTimerVal] = React.useState(null)
66+
if (timer) clearInterval(timer)
67+
timer = setInterval(() => setTimerVal(Date.now()), 60 * 1000) // обновяем через минуту
68+
React.useEffect(onLogout, [logged, userName])// eslint-disable-line react-hooks/exhaustive-deps
69+
React.useEffect(loadDataFromServer, [logged, userName, timerVal]) // eslint-disable-line react-hooks/exhaustive-deps
6670
React.useEffect(loadDataToServer, [cardsArr]) // eslint-disable-line react-hooks/exhaustive-deps
71+
const [openLogin, setOpenLogin] = React.useState(false)
6772

6873
///////////
6974
function tryLogin(login) {
7075
return new Promise((res, rej) => {
71-
try {
72-
setLogin(login)
73-
.then((r => {
74-
setLogged(Boolean(r))
75-
setUserName(login)
76-
}), console.log)
77-
.then(res, rej)
78-
} catch (e) {
79-
rej(e)
80-
console.error(e)
81-
}
76+
tryLogout()
77+
.then(() => {
78+
setDataServLogin(login)
79+
.then(
80+
r => {
81+
setLogged(Boolean(r))
82+
setUserName(login)
83+
res(r)
84+
}
85+
)
86+
.catch(
87+
e => {
88+
console.log("setDataServLogin in Try login", "catch", e);
89+
rej(e)
90+
}
91+
)
92+
})
93+
.catch((e) => console.log("logout catch in tryLogin", e))
8294
})
8395
}
8496

85-
function dislogin() {
86-
if (logged) console.log("Dislogin")
87-
setLogged(null)
97+
function tryLogout() {
98+
return new Promise((res) => {
99+
if (logged) console.log("Dislogin")
100+
let result = setDataServLogin(null)
101+
setUserName(undefined)
102+
setLogged(false)
103+
result.then(onLogout, onLogout).then(res, res).then(onLogout).catch(e => console.log("Data service dislogif failed", e))
104+
})
88105
}
89106

90-
function clearIfUnlogged() {
91-
if (logged === null && cardsArr) deleteAll()
107+
function onLogout() {
108+
if (!logged && !!cardsArr) deleteAll()
92109
}
93110
///////////
94111

95112
///////////
96113
function loadDataToServer() {
97114
try {
98-
if (logged) postData(cardsArr).then((res) => {
99-
console.log('[onPostData]', res)
100-
}, dataError)
115+
if (logged && userName) postData(cardsArr)
116+
.then((res) => {
117+
console.log('[onPostData]', res)
118+
}, e => console.log(`Data post request error. Response: ${e}`))
101119
}
102120
catch (e) {
103121
console.error(e)
@@ -106,23 +124,20 @@ function App() {
106124

107125
function loadDataFromServer() {
108126
try {
109-
if (logged) {
127+
if (logged && userName) {
110128
setLoading(true)
111-
loadData().then(data => {
112-
console.log('[onLoadData]', 'Данные с сервера загружены')
113-
setLoadedCards(data)
114-
setLoading(false)
115-
}, dataError)
129+
loadData()
130+
.then(data => {
131+
console.log('[onLoadData]', 'Данные с сервера загружены')
132+
setLoadedCards(data)
133+
setLoading(false)
134+
}, e => console.log(`Data load request error. Response: ${e}`))
116135
}
117136
}
118137
catch (e) {
119138
console.error(e)
120139
}
121140
}
122-
123-
function dataError(msg) {
124-
console.log(`Data request error. Response: ${msg}`)
125-
}
126141
///////////
127142

128143
///////////
@@ -178,26 +193,38 @@ function App() {
178193
return (
179194
<Context.Provider value={{ removeCard, changeCardState, setEditCard, unsetEditCard, editCardContent, editCardId }}>
180195
<div className="App">
181-
<header className="p-1 h2 text-center">
182-
<img src={logo} className="App-logo" alt="logo" />
183-
<h1 className="d-inline-block h2">{testText}</h1>
184-
<p className="show_login btn btn-light py-0" onClick={(e) => { setLogged(logged === false ? 0 : false) }}>
185-
{logged ? `Login: ${userName}` : "LOG IN"}
186-
</p>
196+
<header className="p-1">
197+
<nav className="d-flex container px-0 flex-wrap-reverse">
198+
<div className="text-center d-flex p-1 align-items-center justify-content-center flex-wrap">
199+
<img src={logo} className="App-logo" alt="logo" />
200+
<h1 className="h2 m-0">{testText}</h1>
201+
</div>
202+
<div className="text-center d-flex p-1 align-items-center ml-auto">
203+
<button className="btn btn-light " onClick={() => setOpenLogin(true)}>
204+
{logged ? `Login: ${userName}` : "LOG IN"}
205+
</button>
206+
</div>
207+
</nav>
208+
<ModalLogin login={tryLogin} logout={tryLogout} logged={logged} userName={userName} isOpen={openLogin} setOpenState={setOpenLogin} />
187209
</header>
188210

189211
<main className="p-1">
190212
<AddCard onCreate={addCard} onDeleteAll={deleteAll} />
191-
<Modal component={ModalLogin} componentProps={{ logged: logged, login: tryLogin, dislogin: dislogin, userName: userName }} />
192-
<Modal component={ModalCardEdit} componentProps={{ card: getCardByIndex(editCardId), index: editCardId }} />
193-
{loading && <Loader />}
213+
<ModalCardEdit card={getCardByIndex(editCardId)} index={editCardId} />
214+
194215
{cardsArr.length ? (
195216
<CardList cards={cardsArr} />
196-
) : loading && !logged ? null : (
217+
) : loading ? null : logged ? (
197218
<div className="container text-center">
198219
<p className="m-3 p-3 h5 text-muted">No cards. You can add a new one!</p>
199220
</div>
221+
) : (
222+
<div className="container text-center">
223+
<p className="m-3 p-3 h5 text-muted">Unlogged</p>
224+
</div>
200225
)}
226+
227+
{loading && <Loader />}
201228
</main>
202229
</div>
203230
</Context.Provider>

src/DataService.js

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,22 @@ export default function DataService() {
77
//let recuestCount = 1;
88

99
////////////////////////////////////////////////////////////
10-
function setLogin(login) {
11-
if (login && typeof login === "string") {
12-
user = login
13-
return Promise.resolve(user)
14-
} else return Promise.reject(login)
10+
function setDataServLogin(login) {
11+
return new Promise((res, rej) => {
12+
if (login && typeof login === "string") {
13+
user = login
14+
//console.log("data serv login set")
15+
res(user)
16+
} else if (login === null) {
17+
user = null
18+
//console.log("data serv dislogin")
19+
res()
20+
} else {
21+
//console.log("data serv cant set login", login)
22+
rej(login)
23+
}
24+
}).catch(e => { console.log("data serv login not set", e); return e })
25+
1526
}
1627
////////////////////////////////////////////////////////////
1728

@@ -65,6 +76,30 @@ export default function DataService() {
6576
}
6677
return value;
6778
}
79+
80+
function checkData(data) {
81+
//console.log('start check data')
82+
const checkCard = (card) => {
83+
return !(
84+
(typeof card.id === "number" || typeof card.id === "string") &&
85+
!isNaN(card.id) && typeof card.completed === "boolean" &&
86+
typeof card.text === "string"
87+
)
88+
}
89+
const checkArr = (arr) => {
90+
let res = true
91+
arr.forEach(element => {
92+
if (checkCard(element)) res = false
93+
})
94+
return res
95+
}
96+
try {
97+
return data === null || data === [] || checkArr(data)
98+
} catch {
99+
return false
100+
}
101+
102+
}
68103
////////////////////////////////////////////////////////////
69104

70105
////////////////////////////////////////////////////////////
@@ -77,7 +112,15 @@ export default function DataService() {
77112
.then((d) => {
78113
let data = tryParce(d)//here we parce json
79114
//console.log("[DATA] from loadData(): ", data)
80-
res(data || [])
115+
if (!checkData(data)) {
116+
console.error("[loadData] Bad data format", data)
117+
if (user !== null) {
118+
console.log('clear data')
119+
requestPostData([{ id: 0, completed: false, text: "Данные были очищены из за ошибки" }]).then(() => loadData().then(res, rej), rej)//очистка данных
120+
} else rej("Not format data & unlogged")
121+
} else {
122+
res(data || [])
123+
}
81124
}, rej)
82125
.catch(rej)
83126
} catch (e) {
@@ -106,5 +149,5 @@ export default function DataService() {
106149
}
107150
////////////////////////////////////////////////////////////
108151

109-
return { loadData, postData, setLogin }
152+
return { loadData, postData, setDataServLogin }
110153
}

src/Modal/Modal.css

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@
1313
}
1414

1515
.modal-window-body {
16-
padding: 2rem;
1716
width: 100%;
1817
max-width: 620px;
19-
border-radius: 5px;
20-
background: #fff;
2118
height: fit-content;
2219
}
2320

src/Modal/Modal.js

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,86 @@ import PropTypes from 'prop-types'
33
import './Modal.css'
44

55
const classes = {
6-
modalWrapper: ' modal-window-wrapper ',
7-
modalBody: ' modal-window-body '
6+
modalWrapper: 'modal-window-wrapper modal',
7+
modalBody: 'modal-window-body'
88
}
9-
export const ModalContext = React.createContext()
9+
1010
function Modal(props) {
11+
const { isOpen, setOpenState, openButton, sideClose, onSideClick } = props
1112

12-
const [isOpen, setOpenState] = React.useState(false)
13-
const Component = props.component
14-
const ComponentProps = props.componentProps
13+
const wrapperRef = React.useRef(null)
1514

1615
function open() {
1716
setOpenState(true)
1817
}
1918

2019
function close() {
2120
setOpenState(false)
21+
if (typeof onSideClick === "function") onSideClick()
22+
}
23+
24+
function handleOpenButtonClick() {
25+
open()
26+
}
27+
28+
function handleWrapperClick(e) {
29+
if (wrapperRef.current && wrapperRef.current === e.target) {
30+
if (sideClose) close()
31+
}
2232
}
2333

2434
return (
2535
<React.Fragment>
26-
<div className="container p-1 d-none">
27-
<button className="btn" onClick={open}>Open modal</button>
36+
<div className="container p-1" style={{ display: openButton ? "block" : "none" }}>
37+
<button className="btn" onClick={handleOpenButtonClick}>Open modal</button>
2838
</div>
2939

3040
<div
3141
style={{ display: !isOpen ? "none" : "flex" }}
3242
className={classes.modalWrapper}
33-
onClick={(e) => { if (e.target.className === classes.modalWrapper) close() }}
43+
ref={wrapperRef}
44+
onClick={handleWrapperClick}
3445
>
35-
<div className={classes.modalBody + 'bg-light'}>
36-
<ModalContext.Provider value={{ open, close, isOpen, classes }}>
37-
<Component {...ComponentProps} />
38-
</ModalContext.Provider>
46+
<div className={classes.modalBody}>
47+
<div className="rounded container p-3 bg-light">
48+
{props.children}
49+
</div>
3950
</div>
4051
</div>
4152

4253
</React.Fragment>
4354
)
4455
}
4556

57+
class ModalProps {
58+
constructor() {
59+
this.isOpen = false
60+
this.setOpenState = null
61+
this.openButton = false
62+
this.sideClose = false
63+
this.onSideClick = null
64+
}
65+
66+
bind() {
67+
return {
68+
isOpen: this.isOpen,
69+
setOpenState: this.setOpenState,
70+
openButton: this.openButton,
71+
sideClose: this.sideClose,
72+
onSideClick: this.onSideClick
73+
}
74+
}
75+
}
76+
4677
Modal.propTypes = {
47-
component: PropTypes.func,
48-
componentProps: PropTypes.object
78+
children: PropTypes.object,
79+
80+
isOpen: PropTypes.bool,
81+
setOpenState: PropTypes.func,
82+
openButton: PropTypes.bool,
83+
sideClose: PropTypes.bool,
84+
onSideClick: PropTypes.func
4985
}
5086

5187
export default Modal
88+
export { Modal, ModalProps }

0 commit comments

Comments
 (0)