fixes / register user

This commit is contained in:
2021-02-08 15:48:21 +01:00
parent f25196f57e
commit ab0f65e247
10 changed files with 310 additions and 72 deletions

View File

@@ -21,8 +21,15 @@ axios.interceptors.response.use(
return axios(error.config); return axios(error.config);
}) })
resolve(response) resolve(response)
} else {
if(error.response && error.response.status === 403){
store.dispatch(logout("Podany użytkownik, lub hasło nie istnieje.", "error"));
} else if(error.response && error.response.status === 400) {
store.dispatch(logout("Dane nieprawidłowe.", "error"));
} else {
store.dispatch(logout("Sesja wygasła", "info"));
}
} }
store.dispatch(logout());
}) })
}); });
@@ -196,23 +203,47 @@ export const tryLogin = (username, password) => {
axios axios
.post(backend + "user/login", data) .post(backend + "user/login", data)
.then((response) => { .then((response) => {
const jwt = response.headers["x-auth-token"]; if(response.data.isRestaurant === true){
dispatch( const jwt = response.headers["x-auth-token"];
dispatch(
toggles.setLoggedIn( toggles.setLoggedIn(
response.data.firstname, response.data.firstname,
response.data.lastname, response.data.lastname,
jwt, jwt,
response.data.id, response.data.id,
response.data.email, response.data.email,
"",
response.data.NIP, response.data.NIP,
response.data.adress, response.data.adress,
response.data.companyName, response.data.companyName,
response.data.restaurants response.data.restaurants,
response.data.isRestaurant
) )
); );
dispatch(toggles.hideBackdrop()); dispatch(toggles.hideBackdrop());
dispatch(notification(`Witaj ${response.data.firstname}!`, "success")); dispatch(notification(`Witaj ${response.data.firstname}!`, "success"));
dispatch(push("/")); dispatch(push("/"));
} else {
const jwt = response.headers["x-auth-token"];
dispatch(
toggles.setLoggedIn(
"",
"",
jwt,
response.data.id,
response.data.email,
response.data.login,
"",
"",
"",
[],
response.data.isRestaurant
)
);
dispatch(toggles.hideBackdrop());
dispatch(notification(`Witaj ${response.data.login}!`, "success"));
dispatch(push("/"));
}
}) })
.catch((err) => { .catch((err) => {
if (!err.response) { if (!err.response) {
@@ -220,7 +251,7 @@ export const tryLogin = (username, password) => {
} else if (err.response.status === 404) { } else if (err.response.status === 404) {
dispatch(toggles.hideBackdrop()); dispatch(toggles.hideBackdrop());
dispatch(notification("Użytkownik nie istnieje :(", "error")); dispatch(notification("Użytkownik nie istnieje :(", "error"));
} else if (err.response.status === 401) { } else if (err.response.status === 403) {
dispatch(toggles.hideBackdrop()); dispatch(toggles.hideBackdrop());
dispatch(notification("Błędne dane logowania :(", "error")); dispatch(notification("Błędne dane logowania :(", "error"));
} else { } else {
@@ -269,9 +300,13 @@ export const changePassword = (email, password, token) => {
}; };
}; };
export const logout = () => { export const logout = (message, type) => {
return function (dispatch) { return function (dispatch) {
dispatch(notification("Wylogowano.", "info")); if(message && type){
dispatch(notification(message, type));
} else {
dispatch(notification("Wylogowano.", "info"));
}
dispatch(toggles.hideBackdrop()); dispatch(toggles.hideBackdrop());
dispatch(toggles.setLoggedOut()); dispatch(toggles.setLoggedOut());
dispatch(push("/")); dispatch(push("/"));
@@ -292,6 +327,7 @@ export const tryRegister = (data) => {
) )
); );
dispatch(toggles.hideBackdrop()); dispatch(toggles.hideBackdrop());
dispatch(push("/"))
} }
}) })
.catch((err) => { .catch((err) => {

View File

@@ -16,10 +16,12 @@ export const setLoggedIn = (
jwt, jwt,
userId, userId,
email, email,
login,
NIP, NIP,
adress, adress,
companyName, companyName,
restaurants restaurants,
isRestaurant
) => { ) => {
return { return {
type: "SET_LOGGEDIN", type: "SET_LOGGEDIN",
@@ -29,10 +31,12 @@ export const setLoggedIn = (
jwt: jwt, jwt: jwt,
userId: userId, userId: userId,
email: email, email: email,
login: login,
NIP: NIP, NIP: NIP,
adress: adress, adress: adress,
companyName: companyName, companyName: companyName,
restaurants: restaurants, restaurants: restaurants,
isRestaurant: isRestaurant
}, },
}; };
}; };

View File

@@ -19,8 +19,13 @@ import LockIcon from "@material-ui/icons/Lock";
import Link from "@material-ui/core/Link"; import Link from "@material-ui/core/Link";
import validator from "validator"; import validator from "validator";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import Checkbox from '@material-ui/core/Checkbox';
export default function RegisterDialog(props) { export default function RegisterDialog(props) {
const [currentTab, setTab] = useState(0);
const [termsAccepted, setTermsAccepted] = useState(0);
const initialFormData = { const initialFormData = {
firstname: "", firstname: "",
lastname: "", lastname: "",
@@ -28,8 +33,10 @@ export default function RegisterDialog(props) {
adress: "", adress: "",
NIP: "", NIP: "",
email: "", email: "",
login: "",
password: "", password: "",
repeatPassword: "", repeatPassword: "",
isRestaurant: false,
firstnameError: false, firstnameError: false,
lastnameError: false, lastnameError: false,
companyNameError: false, companyNameError: false,
@@ -38,6 +45,7 @@ export default function RegisterDialog(props) {
emailError: false, emailError: false,
passwordError: false, passwordError: false,
repeatPasswordError: false, repeatPasswordError: false,
loginError: false
}; };
const [formData, setFormData] = useState(initialFormData); const [formData, setFormData] = useState(initialFormData);
const dispatch = useDispatch(); const dispatch = useDispatch();
@@ -92,44 +100,115 @@ export default function RegisterDialog(props) {
const validateForm = () => { const validateForm = () => {
var valid; var valid;
const validations = { if(currentTab === 1){
firstname: !validator.isEmpty(formData.firstname), const validations = {
lastname: !validator.isEmpty(formData.lastname), firstname: !validator.isEmpty(formData.firstname),
companyName: !validator.isEmpty(formData.companyName), lastname: !validator.isEmpty(formData.lastname),
adress: !validator.isEmpty(formData.adress), companyName: !validator.isEmpty(formData.companyName),
NIP: !validator.isEmpty(formData.NIP), adress: !validator.isEmpty(formData.adress),
email: validator.isEmail(formData.email), NIP: !validator.isEmpty(formData.NIP),
password: validator.isLength(formData.password, { email: validator.isEmail(formData.email),
min: 8, password: validator.isLength(formData.password, {
max: 128, min: 8,
}), max: 128,
repeatPassword: formData.password === formData.repeatPassword, }),
}; repeatPassword: formData.password === formData.repeatPassword,
};
setFormData({ setFormData({
...formData, ...formData,
firstnameError: !validations.firstname, firstnameError: !validations.firstname,
lastnameError: !validations.lastname, lastnameError: !validations.lastname,
companyNameError: !validations.companyName, companyNameError: !validations.companyName,
adressError: !validations.adress, adressError: !validations.adress,
NIPError: !validations.NIP, NIPError: !validations.NIP,
emailError: !validations.email, emailError: !validations.email,
passwordError: !validations.password, passwordError: !validations.password,
repeatPasswordError: !validations.repeatPassword, repeatPasswordError: !validations.repeatPassword,
}); });
valid = valid =
validations.firstname && validations.firstname &&
validations.lastname && validations.lastname &&
validations.email && validations.email &&
validations.password && validations.password &&
validations.repeatPassword && validations.repeatPassword &&
validations.companyName && validations.companyName &&
validations.adress && validations.adress &&
validations.NIP; validations.NIP;
} else {
const validations = {
email: validator.isEmail(formData.email),
login: validator.isLength(formData.login),
password: validator.isLength(formData.password, {
min: 8,
max: 128,
}),
repeatPassword: formData.password === formData.repeatPassword,
};
setFormData({
...formData,
emailError: !validations.email,
loginError: !validations.login,
passwordError: !validations.password,
repeatPasswordError: !validations.repeatPassword,
});
valid =
validations.email &&
validations.password &&
validations.repeatPassword &&
validations.login
}
return valid; return valid;
}; };
const handleTabChange = (event, newValue) => {
if(newValue === 0){
setFormData({
...formData,
firstname: "",
lastname: "",
companyName: "",
adress: "",
NIP: "",
firstnameError: false,
lastnameError: false,
companyNameError: false,
adressError: false,
NIPError: false,
emailError: false,
passwordError: false,
repeatPasswordError: false,
loginError: false,
isRestaurant: false
})
} else if(newValue === 1){
setFormData({
...formData,
firstname: "",
lastname: "",
companyName: "",
adress: "",
NIP: "",
firstnameError: false,
lastnameError: false,
companyNameError: false,
adressError: false,
NIPError: false,
emailError: false,
passwordError: false,
repeatPasswordError: false,
loginError: false,
isRestaurant: true
})
}
setTab(newValue)
}
const handleCheckboxChange = () => {
setTermsAccepted(!termsAccepted);
}
const sendForm = (form) => { const sendForm = (form) => {
if (validateForm()) { if (validateForm()) {
dispatch(tryRegister(form)); dispatch(tryRegister(form));
@@ -158,7 +237,84 @@ export default function RegisterDialog(props) {
</IconButton> </IconButton>
<Divider /> <Divider />
<DialogContent> <DialogContent>
<div> <Tabs onChange={handleTabChange} value={currentTab} indicatorColor="primary" textColor="primary" centered>
<Tab label="Użytkownik" value={0}/>
<Tab label="Restauracja" value={1}/>
</Tabs>
<Divider />
{currentTab === 0 && (<div>
<TextField
className={loginClass.textInput}
required
id="login"
label="Nazwa użytkownika"
type="name"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<AccountCircle color="primary" />
</InputAdornment>
),
}}
error={formData.firstnameError}
onChange={(event) => (formData.login = event.target.value)}
/>
<TextField
className={loginClass.textInput}
required
id="email"
label="Email"
type="email"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<EmailIcon color="primary" />
</InputAdornment>
),
}}
error={formData.emailError}
onChange={(event) => (formData.email = event.target.value)}
/>
<TextField
className={loginClass.textInput}
required
id="password"
label="Hasło (min. 8 znaków)"
type="password"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<LockIcon color="primary" />
</InputAdornment>
),
}}
error={formData.passwordError}
onChange={(event) => (formData.password = event.target.value)}
/>
<TextField
className={loginClass.textInput}
required
id="repeat-password"
label="Powtórz hasło"
type="password"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<LockIcon color="primary" />
</InputAdornment>
),
}}
error={formData.repeatPasswordError}
onChange={(event) =>
(formData.repeatPassword = event.target.value)
}
/>
</div>)}
{currentTab === 1 && (<div>
<TextField <TextField
className={loginClass.textInput} className={loginClass.textInput}
required required
@@ -297,19 +453,23 @@ export default function RegisterDialog(props) {
(formData.repeatPassword = event.target.value) (formData.repeatPassword = event.target.value)
} }
/> />
</div> </div>)}
<Divider /> <Divider />
<div className="register-dialog-actions"> <div className="register-dialog-actions">
<div className="register-dialog-checkbox">
<Checkbox checked={termsAccepted} onChange={handleCheckboxChange}/>
<p> <p>
Rejestracja oznacza akceptację{" "} Przeczytałem i akceptuję postanowienia{" "}
<span> <span>
<Link href="#" onClick={(event) => handleRegulaminClick(event)}> <Link href="#" onClick={(event) => handleRegulaminClick(event)}>
regulaminu regulaminu.
</Link> </Link>
</span> </span>
</p> </p>
</div>
<div className="register-dialog-button"> <div className="register-dialog-button">
<ButtonSecondary <ButtonSecondary
disabled={!termsAccepted}
onClick={() => sendForm(formData)} onClick={() => sendForm(formData)}
text="Zarejestruj" text="Zarejestruj"
/> />

