diff --git a/backend/src/index.js b/backend/src/index.js index 72a72b580a6d4c05697dd640f41764b98b356e80..0e7f8b724572e3ecea8abbdcc05978a75c49110c 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -36,11 +36,14 @@ app.use( credentials: true, }) ); //cors 설정을 한다.. -app.use(express.static(path.join(process.cwd(), '../frontend/public'))); +// app.use(express.static(path.join(process.cwd(), '../public'))); + +app.use(express.static('public')) + app.use(cookieParser()); app.use(express.json()); app.use(express.urlencoded({ extended: false })); - +console.log("hello") app.listen(PORT, () => { console.log(`Listening on port ${PORT}`); diff --git a/backend/src/models/article.js b/backend/src/models/article.js index d3ff4fd4bc6178e7e8f1ebcfd8855a9c163cce3b..9ac2e235b4ac1d635d8119f923e8a2dd5a1012ac 100644 --- a/backend/src/models/article.js +++ b/backend/src/models/article.js @@ -34,6 +34,18 @@ const ArticleSchema = new mongoose.Schema({ ref: 'User', required: true, }, + keyword: { + type: String, + required: true, + }, + latitude: { + type: Number, + required: true, + }, + longitude: { + type: Number, + required: true, + }, comments: { type: [CommentSchema], unique: false, @@ -46,6 +58,7 @@ const ArticleSchema = new mongoose.Schema({ type: Date, default: Date.now, }, + }); const Article = mongoose.model("Article", ArticleSchema); diff --git a/backend/src/post.js b/backend/src/post.js index 01fdc901aaa66cdc1de6c035fe1d03b26dba579f..14d6a471ee2c74126005a24c7295f64d2996b009 100644 --- a/backend/src/post.js +++ b/backend/src/post.js @@ -5,6 +5,8 @@ import path from 'path' import userService from './data/userService.js'; import articleService from './data/articleService.js'; +const __dirname = path.resolve(); + export const router = express.Router(); const upload = multer({ @@ -32,12 +34,18 @@ router.post("/upload", upload.array("img"), async function(req, res, next) { const inputImage = req.files.map(el => el.path); const useremail = req.session.sessionid.email const author = await userService.findUserByEmail(useremail); + const inputkeyword = req.body.keyword + const inputlat = req.body.latitude + const inputlng = req.body.longitude await articleService.createArticle({ title: inputTitle, content: inputContent, imageUrls: inputImage, author: author, + keyword: inputkeyword, + latitude: inputlat, + longitude: inputlng, comments: [], likes: [] }); @@ -47,7 +55,9 @@ router.post("/upload", upload.array("img"), async function(req, res, next) { res.send(); }); + router.get("/loadarticle", async (req, res) => { + console.log(path.join(process.cwd(), '/public')) if(req.session.sessionid){ console.log("세션 O") } @@ -55,8 +65,24 @@ router.get("/loadarticle", async (req, res) => { console.log("세션 X") } const articles = await articleService.findAllArticle(); + articles.forEach((article) => { + article.imageUrls.forEach( + (urls) => { + try{ + //res.sendFile(path.join(__dirname, urls)); + } + catch(err){ + console.log(err) + } + + }); + }); + const retval = { + + + } + // console.log(articles) console.log(articles) - console.log(JSON.stringify(articles)) res.send(JSON.stringify(articles) ); }); /* diff --git a/frontend/src/App.js b/frontend/src/App.js index a4bbc5b6c63608ec69ffc296d5e649981f4076e6..3a124be430eb685ef297809dc08a439bff525438 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,7 +1,7 @@ import "./css/App.css"; import {Routes, Route, Link, useNavigate, Navigate } from 'react-router-dom'; import React, { useEffect, useState, useContext} from 'react'; -import { UserContext } from './Usercontext.js'; +import { UserContext } from './Context.js'; import Main from "./pages/Main.js"; import Login from "./pages/Login.js"; diff --git a/frontend/src/Usercontext.js b/frontend/src/Context.js similarity index 54% rename from frontend/src/Usercontext.js rename to frontend/src/Context.js index 319ac09ef3bfdb124bda439d505ea15f315a37f9..effc8f2097cc4e9314180c352db2e812d02d390c 100644 --- a/frontend/src/Usercontext.js +++ b/frontend/src/Context.js @@ -1,9 +1,15 @@ import { createContext } from 'react'; -export const UserContext = createContext({ +const UserContext = createContext({ IsloggedIn : false, UserName : "", LogIn : ()=>{}, LogOut : ()=>{}, CheckSession : ()=>{} -}); \ No newline at end of file +}); + +const LocationContext = createContext({ + +}); + +export {UserContext, LocationContext} \ No newline at end of file diff --git a/frontend/src/components/Article.js b/frontend/src/components/Article.js index 372c73ba2665d66deb4cb22ff0e4d489842d0f90..7c34f7615c667d728c2dcc9317c1f448fbd70e9d 100644 --- a/frontend/src/components/Article.js +++ b/frontend/src/components/Article.js @@ -7,10 +7,11 @@ function Article(prop) { console.log(prop) let listItem = [] listItem = prop.images.map((el)=>{ + // http://localhost:8080/uploads/21701487062905.png return( <img - src={`http://localhost:8080/${el}`} - alt={`http://localhost:8080/${el}`} + src={`http://localhost:8080/${el.replaceAll("\\", "/").substring(7)}`} + alt={`http://localhost:8080/${el.replaceAll("\\", "/").substring(7)}`} style={{ width: "100px", height: "100px"}}/> )}); diff --git a/frontend/src/components/GoogleLoginButton.js b/frontend/src/components/GoogleLoginButton.js index cf08478822f42fa85f005261da2593934b7395f5..dc33d9d266094924f6fd4e3eda66924cf3756812 100644 --- a/frontend/src/components/GoogleLoginButton.js +++ b/frontend/src/components/GoogleLoginButton.js @@ -3,7 +3,7 @@ import { GoogleOAuthProvider } from "@react-oauth/google"; import { useNavigate, Navigate } from "react-router-dom"; import { useCookies } from 'react-cookie' import React, { useEffect, useState, useContext} from 'react'; -import { UserContext } from '../Usercontext.js'; +import { UserContext } from '../Context.js'; // 안써도 자동으로 한국 시간을 불러온다. 명확하게 하기 위해 import import moment from 'moment'; diff --git a/frontend/src/components/Header.js b/frontend/src/components/Header.js index 6b0147da3d022484a247ea756018e644c078a5eb..05b61784ef93c4fd7efc492d7d20ee28857b1434 100644 --- a/frontend/src/components/Header.js +++ b/frontend/src/components/Header.js @@ -1,7 +1,7 @@ import logo from '../logo.png'; import '../css/Header.css'; -import { UserContext } from '../Usercontext.js'; +import { UserContext } from '../Context.js'; import React, { useEffect, useState, useContext} from 'react'; import { Link, useNavigate, Navigate } from "react-router-dom"; diff --git a/frontend/src/components/SearchMapByKeyword.js b/frontend/src/components/SearchMapByKeyword.js index 59d21e41e8c99cade1799f45838621c75461b10e..f0b66165fcd587a9666144279e454b0be1db0ed0 100644 --- a/frontend/src/components/SearchMapByKeyword.js +++ b/frontend/src/components/SearchMapByKeyword.js @@ -50,9 +50,6 @@ function SearchMapByKeyword({loc, setLoc}){ <div className="UserInput"> <input onChange={handleInput}/> <button onClick={()=>handleSearch()}>검색</button><br></br> - <input readOnly={true} type="text" placeholder="장소 키워드" value={loc.keyword}/> - <input readOnly={true} type="text" placeholder="위도" value={loc.center.lat}/> - <input readOnly={true} type="text" placeholder="경도" value={loc.center.lng}/> <Map // 지도를 표시할 Container center={markers[0] && markers[0].position || defaultCenter} style={{ diff --git a/frontend/src/pages/Login.js b/frontend/src/pages/Login.js index 48eb7330de8514d7495cd200bbc84d8f0f4e5e9a..b21550ea33e49e1e155092ff1ffe8bc6b3e26fab 100644 --- a/frontend/src/pages/Login.js +++ b/frontend/src/pages/Login.js @@ -2,7 +2,7 @@ import { useNavigate } from 'react-router-dom'; import GoogleLoginButton from "../components/GoogleLoginButton.js"; import React, { useState, useEffect, useContext } from 'react'; -import { UserContext } from '../Usercontext.js'; +import { UserContext } from '../Context.js'; function Button({history, children}){ const navigate = useNavigate(); return( diff --git a/frontend/src/pages/Main.js b/frontend/src/pages/Main.js index 7e5fece1f8e8a8f4dab4a74597d43ace7484ff62..b29a63029a6f43d8d38d603fbf0bf79e50303e2d 100644 --- a/frontend/src/pages/Main.js +++ b/frontend/src/pages/Main.js @@ -1,6 +1,6 @@ import { useNavigate } from 'react-router-dom'; import cookie from 'react-cookies'; -import { UserContext } from '../Usercontext.js'; +import { UserContext } from '../Context.js'; import Article from '../components/Article.js'; import React, { useEffect, useState, useContext} from 'react'; diff --git a/frontend/src/pages/PostWrite.js b/frontend/src/pages/PostWrite.js index 3a52ad00d4d07f96e92ff90118e32a80a5df854c..58259a9dfd09f9caf86baa9cb18c02f3dbdda098 100644 --- a/frontend/src/pages/PostWrite.js +++ b/frontend/src/pages/PostWrite.js @@ -1,7 +1,7 @@ import React, { useRef, useState, useEffect, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; -import { UserContext } from '../Usercontext.js'; +import { UserContext } from '../Context.js'; import SearchMap from '../components/SearchMapByKeyword.js' import axios from 'axios'; @@ -31,102 +31,18 @@ function PostWrite(){ console.log(response) }) }); - /* - - - - - - - const [inputs, setInputs] = useState({ - title: "", - content: "", + const [previewImg, setPreviewImg] = useState({ imageUrls: [], }); - const [previewImg, setPreviewImg] = useState({ - imageUrls: [], - }); - const imgRef = useRef(); - - // 이미지 업로드 input의 onChange - const saveImgFile = async () => { - console.log(imgRef.current.files) - const file = imgRef.current.files[0]; - console.log(file) - inputs.imageUrls.push(file); - setInputs({ - ...inputs, - imageUrls: inputs.imageUrls - }) - - const reader = new FileReader(); - reader.readAsDataURL(file); - reader.onloadend = () => { - previewImg.imageUrls.push(reader.result); - setPreviewImg({ - imageUrls: previewImg.imageUrls - }); - }; - }; - - let imglist = []; - imglist = previewImg.imageUrls.map((image)=>{ - return( - <img - src={image ? image :null} - alt="이미지" - style={{ width: "100px", height: "100px"}} - /> - ) - } - ); - - const handleSubmit= async (event) => { - event.preventDefault(); - - try { - console.log(inputs) - const response = await axios({ - url: 'http://localhost:8080/post/upload', // 통신할 웹문서 - method: 'post', // 통신할 방식 - headers: {'Content-Type': 'multipart/form-data', charset: 'utf-8'}, - data: inputs - }); - if (response.status === 200) { - MoveTo('/') - return response.data; - } - else { - return null; - } - - } - catch (error){ - console.log('Error during post creation:', error); - } - } - - - const onChange = (e) => { - const {value, name} = e.target; - setInputs({ - ...inputs, - [name]: value - }); - } - */ + const [content, setContent] = useState(""); const [inputs, setInputs] = useState({ title: "", content: "", }); - const [content, setContent] = useState(""); - const [uploadedImg, setUploadedImg] = useState({ - fileName: "", - fillPath: "" - }); - const BASE_URL = "http://localhost:3000"; + + const onTextChange = (e) => { const {value, name} = e.target; @@ -135,123 +51,134 @@ function PostWrite(){ [name]: value }); } + const onImgChange = e => { let temp = [] for (let i=0; i< e.target.files.length; i++) { temp.push(e.target.files[i]) } + setContent(e.target.files); - }; + Array.from(e.target.files).forEach((file) => { + const reader = new FileReader(); + console.log(file) + reader.readAsDataURL(file); + reader.onloadend = () => { + previewImg.imageUrls.push(reader.result); + setPreviewImg({ + imageUrls: previewImg.imageUrls + }); + }; + }); + }; + let imglist = []; + imglist = previewImg.imageUrls.map((image)=>{ + return( + <img + src={image ? image :null} + alt="이미지" + style={{ width: "100px", height: "100px"}} + /> + ) + } + ); const onSubmit = e => { + e.preventDefault(); + + if (!location.keyword) { + alert("위치를 알려주세요."); + return + } + + if (!inputs.title) { + alert("제목을 입력해주세요."); + return + } + + if (!inputs.content) { + alert("내용을 입력해주세요."); + return + } + const formData = new FormData(); Array.from(content).forEach((el) => { formData.append("img", el); }); formData.append("title", inputs.title); formData.append("content", inputs.content); - + formData.append("keyword", location.keyword); + formData.append("latitude", location.center.lat); + formData.append("longitude", location.center.lng); axios .post("http://localhost:8080/post/upload", formData, { headers: {"Content-Type": "multipart/form-data"} }) .then(res => { - const { fileName } = res.data; - console.log(fileName); - setUploadedImg({ fileName, filePath: `${BASE_URL}/img/${fileName}` }); alert("The file is successfully uploaded"); + MoveTo('/') }) .catch(err => { console.error(err); }); }; + // <input readOnly={true} type="text" placeholder="장소 키워드" value={location.keyword} /> + // <input readOnly={true} type="text" placeholder="위도" value={location.center.lat} /> + // <input readOnly={true} type="text" placeholder="경도" value={location.center.lng} /> + return( <> - <section> - <div style={{float: "left"}}> - <SearchMap loc={location} setLoc={setLocation}></SearchMap> - </div> - <div style={{float: "right"}}> - <form onSubmit={onSubmit}> - <div> - <label>제목</label> - <input - type="text" - name='title' - onChange={onTextChange} - required/> - </div> - <div> - <label>Content</label> - <input - type="text" - name='content' - onChange={onTextChange} - required/> - </div> - <input type="file" onChange={onImgChange} multiple/> - <button type="submit">Upload</button> - </form> - </div> - - </section> - - - </> - - ) -/* - return( - <div> - <aside style={{float: "left"}}> - <SearchMap loc={location} setLoc={setLocation}></SearchMap> - </aside> - <main style={{float: "right"}}> - <form onSubmit={handleSubmit} enctype="multipart/form-data"> - <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> - <div> + <section style={{display: "flex"}}> + <div> + <SearchMap loc={location} setLoc={setLocation}></SearchMap> + </div> + <div> + <form onSubmit={onSubmit}> + <div style={{display: "flex"}}> + <input readOnly={true} type="text" placeholder="장소 키워드" value={location.keyword} /> + <button type="button" onClick={()=>{ + setLocation({ + keyword: "", + center: { lat: null, lng: null } + })}}>선택 해제</button> + </div> + <div style={{display: "grid"}}> + <label>제목</label> + <input + type="text" + name='title' + onChange={onTextChange} + /> + </div> + <div style={{display: "grid"}}> + <label>Content</label> + <input + type="text" + name='content' + onChange={onTextChange} + /> + </div> + <div style={{display: "grid"}}> + <div style={{display: "flex"}}> {imglist} - <label className="signup-profileImg-label" htmlFor="profileImg">이미지 추가</label> - <input - name="image" - style={{ display: "none"}} - className="signup-profileImg-input" - type="file" - accept="image/*" - id="profileImg" - onChange={()=>{saveImgFile()}} - ref={imgRef}/> </div> - </form> - </main> - </div> + <label htmlFor="profileImg">이미지 업로드</label> + <input style={{ display: "none"}} id="profileImg" type="file" onChange={onImgChange} multiple/> + </div> + <button type="submit">포스팅!</button> + + </form> + </div> + + </section> + </> ) -*/ - } /* diff --git a/frontend/src/pages/Search.js b/frontend/src/pages/Search.js index 4c06db0b4da5289ed33adadc953ec85368697679..8a1d22977e63e10612c8557ccbfe3f45fac7fbc7 100644 --- a/frontend/src/pages/Search.js +++ b/frontend/src/pages/Search.js @@ -2,7 +2,7 @@ import { Map, MapMarker } from "react-kakao-maps-sdk"; import React, { useState, useEffect, useContext } from 'react'; import {Routes, Route, Link, useNavigate, Navigate } from 'react-router-dom'; -import { UserContext } from '../Usercontext.js'; +import { UserContext } from '../Context.js'; const {kakao} = window; //카카오 지도 API를 이용한 검색(예정)