diff --git a/backend/package-lock.json b/backend/package-lock.json index cbf9625a07d8ad1263d0ad83f979b4c3bd9f8f82..7a49c3d289f7e6d81a4de24380f713aa2d5f71f3 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -18,6 +18,7 @@ "memorystore": "^1.6.7", "moment": "^2.29.4", "mongoose": "^8.0.1", + "mongoose-sequence": "^5.3.1", "nodemon": "^3.0.1" }, "devDependencies": { @@ -176,6 +177,14 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -807,6 +816,11 @@ "node": ">=12.0.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1015,6 +1029,18 @@ "url": "https://opencollective.com/mongoose" } }, + "node_modules/mongoose-sequence": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/mongoose-sequence/-/mongoose-sequence-5.3.1.tgz", + "integrity": "sha512-kQB1ctCdAQT8YdQzoHV0CpBRsO4RNVy03SOkzM6TQKBbGBs1ZgVS4UlKsuvBPaiPt9q5tKgQZvorGJ1awbHDqA==", + "dependencies": { + "async": "^2.5.0", + "lodash": "^4.17.20" + }, + "peerDependencies": { + "mongoose": ">=4" + } + }, "node_modules/mongoose/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", diff --git a/backend/package.json b/backend/package.json index 5ce671e0e7fbd0a00ef23f19c659001fe4a308fa..51b4297795a014fb4d119d7bf7d506c1536fed77 100644 --- a/backend/package.json +++ b/backend/package.json @@ -21,6 +21,7 @@ "memorystore": "^1.6.7", "moment": "^2.29.4", "mongoose": "^8.0.1", + "mongoose-sequence": "^5.3.1", "nodemon": "^3.0.1" }, "devDependencies": { diff --git a/backend/src/db.js b/backend/src/db.js index 25ae4a409b027f9d582e6b4c2e66149c1e60b83b..608eb413c169e605f0a0f7cfaabe0d082872212b 100644 --- a/backend/src/db.js +++ b/backend/src/db.js @@ -7,7 +7,7 @@ const GoogleProviderSchema = new mongoose.Schema({ id: { type: String, required: true, - unique: true, + //unique: true, }, profileUrl: { type: String, @@ -18,28 +18,31 @@ const UserSchema = new mongoose.Schema({ user_id: { type: String, required: true, - unique: true, + //unique: true, }, nickname: { type: String, }, email: { type: String, - unique: true, + //unique: true, }, google: { type: GoogleProviderSchema, } }); + const UserModel = mongoose.model("User", UserSchema); const CommentSchema = new mongoose.Schema({ + /* commentId: { type: String, required: true, - unique: true, - }, + unique: false, + }, + */ content: { type: String, required: true, @@ -53,16 +56,19 @@ const CommentSchema = new mongoose.Schema({ default: Date.now, }, }); +CommentSchema.index( { commentId: 1 } , { sparse: true } ) const ArticleSchema = new mongoose.Schema({ title: { type: String, required: true, }, - articleId: { + /* + articleId: { type: String, - unique: true, - }, + unique: true, + }, + */ content: { type: String, required: true, @@ -76,6 +82,7 @@ const ArticleSchema = new mongoose.Schema({ }, comments: { type: [CommentSchema], + unique: false, }, likes: { type: [UserSchema], @@ -86,6 +93,7 @@ const ArticleSchema = new mongoose.Schema({ }, }); +ArticleSchema.index({articleId:1}, { sparse: true }) const ArticleModel = mongoose.model("Article", ArticleSchema); const connectDB = async () => { diff --git a/backend/src/index.js b/backend/src/index.js index 222a9a94f0e164a595efa7e361ee6833a82c237e..abd93ceca8509972dd14f82e033078a016ddbcb3 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -14,7 +14,7 @@ db.connectDB(); app.use(express.static(path.join(process.cwd(), '../frontend/build'))); -const maxAge = 1000 * 60 * 1; // 5분(임시) +const maxAge = 1000 * 60 * 60; // 5분(임시) app.use(session({ secret: '12345', @@ -45,6 +45,14 @@ function b64_to_utf8( str ) { return decodeURIComponent(escape(window.atob( str ))); } +function b64DecodeUnicode(str) { + // Going backwards: from bytestream, to percent-encoding, to original string. + return decodeURIComponent(atob(str) + .split('').map(function (c) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }).join('')); +} + function encode_utf8(s) { return unescape(encodeURIComponent(s)); } @@ -54,11 +62,12 @@ app.post('/login', async (req, res) => { TODO: 토큰의 무결성 체크 토큰이 이상이 없다면, 로그인/회원가입 로직을 수행 후 jwt 쿠키를 보낸다. */ - const expires = moment().add('1','m').toDate() + const expires = moment().add('60','m').toDate() // 정보가 없다면 회원 가입 (강제?) const user = await db.UserModel.find({ user_id: req.body.email }); if (!user.length) { // 유저가 없다면 회원 가입 후 세션 생성 + let userProfilePicture = req.body.picture || null const userModel = new db.UserModel({ user_id: req.body.email, @@ -70,15 +79,15 @@ app.post('/login', async (req, res) => { }, }); await userModel.save(); - console.log('saved') + console.log('new user saved!') } + console.log('login done') - - req.session.sessionid = req.body.name; //세션 생성 + req.session.sessionid = req.body; //세션 생성 res.cookie('name', req.body.name, {expires}); //사용자 이름 쿠키 if(req.session.sessionid){ - console.log(req.session.sessionid); + //console.log(req.session.sessionid); //res.send('세션 o'); } @@ -107,6 +116,66 @@ app.get("/logout", (req, res) => { } }); +app.post("/post", async (req, res) => { + console.log("포스팅 '해줘'"); + if(!req.session.sessionid){ + // 세션이 없엉 + } + console.log(db) + + const inputTitle = req.body.title + const inputContent = req.body.content + const inputImage = [] + const useremail = req.session.sessionid.email + const author = await db.UserModel.find({ user_id: useremail }); + const articleModel = new db.ArticleModel({ + title: inputTitle, + content: inputContent, + imageUrls: inputImage, + author: author[0], + comments: [], + likes: [] + }); + await articleModel.save(); + console.log('saved.') + res.send(); +}); + +/* + +const ArticleSchema = new mongoose.Schema({ + title: { + type: String, + required: true, + }, + articleId: { + type: String, + unique: true, + }, + content: { + type: String, + required: true, + }, + imageUrls: { + type: [String], + }, + author: { + type: UserSchema, + required: true, + }, + comments: { + type: [CommentSchema], + }, + likes: { + type: [UserSchema], + }, + createdAt: { + type: Date, + default: Date.now, + }, +}); + +*/ diff --git a/frontend/package-lock.json b/frontend/package-lock.json index ed59d0a57cfdd9339a8192be8d186fbe00716253..00012ccdea21e8058a6cbbbc212ecb822edd6120 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -15,6 +15,7 @@ "axios": "^1.6.1", "base-64": "^1.0.0", "express": "^4.18.2", + "http-proxy-middleware": "^2.0.6", "jwt-decode": "^4.0.0", "moment": "^2.29.4", "react": "^18.2.0", @@ -4233,7 +4234,7 @@ "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -4252,7 +4253,7 @@ "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, + "devOptional": true, "dependencies": { "@types/node": "*" } @@ -4302,7 +4303,7 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, + "devOptional": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -4314,7 +4315,7 @@ "version": "4.17.41", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", - "dev": true, + "devOptional": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -4350,13 +4351,12 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true + "devOptional": true }, "node_modules/@types/http-proxy": { "version": "1.17.14", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -4634,7 +4634,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "devOptional": true }, "node_modules/@types/node": { "version": "20.9.0", @@ -4680,13 +4680,13 @@ "version": "6.9.10", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==", - "dev": true + "devOptional": true }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "devOptional": true }, "node_modules/@types/react": { "version": "18.2.37", @@ -4736,7 +4736,7 @@ "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, + "devOptional": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -4755,7 +4755,7 @@ "version": "1.15.5", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", - "dev": true, + "devOptional": true, "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -8638,8 +8638,7 @@ "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "node_modules/events": { "version": "3.3.0", @@ -9833,7 +9832,6 @@ "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -9861,7 +9859,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -10211,7 +10208,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -10265,7 +10261,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -10343,7 +10338,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, "engines": { "node": ">=10" }, @@ -16260,8 +16254,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/resolve": { "version": "1.22.8", diff --git a/frontend/package.json b/frontend/package.json index bfb51ec6b34f95305e05754bfc0e8460f982c1b3..1f9ba84780897783cb914bfe9e3afbd1fcc61eeb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,6 +10,7 @@ "axios": "^1.6.1", "base-64": "^1.0.0", "express": "^4.18.2", + "http-proxy-middleware": "^2.0.6", "jwt-decode": "^4.0.0", "moment": "^2.29.4", "react": "^18.2.0", diff --git a/frontend/src/App.js b/frontend/src/App.js index 1182d9d190bad87a8a9caa8ceb06111e012bcf7e..b4071a36d2dbc4d7e4e0179e6b60aea69ba0a919 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -4,6 +4,8 @@ import Header from "./Header.js"; import Main from "./Main.js"; import Login from "./Login.js"; import Search from "./Search.js"; +import PostWrite from "./PostWrite.js" + import GoogleLoginButton from "./GoogleLoginButton.js"; import React, { useEffect, useState, useContext} from 'react'; import { UserContext } from './Usercontext.js'; @@ -20,7 +22,7 @@ function App() { <Route path="/" element={<Main/>}></Route> <Route path="/login" element={<Login/>}></Route> <Route path="/search" element={<Search/>}></Route> - {/* <Route path="/postwrite" element={<PostWrite/>}></Route> */} + {<Route path="/postwrite" element={<PostWrite/>}></Route> } </Routes> </UserContext.Provider> {/* <Footer/> */} diff --git a/frontend/src/GoogleLoginButton.js b/frontend/src/GoogleLoginButton.js index 572894ab9709f36a5023454fe457bcaa3d4a14c1..d787646ed30ec6a0aaeac5ee33d674cd113cfef4 100644 --- a/frontend/src/GoogleLoginButton.js +++ b/frontend/src/GoogleLoginButton.js @@ -14,7 +14,6 @@ import axios from 'axios'; axios.defaults.withCredentials = true; - const GoogleLoginButton = () => { const setUserName = useContext(UserContext); diff --git a/frontend/src/Main.js b/frontend/src/Main.js index 86bc01a319f531b2c073b9e0f7ccd66a51cbb9ca..b1156b6082caa963a030e1b0882326973ff57684 100644 --- a/frontend/src/Main.js +++ b/frontend/src/Main.js @@ -3,12 +3,12 @@ import cookie from 'react-cookies'; import React, { useState, useEffect, useContext } from 'react'; function Button({history, children}){ - const navigate = useNavigate(); + const navigate = useNavigate(); return( - <button onClick={() => {navigate('/search');}}> - {children} - </button> - ); + <button onClick={() => {navigate('/search');}}> + {children} + </button> + ); } function Main() { diff --git a/frontend/src/PostWrite.js b/frontend/src/PostWrite.js index 5765fb417454203627aa93707684bee7a3926939..96ab45f56e109b997d433ea15751f9d8448bc4f7 100644 --- a/frontend/src/PostWrite.js +++ b/frontend/src/PostWrite.js @@ -1,6 +1,67 @@ import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; +import axios from 'axios'; +import { Map, MapMarker } from "react-kakao-maps-sdk"; +const {kakao} = window; +axios.defaults.withCredentials = true; + +function SearchMap({loc, setLoc}){ + // 아주대학교를 기본 위치로 설정 + + + /* + const handleInput = (e) => { + SetSearchAddress(e.target.value); + } + + const SearchStart = () => { + console.log('Start Search!');// action test + // 주소를 기반으로 한 검색 구현(제주특별자치도 제주시 첨단로 242 를 입력하면 kakao가 나온다) + const geocoder = new kakao.maps.services.Geocoder(); + let callback = function(result, status) { + if (status === kakao.maps.services.Status.OK) { + console.log(result) + const newSearch = result[0] + + setLoc({ + center: { lat: newSearch.y, lng: newSearch.x } + }) + } + }; + geocoder.addressSearch(`${searchAddress}`, callback); + + <input onChange={handleInput}/> + <button onClick={SearchStart}>검색!</button> + } + */ + return ( + <div className="UserInput"> + <button onClick={()=>{console.log(loc)}}>위도경도 (디버깅)</button> + <Map // 지도를 표시할 Container + center={loc.center} + isPanto={loc.isPanto} + style={{ + // 지도의 크기 + width: "450px", + height: "450px", + }} + onClick={(_t, mouseEvent) => setLoc({ + center: { lat: mouseEvent.latLng.getLat(), lng: mouseEvent.latLng.getLng() }, + isPanto: true, + })} + level={3}> + <MapMarker // 마커를 생성합니다 + position={{ + // 마커가 표시될 위치입니다 + lat: loc.center.lat, + lng: loc.center.lng, + }} + /> + </Map> + </div> + ) +} function PostWrite(){ @@ -8,6 +69,12 @@ function PostWrite(){ // const [content, setContent] = useState(''); // const [imageUrls, setImageUrls] = useState([]); + const [location, setLocation] = useState({ + center: { lat: 37.28238488648025, lng: 127.04350967609274 }, + isPanto: true, + }); + const [searchAddress, SetSearchAddress] = useState(); //주소 입력 + const [inputs, setInputs] = useState({ title: "", content: "", @@ -15,24 +82,28 @@ function PostWrite(){ }); const {title, content, imageUrls} = inputs; // 비구조화 할당; - + + //console.log(title) + //console.log(content) + //console.log(imageUrls) + const handleSubmit= async (event) => { event.preventDefault(); + try { - const response = await fetch('http://post/:id', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(), - }); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const data = await response.json(); - console.log('Post created successfully:', data); + + const response = await axios({ + url: 'http://localhost:8080/post', // 통신할 웹문서 + method: 'post', // 통신할 방식 + data: inputs + }); + if (response.status === 200) { + return response.data; + } + else { + return null; + } + } catch (error){ console.log('Error during post creation:', error); @@ -48,24 +119,34 @@ function PostWrite(){ } return( - <form onSubmit={handleSubmit}> - <div> - <label>제목</label> - <input - type="text" - value={title} - onChange={onChange} - required - /> - </div> - <div> - <label>Content</label> - <textarea - value={content} - onChange={onChange} - /> - </div> - </form> + <div> + <aside style={{float: "left"}}> + <SearchMap loc={location} setLoc={setLocation}></SearchMap> + </aside> + <main style={{float: "right"}}> + <form onSubmit={handleSubmit}> + <div> + <label>제목</label> + <input + type="text" + name='title' + //value={title} + onChange={onChange} + required + /> + </div> + <div> + <label>Content</label> + <textarea + name='content' + //value={content} + onChange={onChange} + /> + </div> + <button style={{height:"50px"}}>wow</button> + </form> + </main> + </div> )