View File

@@ -83,15 +83,24 @@ export default function Settings() {
}); });
const history = useHistory(); const history = useHistory();
const style = useStyles(); const style = useStyles();
const isRestaurant = useSelector((store) => store.data.userData.isRestaurant)
const data = useSelector((state) => state.data.userData); const data = useSelector((state) => state.data.userData);
const initialState = { let initialState;
firstname: data.firstname, if(isRestaurant === true) {
lastname: data.lastname, initialState = {
email: data.userEmail, firstname: data.firstname,
NIP: data.billing.NIP, lastname: data.lastname,
adress: data.billing.adress, email: data.userEmail,
companyName: data.billing.companyName, NIP: data.billing.NIP,
}; adress: data.billing.adress,
companyName: data.billing.companyName,
};
} else {
initialState = {
email: data.userEmail,
login: data.login,
};
}
const [state, setState] = useState(initialState); const [state, setState] = useState(initialState);
return ( return (
<Dialog aria-labelledby="settings-title" className={style.root} open={true}> <Dialog aria-labelledby="settings-title" className={style.root} open={true}>
@@ -104,7 +113,7 @@ export default function Settings() {
<CloseIcon /> <CloseIcon />
</IconButton> </IconButton>
<Divider /> <Divider />
<DialogContent> {isRestaurant && (<DialogContent>
<TextField <TextField
className={style.textInput} className={style.textInput}
value={state.firstname} value={state.firstname}
@@ -202,7 +211,28 @@ export default function Settings() {
<Divider /> <Divider />
<ButtonPrimary onClick={() => history.goBack()} text="Anuluj" /> <ButtonPrimary onClick={() => history.goBack()} text="Anuluj" />
<ButtonSecondary text="Zapisz" /> <ButtonSecondary text="Zapisz" />
</DialogContent> </DialogContent>)}
{!isRestaurant && (<DialogContent>
<TextField
className={style.textInput}
value={state.email}
onChange={(event) =>
setState({ ...state, email: event.target.value })
}
label="Email"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<AlternateEmailIcon color="primary"/>
</InputAdornment>
)
}}
/>
<Divider />
<ButtonPrimary onClick={() => history.goBack()} text="Anuluj" />
<ButtonSecondary text="Zapisz" />
</DialogContent>)}
</Dialog> </Dialog>
); );
} }

