김대휘

Modify 구현

......@@ -11,7 +11,7 @@
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1"
"react-scripts": "^3.4.1"
},
"scripts": {
"start": "react-scripts start",
......
......@@ -73,8 +73,7 @@ export default function BodyLayout() {
{data.map((card, idx) => {
let isVisible = card.isPublic;
let showDate = null;
const isMine = card.name === "aa"; ////data.name과 session name 비교 로그인 구현하고 수정
const isMine = card.name === localStorage["userName"]; //remove item
if (idx === 0 || card.date !== data[idx - 1].date) {
showDate = (
<Typography variant="h4" className={classes.date}>
......@@ -105,10 +104,6 @@ export default function BodyLayout() {
return <>{showDate}</>;
}
})}
{/* <Grid item xs={6} sm={6} md={3}>
<Icon style={{ fontSize: 60 }}>add_circle</Icon>
</Grid> */}
</Grid>
<AddButton></AddButton>
</Container>
......
......@@ -99,7 +99,7 @@ export default function AddButton({ handleClose }) {
const initCK = Array.apply(null, Array(textList.length)).map(Number.prototype.valueOf,0);
addApi({
isPublic: isPublic,
name: "testName",
name: localStorage["userName"],
date: date.toLocaleDateString(),
time: date.toLocaleTimeString(),
title: title,
......
import React, { useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Modal from "@material-ui/core/Modal";
import IconButton from "@material-ui/core/IconButton";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import AddIcon from "@material-ui/icons/Add";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";
const useStyles = makeStyles((theme) => ({
iconButton: {
margin: "0",
padding: "0",
position: "fixed",
bottom: "3rem",
right: "3rem",
},
icon: {
fontSize: 70,
color: "black",
},
addButton: {
fontSize: 11,
float: "right",
margin: 0,
marginTop: "1rem",
marginRight: "1rem",
},
buttonGroup: {
clear: "both",
"& > *": {
margin: theme.spacing(1),
float: "right",
},
},
title: {
float: "left",
width: "13rem",
marginLeft: "0.5rem",
marginTop: "0.3rem",
padding: 0,
},
isPublic: {
float: "left",
},
paper: {
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
position: "absolute",
width: "90%",
maxWidth: 320,
maxHeight: 500,
msOverflowStyle: "none",
backgroundColor: "white",
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 2),
},
input: {
"& > *": {
float: "left",
margin: theme.spacing(1),
marginRight: 0,
width: "14.5rem",
},
},
}));
export default function AddButton({ data, handleClose }) {
const classes = useStyles();
const [title, setTitle] = useState(data.title);
//const [date, setDate] = useState(new Date());
const [isPublic, setIsPublic] = useState(data.isPublic);
const [textList, setTextList] = useState(data.todo.split(","));
const [textFieldBody, setTextFieldBody] = useState(
textList.map((text, idx) => {
return (
<TextField
required
fullWidth={true}
defaultValue={textList[idx]}
label={"To do " + (idx + 1)}
onChange={(e) => handleText(e, idx)}
/>
);
})
);
const modifyApi = (data) => {
return fetch("/api/updatecard", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
}).then((response) => response.json());
};
const checkAndClose = () => {
if (title === "") {
alert("Please enter a title!");
} else if (checkEemptyList(textList)) {
alert("Please fill in the blank!");
} else {
const initCK = Array.apply(null, Array(textList.length)).map(
Number.prototype.valueOf,
0
);
modifyApi({
isPublic: isPublic,
name: localStorage["userName"],
date: data.date,
time: data.time,
title: title,
todo: textList.join(","),
ck: initCK.join(","),
});
handleClose();
}
};
const checkEemptyList = (arr) => {
if (arr.length === 0) {
return 1;
}
for (let idx = 0; idx < arr.length; idx++) {
if (arr[idx] === undefined || arr[idx] === "") {
return 1;
}
}
return 0;
};
const handleTitle = (e) => {
setTitle(e.target.value);
};
const handlePublic = () => {
setIsPublic(isPublic ? 0 : 1);
};
const handleText = (e, idx) => {
let tempArr = textList;
tempArr[idx] = e.target.value;
setTextList(tempArr);
};
const handleAdd = () => {
if (textFieldBody.length < 5) {
const idx = textFieldBody.length;
setTextFieldBody([
...textFieldBody,
<TextField
required
label={"To do " + (idx + 1)}
onChange={(e) => handleText(e, idx)}
/>,
]);
} else {
alert("You can register up to five.");
}
};
return (
<>
<Modal open={true}>
<div className={classes.paper}>
<Typography className={classes.title} variant="h5">
MODIFY TODO
</Typography>
<FormControlLabel
className={classes.isPublic}
control={<Checkbox onClick={handlePublic} />}
checked={isPublic}
label="Public"
/>
<form className={classes.input} noValidate autoComplete="off">
<TextField required label="Title" onChange={handleTitle} defaultValue={data.title}/>
{textFieldBody.map((field) => field)}
</form>
<IconButton className={classes.addButton} onClick={handleAdd}>
<AddIcon />
</IconButton>
<form className={classes.buttonGroup}>
<Button variant="contained" color="primary" onClick={checkAndClose}>
수정
</Button>
<Button variant="contained" color="secondary" onClick={handleClose}>
삭제
</Button>
</form>
</div>
</Modal>
</>
);
}
......@@ -4,8 +4,6 @@ import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
const useStyles = makeStyles((theme) => ({
root: {
......@@ -14,12 +12,13 @@ const useStyles = makeStyles((theme) => ({
bar:{
backgroundColor:"rgba(0,0,0,0.8)"
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
marginLeft:"9%",
flexGrow: 1,
},
logout:{
marginRight:"9%",
}
}));
export default function ButtonAppBar() {
......@@ -29,13 +28,10 @@ export default function ButtonAppBar() {
<div className={classes.root}>
<AppBar className={classes.bar} position="fixed">
<Toolbar>
<IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
Do-gether
</Typography>
<Button color="inherit">Logout</Button>
<Button color="inherit" className={classes.logout}>Logout</Button>
</Toolbar>
</AppBar>
</div>
......
import React from "react";
import React, { useState } from "react";
import ModifyControl from "./ModifyControl.js";
import { makeStyles } from "@material-ui/core/styles";
import Icon from "@material-ui/core/Icon";
import IconButton from "@material-ui/core/IconButton";
......@@ -17,16 +17,35 @@ const useStyles = makeStyles({
},
});
export default function SettingButton() {
export default function SettingButton({data, isMine }) {
const classes = useStyles();
const [open, setOpen] = useState();
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
if (isMine) {
if (!open) {
return (
<>
<IconButton className={classes.iconButton}>
<Icon className={classes.icon}>
settings
</Icon>
<IconButton className={classes.iconButton} onClick={handleOpen}>
<Icon className={classes.icon}>settings</Icon>
</IconButton>
</>
);
} else {
return (
<>
<ModifyControl handleClose={handleClose} data={data}/>
</>
);
}
} else {
return <></>;
}
}
......
import React, {useState} from "react";
import React, { useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
......@@ -30,52 +30,75 @@ const useStyles = makeStyles({
},
});
export default function TodoCard({ data, isMine}) {
export default function TodoCard({ data, isMine }) {
const classes = useStyles();
const [open, setOpen] = useState(false);
const [render, setRender] = useState(0);
const todo = data.todo.split(",").map((text)=>{
const todo = data.todo.split(",").map((text) => {
return text;
});
const [checkState, setCheckState] = useState(data.ck.split(",").map((ck) => {
const [checkState, setCheckState] = useState(
data.ck.split(",").map((ck) => {
return parseInt(ck);
}))
let settingButton = null;
})
);
const handleCheck = (idx) => {
if(localStorage["userName"]===data.name)
{
let tempArr = checkState;
tempArr[idx] = tempArr[idx]?0:1;
tempArr[idx] = tempArr[idx] ? 0 : 1;
setCheckState(tempArr);
setRender([]);
modifyApi({
isPublic: data.isPublic,
name: localStorage["userName"],
date: data.date,
time: data.time,
title: data.title,
todo: data.todo,
ck: tempArr.join(",")
});
}else{
alert("You can't modify other people's list.");
}
};
const modifyApi = (data) => {
return fetch("/api/updatecard", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
}).then((response) => response.json());
};
if (isMine) {
settingButton = (
<SettingButton></SettingButton>
);
}
return (
<>
<Card className={classes.root}>
<CardContent>
<Typography className={classes.date} gutterBottom> {/*color="textSecondary"*/}
<Typography className={classes.date} gutterBottom>
{" "}
{data.name} &middot; {data.time}
</Typography>
{settingButton}
<SettingButton isMine={isMine} data={data}></SettingButton>
<Typography className={classes.title} variant="h6">
{data.title}
</Typography>
<Typography className={classes.percent} variant="h6">
{checkState.reduce((a, b) => a + b)}/{checkState.length}
</Typography>
{todo.map((item, idx) => {
return (
<FormControlLabel
className={classes.checkBox}
control={<Checkbox onClick={e=>(handleCheck(idx))}/>}
control={<Checkbox onClick={(e) => handleCheck(idx)} />}
checked={checkState[idx]}
label={item}
/>
......@@ -83,5 +106,6 @@ export default function TodoCard({ data, isMine}) {
})}
</CardContent>
</Card>
</>
);
}
......
......@@ -68,7 +68,14 @@ export default function LandingPage(props) {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
}).then((response) => response.json());
}).then((response) => response.json())
.then(result => {
if(result.success === 'login sucessfull') {
localStorage.userName = result.username;
window.location.href = '/main';
}
});
};
const handleLogin = () => {
......
......@@ -9826,7 +9826,7 @@ react-router@5.2.0:
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-scripts@3.4.1:
react-scripts@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.1.tgz#f551298b5c71985cc491b9acf3c8e8c0ae3ada0a"
integrity sha512-JpTdi/0Sfd31mZA6Ukx+lq5j1JoKItX7qqEK4OiACjVQletM1P38g49d9/D0yTxp9FrSF+xpJFStkGgKEIRjlQ==
......
......@@ -10,9 +10,14 @@
"bcrypt": "^5.0.0",
"body-parser": "^1.18.3",
"express": "^4.16.4",
"mysql": "^2.18.1"
"express-session": "^1.17.1",
"mysql": "^2.18.1",
"nodemon": "^2.0.4"
},
"devDependencies": {
"concurrently": "^4.0.1"
}
},
"proxy": "http://localhost:3000/",
"license": "UNLICENSED"
}
......
const fs = require("fs");
const express = require("express");
const bodyParser = require("body-parser");
const bcrypt = require("bcrypt");
const session = require("express-session");
const app = express();
const port = process.env.PORT || 5000;
const bcrypt = require("bcrypt");
const saltRounds = 10;
const data = fs.readFileSync("./database.json");
......@@ -19,11 +20,17 @@ const connection = mysql.createConnection({
port: conf.port,
database: conf.database,
});
connection.connect();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
session({
secret: "asdjha!@#@#$dd",
resave: false,
saveUninitialized: true,
})
);
app.get("/api/cards", (req, res) => {
connection.query("SELECT * FROM CARDINFO", (err, rows, fields) => {
......@@ -60,6 +67,64 @@ app.post("/api/addcard", (req, res) => {
});
});
app.put("/api/updatecard", (req, res) => {
const data = req.body;
const sql =
`UPDATE CARDINFO SET title="${data.title}",todo="${data.todo}",ck="${data.ck}" WHERE name="${data.name}" AND date="${data.date}" AND time="${data.time}";`;
console.log(sql);
// const params = [
// data.isPublic,
// data.name,
// data.date,
// data.time,
// data.title,
// data.todo,
// data.ck,
// ];
connection.query(sql, (err, rows, fields) => {
if (err) {
res.send({
code: 400,
message: "error",
});
} else {
res.send({
code: 200,
message: "success",
});
}
});
});
app.delete("/api/deletecard", (req, res) => {
const data = req.body;
const sql =
"INSERT INTO CARDINFO(isPublic,name,date,time,title,todo,ck) VALUES(?,?,?,?,?,?,?);";
const params = [
data.isPublic,
data.name,
data.date,
data.time,
data.title,
data.todo,
data.ck,
];
connection.query(sql, params, (err, rows, fields) => {
if (err) {
res.send({
code: 400,
message: "error",
});
} else {
res.send({
code: 200,
message: "success",
});
}
});
});
app.post("/api/signup", async (req, res) => {
const data = req.body;
const sql = "INSERT INTO USERINFO(userID,userPW,userName) VALUES(?,?,?);";
......@@ -86,39 +151,45 @@ app.post("/api/login", (req, res) => {
const data = req.body;
const enteredID = data.userID;
const enteredPW = data.userPW;
connection.query('SELECT * FROM USERINFO WHERE userID = ?', [enteredID],
function( error, results, fields) {
connection.query(
"SELECT * FROM USERINFO WHERE userID = ?",
[enteredID],
function (error, results, fields) {
if (error) {
// console.log("error ocurred", error);
res.send({
"code": 400,
"failed": "error ocurred"
})
code: 400,
failed: "error ocurred",
});
} else {
// console.log('The solution is: ', results);
if(results.length > 0) {
bcrypt.compare(enteredPW, results[0].userPW, function(err, check) {
if (results.length > 0) {
bcrypt.compare(enteredPW, results[0].userPW, function (err, check) {
console.log(check);
if(check) {
console.log("sec")
if (check) {
req.session.userName = results[0].userName;
console.log( req.session.userName);
res.send({
"code": 200,
"success": "login sucessfull"
code: 200,
success: "login sucessfull",
username : results[0].userName
});
// res.redirect("/main");
} else {
res.send({
"code": 204,
"success": "id and password does not match."
code: 204,
success: "Id and password does not match.",
});
}
});
} else {
res.send({
"code":204,
"success": "Email does not exists"
code: 204,
success: "Id does not exists",
});
}
}
})
}
);
});
app.listen(port, () => console.log(`Listening on port ${port}`));
......
This diff is collapsed. Click to expand it.