View File

@@ -4,7 +4,7 @@ export default class Footer extends React.Component {
render() { render() {
return ( return (
<div className="footer"> <div className="footer">
<p>Menui (wersja testowa aplikacji)</p> <p>Bankai Software @2021 | Menui (v0.6.0)</p>
</div> </div>
); );
} }

View File

@@ -39,7 +39,9 @@ const useStyles = makeStyles((theme) => ({
export default function TopBar() { export default function TopBar() {
const classes = useStyles(); const classes = useStyles();
const loggedIn = useSelector((state) => state.data.loggedIn); const loggedIn = useSelector((state) => state.data.loggedIn);
const username = useSelector((state) => state.data.userData.firstname); const firstname = useSelector((state) => state.data.userData.firstname);
const login = useSelector((state) => state.data.userData.login);
const isRestaurant = useSelector((state) => state.data.userData.isRestaurant)
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const handleClick = (button) => { const handleClick = (button) => {
@@ -95,13 +97,13 @@ export default function TopBar() {
onClick={() => history.push("/")} onClick={() => history.push("/")}
/> />
<div className="vertical-divider"></div> <div className="vertical-divider"></div>
<h5>Food guide (wersja testowa)</h5> <h5>Food guide</h5>
</div> </div>
<div className="topBar-hamburger"> <div className="topBar-hamburger">
{loggedIn && ( {loggedIn && (
<div className="topbar-username"> <div className="topbar-username">
{" "} {" "}
<p>Witaj {username}</p>{" "} <p>Witaj {isRestaurant ? firstname : login}</p>{" "}
</div> </div>
)} )}
<IconButton onClick={toggleDrawer(true)} aria-label="menu"> <IconButton onClick={toggleDrawer(true)} aria-label="menu">

View File

@@ -32,6 +32,7 @@ const useStyles = makeStyles((theme) => ({
export default function UserMenu(props) { export default function UserMenu(props) {
const restaurants = useSelector((state) => state.data.userData.restaurants); const restaurants = useSelector((state) => state.data.userData.restaurants);
const isRestaurant = useSelector((state) => state.data.userData.isRestaurant);
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
const classes = useStyles(); const classes = useStyles();
const handleClick = () => { const handleClick = () => {
@@ -74,14 +75,14 @@ export default function UserMenu(props) {
</ListItemIcon> </ListItemIcon>
<ListItemText primary="Ustawienia konta" /> <ListItemText primary="Ustawienia konta" />
</ListItem> </ListItem>
<ListItem button onClick={handleClick} disableGutters> {isRestaurant && <ListItem button onClick={handleClick} disableGutters>
<ListItemIcon> <ListItemIcon>
<FastfoodIcon /> <FastfoodIcon />
</ListItemIcon> </ListItemIcon>
<ListItemText primary="Moje restauracje" /> <ListItemText primary="Moje restauracje" />
{open ? <ExpandLess /> : <ExpandMore />} {open ? <ExpandLess /> : <ExpandMore />}
</ListItem> </ListItem>}
<Collapse in={open} timeout="auto" unmountOnExit> {isRestaurant && <Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding> <List component="div" disablePadding>
<ListItem button onClick={() => handleButtonClick("/newRestaurant")}> <ListItem button onClick={() => handleButtonClick("/newRestaurant")}>
<ListItemIcon> <ListItemIcon>
@@ -89,9 +90,9 @@ export default function UserMenu(props) {
</ListItemIcon> </ListItemIcon>
<ListItemText primary="Dodaj restaurację" /> <ListItemText primary="Dodaj restaurację" />
</ListItem> </ListItem>
{viewRestaurants} {isRestaurant && viewRestaurants}
</List> </List>
</Collapse> </Collapse>}
</List> </List>
); );
} }

View File

@@ -1,5 +1,5 @@
export const backend = "https://api.menui.pl/"; //export const backend = "https://api.menui.pl/";
//export const backend = "http://localhost:4000/"; export const backend = "http://localhost:4000/";
export const restaurantTypes = [ export const restaurantTypes = [
"afrykańska", "afrykańska",

View File

@@ -1,9 +1,6 @@
const initialState = { const initialState = {
showDishList: false, showDishList: false,
loggedIn: false, loggedIn: false,
username: "",
userId: "",
userEmail: "",
userData: { userData: {
jwt: "", jwt: "",
firstname: "", firstname: "",
@@ -16,6 +13,7 @@ const initialState = {
companyName: "", companyName: "",
}, },
restaurants: [], restaurants: [],
isRestaurant: false
}, },
dialogs: { dialogs: {
regulamin: false, regulamin: false,
@@ -44,12 +42,14 @@ const data = (state = initialState, action) => {
lastname: action.payload.lastname, lastname: action.payload.lastname,
userId: action.payload.userId, userId: action.payload.userId,
userEmail: action.payload.email, userEmail: action.payload.email,
login: action.payload.login,
billing: { billing: {
NIP: action.payload.NIP, NIP: action.payload.NIP,
adress: action.payload.adress, adress: action.payload.adress,
companyName: action.payload.companyName, companyName: action.payload.companyName,
}, },
restaurants: action.payload.restaurants, restaurants: action.payload.restaurants,
isRestaurant: action.payload.isRestaurant
}, },
}); });
case "SET_LOGGEDOUT": case "SET_LOGGEDOUT":
@@ -68,6 +68,7 @@ const data = (state = initialState, action) => {
companyName: "", companyName: "",
}, },
restaurants: [], restaurants: [],
isRestaurant: false
}, },
}); });
case "DIALOG_REGULAMIN_SHOW": case "DIALOG_REGULAMIN_SHOW":

View File

@@ -24,3 +24,7 @@
font-size: 0.8rem; font-size: 0.8rem;
} }
} }
.register-dialog-checkbox{
display: flex;
}