Commit ac3ddf08 authored by Yoon, Daeki's avatar Yoon, Daeki 😅
Browse files

Merge branch 'develop' into main-dev

parents 9d3f66f3 4a7a2303
...@@ -48,7 +48,7 @@ export function MySlide({ slides}: num) { ...@@ -48,7 +48,7 @@ export function MySlide({ slides}: num) {
{slides.slice(page - 1, page + 2).map((slide) => ( {slides.slice(page - 1, page + 2).map((slide) => (
<div key={Math.random()} className="min-w-full" <div key={Math.random()} className="min-w-full"
> >
<div key={slide} className={`inline-grid grid-cols-2 ${style}`}> <div key={slide} className={`inline-grid grid-cols-2 ${style} min-w-full`}>
{slide} {slide}
</div> </div>
</div> </div>
......
...@@ -35,11 +35,9 @@ export default function Login() { ...@@ -35,11 +35,9 @@ export default function Login() {
setLoading(true); setLoading(true);
await login(user.email, user.password, () => { await login(user.email, user.password, () => {
if (user.email == "admin@korea.ac.kr" && user.password == "111111") {
navigate("/admin", { replace: true }); navigate("/", { replace: true });
} else {
navigate("/", { replace: true });
}
}); });
// console.log("서버연결됬나요", res); // console.log("서버연결됬나요", res);
// console.log("로그인"); // console.log("로그인");
......
...@@ -59,7 +59,7 @@ export default function Profile() { ...@@ -59,7 +59,7 @@ export default function Profile() {
const user: Profile = await profileApi.profile(); const user: Profile = await profileApi.profile();
console.log("user in effect", user); console.log("user in effect", user);
setEmail(user.email); setEmail(user.email);
setAvatarUrl(user.avatar?.newfilename); setAvatarUrl(user.fileInfo?.newfilename);
setProfile({ ...profile, name: user.name }); setProfile({ ...profile, name: user.name });
}; };
getProfile(); getProfile();
......
...@@ -77,12 +77,12 @@ export default function Signup() { ...@@ -77,12 +77,12 @@ export default function Signup() {
<div className="flex flex-col "> <div className="flex flex-col ">
<div className="border-0 border-y-2 border-black"> <div className="border-0 border-y-2 border-black">
<div className="h-16 flex "> <div className="h-16 flex ">
<div className="whitespace-nowrap grid place-items-center basis-1/5 shrink-0 border-0 border-r-2"> <div className="whitespace-nowrap grid place-items-center w-32 lg:basis-1/5 shrink-0 border-0 border-r-2">
이름 이름
</div> </div>
<div className="grid place-items-center mx-5"> <div className="flex items-center mx-5">
<input <input
className="h-10 basis-1/5 border-2 focus:border-black" className="h-10 w-4/5 lg:w-60 border-2 focus:border-black"
type="text" type="text"
name="name" name="name"
onChange={handleChange} onChange={handleChange}
...@@ -90,12 +90,12 @@ export default function Signup() { ...@@ -90,12 +90,12 @@ export default function Signup() {
</div> </div>
</div> </div>
<div className="h-16 flex border-0 border-t-2"> <div className="h-16 flex border-0 border-t-2">
<div className="whitespace-nowrap grid place-items-center basis-1/5 shrink-0 border-0 border-r-2"> <div className="whitespace-nowrap grid place-items-center w-32 lg:basis-1/5 shrink-0 border-0 border-r-2">
이메일 이메일
</div> </div>
<div className="grid place-items-center mx-5"> <div className="flex items-center mx-5">
<input <input
className=" grid place-items-center h-10 basis-1/5 border-2 focus:border-black" className=" w-4/5 h-10 lg:w-60 border-2 focus:border-black"
type="email" type="email"
name="email" name="email"
onChange={handleChange} onChange={handleChange}
...@@ -103,12 +103,12 @@ export default function Signup() { ...@@ -103,12 +103,12 @@ export default function Signup() {
</div> </div>
</div> </div>
<div className="h-16 flex border-0 border-t-2"> <div className="h-16 flex border-0 border-t-2">
<div className="whitespace-nowrap grid place-items-center basis-1/5 shrink-0 border-0 border-r-2"> <div className="whitespace-nowrap grid place-items-center w-32 lg:basis-1/5 shrink-0 border-0 border-r-2">
비밀번호 비밀번호
</div> </div>
<div className="grid place-items-center mx-5"> <div className="flex items-center mx-5">
<input <input
className="grid place-items-center h-10 basis-1/5 border-2 focus:border-black" className="w-4/5 h-10 lg:w-60 border-2 focus:border-black"
type="password" type="password"
name="password" name="password"
onChange={handleChange} onChange={handleChange}
...@@ -117,13 +117,13 @@ export default function Signup() { ...@@ -117,13 +117,13 @@ export default function Signup() {
</div> </div>
<div className="h-16 flex border-0 border-t-2"> <div className="h-16 flex border-0 border-t-2">
<div className="whitespace-nowrap grid place-items-center basis-1/5 shrink-0 border-0 border-r-2"> <div className="whitespace-nowrap grid place-items-center w-32 lg:basis-1/5 shrink-0 border-0 border-r-2">
비밀번호 확인 비밀번호 확인
</div> </div>
<div className="grid place-items-center mx-5"> <div className="flex items-center mx-5">
<input <input
className="grid place-items-center h-10 basis-1/5 border-2 focus:border-black" className="w-4/5 h-10 lg:w-60 border-2 focus:border-black"
type="password" type="password"
name="password2" name="password2"
onChange={handleChange} onChange={handleChange}
......
import React, { useState, MouseEvent, useEffect } from "react"; import React, { useState, MouseEvent, useEffect } from "react";
import { Link } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import { PostType } from "../types"; import { PostType } from "../types";
import Post from "../post/post"; import Post from "../post/post";
import { postApi } from "../apis"; import { postApi } from "../apis";
import { useAuth } from "../auth/auth.context";
interface Posts { interface Posts {
posts: PostType[]; posts: PostType[];
} }
interface Newpost {
state: PostType;
}
export default function BoardPage() { export default function BoardPage() {
const [posts, setPosts] = useState<PostType[]>(); const [posts, setPosts] = useState<PostType[]>();
const location = useLocation() as Newpost;
const newPost = location.state;
const navigate = useNavigate();
const { user } = useAuth();
console.log("get newPost Info", newPost);
const setNewPosts = (newpost: PostType) => {
const postArr = posts?.splice(-1, 0, newPost);
if (!(postArr === undefined)) {
setPosts(postArr);
}
};
useEffect(() => { useEffect(() => {
getDataList(); getDataList();
setNewPosts(newPost);
}, []); }, []);
// posts // posts
const getDataList = async () => { const getDataList = async () => {
const res = await postApi.getData(); const res = await postApi.getData();
setPosts(res); setPosts(res); //posts = res
}; };
const titleHandleClick = async (event: MouseEvent<HTMLButtonElement>) => { const titleHandleClick = async (event: MouseEvent<HTMLButtonElement>) => {
...@@ -36,29 +55,37 @@ export default function BoardPage() { ...@@ -36,29 +55,37 @@ export default function BoardPage() {
} }
}; };
const GoLogin = async (event: React.MouseEvent) => {
if (!user.isLoggedIn) {
alert("로그인이 필요합니다.");
navigate("/login", { replace: true });
}
};
return ( return (
<div className="flex flex-col "> <div className="flex flex-col ">
<div className="flex flex-col mt-6"> <div className="flex flex-col mt-6">
<div className="text-2xl">자유 게시판</div> <div className="text-2xl whitespace-nowrap">자유 게시판</div>
<div className="text-sm mt-5">여행지 후기를 남겨주세요!</div> <div className="text-sm mt-5 whitespace-nowrap">
여행지 후기를 남겨주세요!
</div>
</div> </div>
<div className="flex flex-col w-full mt-16"> <div className="flex flex-col w-full mt-16">
<div className="flex justify-end"> <div className="flex justify-end">
<div className="border-2 border-blue-500 rounded mb-2"> <div className="border-2 border-blue-500 rounded mb-2 whitespace-nowrap">
<Link to="/posting"> <button onClick={GoLogin}>
<button>글쓰기</button> <Link to="/posting">글쓰기</Link>
</Link> </button>
</div>{" "} </div>
{/* Link */}
</div> </div>
<div className="sm:overflow-y-auto"> <div className="sm:overflow-y-auto">
<div className="flex place-items-center divide-x-2 border-2 border-solid border-y-2 h-10 bg-gradient-to-r from-cyan-500 to-blue-500 "> <div className="whitespace-nowrap flex place-items-center divide-x-2 border-2 border-solid border-y-2 h-10 bg-gradient-to-r from-cyan-500 to-blue-500 ">
<div className="basis-full">제목</div> <div className="basis-full">제목</div>
<div className="basis-3/12">게시 날짜</div> <div className="basis-3/12">게시 날짜</div>
<div className="basis-2/12">조회수</div> <div className="basis-2/12">조회수</div>
</div> </div>
<div className=""> <div className="whitespace-nowrap">
{posts?.map((post, i) => ( {posts?.map((post, i) => (
<Post key={i} post={post} handleClick={titleHandleClick} /> <Post key={i} post={post} handleClick={titleHandleClick} />
))} ))}
......
...@@ -21,10 +21,10 @@ export default function Body() { ...@@ -21,10 +21,10 @@ export default function Body() {
imgsData(); imgsData();
}, []); }, []);
useEffect(() => { // useEffect(() => {
console.log(searchParams.get("theme"), searchParams.get("city")); // console.log(searchParams.get("theme"), searchParams.get("city"));
setSearchParams(searchParams); // setSearchParams(searchParams);
}, []); // }, []);
const themeHandleClick = (event: MouseEvent<HTMLButtonElement>) => { const themeHandleClick = (event: MouseEvent<HTMLButtonElement>) => {
console.log(`theme id= ${event.currentTarget.id}`); console.log(`theme id= ${event.currentTarget.id}`);
...@@ -65,16 +65,16 @@ export default function Body() { ...@@ -65,16 +65,16 @@ export default function Body() {
Idpics.slice(i * limit, i * limit + limit).map( Idpics.slice(i * limit, i * limit + limit).map(
(picture, index: number) => ( (picture, index: number) => (
<div <div
className={`m-1 shrink-0 rounded shadow-md h-45 relative overflow-hidden`} className={`m-1 shrink-0 rounded shadow-md h-50 relative overflow-hidden`}
key={index} key={index}
> >
<img <img
src={ src={
"http://localhost:3000/images/" + picture.fileInfo.newfilename "http://localhost:3000/images/" + picture.fileInfo.newfilename
} }
className="w-full h-40 object-cover hover:scale-110 transition duration-0 hover:duration-500" className="w-full h-48 object-cover hover:scale-110 transition duration-0 hover:duration-500"
/> />
<div className="bg-transparent text-neutral-50 text-xs rounded-full absolute bottom-0 ml-1 mb-1 hover:scale-110 transition duration-0 hover:duration-500"> <div className="bg-transparent text-neutral-50 text-xs md:text-lg rounded-full absolute bottom-0 ml-1 mb-1 hover:scale-110 transition duration-0 hover:duration-500">
<span>{picture.title}</span> <span>{picture.title}</span>
</div> </div>
</div> </div>
......
...@@ -14,20 +14,20 @@ export default function Header() { ...@@ -14,20 +14,20 @@ export default function Header() {
}; };
return ( return (
<div className="flex flex-col lg:px-56 "> <div className="flex flex-col md:px-56 ">
<div className="flex flex-col-reverse pt-3 pb-12 border-b-2 border-sky-200 bg-gradient-to-t from-sky-200"> <div className="flex flex-col-reverse pt-3 pb-12 border-b-2 border-sky-200 bg-gradient-to-t from-sky-200">
<div className="flex mt-5 justify-between pr-3"> <div className="flex mt-5 justify-between pr-3">
<button className="ml-3 shrink-0 text-2xl"> <button className="ml-3 shrink-0 md:text-2xl">
<Link to="/" className="hover:text-sky-300 active:text-purple-500"> <Link to="/" className="hover:text-sky-300 active:text-purple-500">
Travel Report Travel Report
</Link> </Link>
</button> </button>
<div className="flex h-12"> <div className="flex h-12">
<input <input
className="ml-10 focus:outline-none focus:border-y-4 focus:border-l-4 focus:border-sky-500 w-20 w-40 md:w-4/5 border-y-4 border-l-4 border-sky-300 pl-9 rounded-l-full focus:border-0" className="ml-10 focus:outline-none focus:border-y-4 focus:border-l-4 focus:border-sky-500 w-3/5 md:w-4/5 border-y-4 border-l-4 border-sky-300 pl-9 rounded-l-full focus:border-0"
onChange={handleChange} onChange={handleChange}
/> />
<button className="shrink-0 bg-white border-y-4 border-r-4 border-sky-500 rounded-r-full pr-4"> <button className="whitespace-nowrap bg-white border-y-4 border-r-4 border-sky-500 rounded-r-full pr-4">
검색 검색
</button> </button>
</div> </div>
......
import React, { MouseEventHandler } from "react"; import React, { MouseEventHandler, useState } from "react";
type ThemeProps = { type ThemeProps = {
handleClick: MouseEventHandler; handleClick: MouseEventHandler;
}; };
export default function Theme({ handleClick }: ThemeProps) { export default function Theme({ handleClick }: ThemeProps) {
const [active, setActive] = useState(0);
const onactive = "whitespace-nowrap px-5 text-sky-300 ";
const offactive = "whitespace-nowrap px-5 ";
const clickActive = (a: number) => {
setActive(a);
};
return ( return (
<div className="overflow-x-auto flex rounded md:justify-center py-2 border-b-2 divide-x-2"> <div className="overflow-x-auto flex rounded py-2 md:p-2 border-b-2 divide-x-2">
<button <div onClick={() => clickActive(1)}>
id={"surfing"} <button
onClick={handleClick} id={"surfing"}
className="shrink-0 px-5 hover:text-sky-300 " onClick={handleClick}
> className={active === 1 ? onactive : offactive}
서핑 >
</button> 서핑
<button </button>
id={"activity"} </div>
onClick={handleClick} <div onClick={() => clickActive(2)}>
className="shrink-0 px-5 hover:text-sky-300" <button
> id={"activity"}
액티비티 onClick={handleClick}
</button> className={active === 2 ? onactive : offactive}
<button >
id={"camping"} 액티비티
onClick={handleClick} </button>
className="shrink-0 px-5 hover:text-sky-300 " </div>
> <div onClick={() => clickActive(3)}>
캠핑 <button
</button> id={"camping"}
<button onClick={handleClick}
id={"skiing"} className={active === 3 ? onactive : offactive}
onClick={handleClick} >
className="shrink-0 px-5 hover:text-sky-300" 캠핑
> </button>
스키 </div>
</button> <div onClick={() => clickActive(4)}>
<button <button
id={"boat"} id={"skiing"}
onClick={handleClick} onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300" className={active === 4 ? onactive : offactive}
> >
보트 스키
</button> </button>
<button </div>
id={"desert"} <div onClick={() => clickActive(5)}>
onClick={handleClick} <button
className="shrink-0 px-5 hover:text-sky-300" id={"boat"}
> onClick={handleClick}
사막 className={active === 5 ? onactive : offactive}
</button> >
<button 보트
id={"golf"} </button>
onClick={handleClick} </div>
className="shrink-0 px-5 hover:text-sky-300" <div onClick={() => clickActive(6)}>
> <button
골프 id={"desert"}
</button> onClick={handleClick}
<button className={active === 6 ? onactive : offactive}
id={"cave"} >
onClick={handleClick} 사막
className="shrink-0 px-5 hover:text-sky-300" </button>
> </div>
동굴 <div onClick={() => clickActive(7)}>
</button> <button
<button id={"golf"}
id={"history"} onClick={handleClick}
onClick={handleClick} className={active === 7 ? onactive : offactive}
className="shrink-0 px-5 hover:text-sky-300" >
> 골프
문화재 </button>
</button> </div>
<button <div onClick={() => clickActive(8)}>
id={"zoo"} <button
onClick={handleClick} id={"cave"}
className="shrink-0 px-5 hover:text-sky-300" onClick={handleClick}
> className={active === 8 ? onactive : offactive}
동물원 >
</button> 동굴
<button </button>
id={"cycling"} </div>
onClick={handleClick} <div onClick={() => clickActive(9)}>
className="shrink-0 px-5 hover:text-sky-300" <button
> id={"history"}
사이클링 onClick={handleClick}
</button> className={active === 9 ? onactive : offactive}
>
문화재
</button>
</div>
<div onClick={() => clickActive(10)}>
<button
id={"zoo"}
onClick={handleClick}
className={active === 10 ? onactive : offactive}
>
동물원
</button>
</div>
<div onClick={() => clickActive(11)}>
<button
id={"cycling"}
onClick={handleClick}
className={active === 11 ? onactive : offactive}
>
사이클링
</button>
</div>
</div> </div>
); );
} }
import React, { MouseEventHandler } from "react"; import React, { MouseEventHandler, useState } from "react";
type CityProps = { type CityProps = {
handleClick: MouseEventHandler; handleClick: MouseEventHandler;
}; };
export default function Citylist({ handleClick }: CityProps) { export default function Citylist({ handleClick }: CityProps) {
const [active, setActive] = useState(0);
const onactive = "text-start px-5 py-2 underline whitespace-nowrap";
const offactive = "text-start px-5 py-2 whitespace-nowrap";
const clickActive = (a: number) => {
setActive(a);
};
return ( return (
<div className="overflow-auto w-full flex flex-row md:flex-col md:mr-24 bg-sky-100"> <div className="overflow-auto w-full flex flex-row md:flex-col md:mr-24 bg-sky-100">
<div className="text-start px-5 py-2 bg-white whitespace-nowrap"> <div className="text-start px-5 py-2 bg-white whitespace-nowrap">
도시 도시
</div> </div>
<button <div onClick={() => clickActive(1)}>
id={"Seoul"} <button
onClick={handleClick} id={"Seoul"}
className="text-start px-5 py-2 hover:underline whitespace-nowrap" onClick={handleClick}
> className={active === 1 ? onactive : offactive}
서울 >
</button> 서울
<button </button>
id={"Busan"} </div>
onClick={handleClick} <div onClick={() => clickActive(2)}>
className="text-start px-5 py-2 hover:underline whitespace-nowrap" <button
> id={"Busan"}
부산 onClick={handleClick}
</button> className={active === 2 ? onactive : offactive}
<button >
id={"Incheon"} 부산
onClick={handleClick} </button>
className="text-start px-5 py-2 hover:underline whitespace-nowrap" </div>
> <div onClick={() => clickActive(3)}>
인천 <button
</button> id={"Incheon"}
<button onClick={handleClick}
id={"Daegoo"} className={active === 3 ? onactive : offactive}
onClick={handleClick} >
className="text-start px-5 py-2 hover:underline whitespace-nowrap" 인천
> </button>
대구 </div>
</button> <div onClick={() => clickActive(4)}>
<button <button
id={"Gwangjoo"} id={"Daegoo"}
onClick={handleClick} onClick={handleClick}
className="text-start px-5 py-2 hover:underline whitespace-nowrap" className={active === 4 ? onactive : offactive}
> >
광주 대구
</button> </button>
<button </div>
id={"Daejeon"} <div onClick={() => clickActive(5)}>
onClick={handleClick} <button
className="text-start px-5 py-2 hover:underline whitespace-nowrap" id={"Gwangjoo"}
> onClick={handleClick}
대전 className={active === 5 ? onactive : offactive}
</button> >
<button 광주
id={"Woolsan"} </button>
onClick={handleClick} </div>
className="text-start px-5 py-2 hover:underline whitespace-nowrap" <div onClick={() => clickActive(6)}>
> <button
울산 id={"Daejeon"}
</button> onClick={handleClick}
<button className={active === 6 ? onactive : offactive}
id={"Sejong"} >
onClick={handleClick} 대전
className="text-start px-5 py-2 hover:underline whitespace-nowrap" </button>
> </div>
세종 <div onClick={() => clickActive(7)}>
</button> <button
<button id={"Woolsan"}
id={"Dokdo"} onClick={handleClick}
onClick={handleClick} className={active === 7 ? onactive : offactive}
className="text-start px-5 py-2 hover:underline whitespace-nowrap" >
> 울산
독도 </button>
</button> </div>
<button <div onClick={() => clickActive(8)}>
id={"Jeju"} <button
onClick={handleClick} id={"Sejong"}
className="text-start px-5 py-2 hover:underline whitespace-nowrap" onClick={handleClick}
> className={active === 8 ? onactive : offactive}
제주 >
</button> 세종
{/* citylist */} </button>
</div>
<div onClick={() => clickActive(9)}>
<button
id={"Dokdo"}
onClick={handleClick}
className={active === 9 ? onactive : offactive}
>
독도
</button>
</div>
<div onClick={() => clickActive(10)}>
<button
id={"Jeju"}
onClick={handleClick}
className={active === 10 ? onactive : offactive}
>
제주
</button>
</div>
</div> </div>
// Citylist Page // Citylist Page
); );
......
import React, { FormEvent, useState, useEffect } from "react"; import React, { FormEvent, MouseEventHandler, useState } from "react";
import { useNavigate, useLocation } from "react-router-dom"; import { useNavigate, useLocation, Link } from "react-router-dom";
import isLength from "validator/lib/isLength"; import isLength from "validator/lib/isLength";
import equals from "validator/lib/equals"; import equals from "validator/lib/equals";
import { catchErrors } from "../helpers"; import { catchErrors } from "../helpers";
import { PostType } from "../types"; import { PostType } from "../types";
import { postApi } from "../apis"; import { postApi } from "../apis";
import { PostState } from "./intopost"; import { PostState } from "./intopost";
import { FileType } from "./intopost";
export function EditPost() { export function EditPost() {
const [city, setCity] = useState<string>("city"); const location = useLocation() as PostState;
const [theme, setTheme] = useState<string>("theme"); const post = location.state;
const [city, setCity] = useState<string>(post.city);
const [theme, setTheme] = useState<string>(post.theme);
const [title, setTitle] = useState<string>(""); const [title, setTitle] = useState<string>("");
const [text, setText] = useState<string>(""); const [text, setText] = useState<string>("");
const [file, setFile] = useState<FileList>(); const [file, setFile] = useState<FileList>();
const [imgSrc, setImgSrc] = useState<string[]>(); const [imgSrc, setImgSrc] = useState<string[]>();
const [filesList, setFilesList] = useState<FileType[]>(); const [change, setChange] = useState<boolean>(false);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation() as PostState;
const post = location.state;
const [user, setUser] = useState<PostType>({ const [user, setUser] = useState<PostType>({
title: post.title, title: post.title,
...@@ -30,6 +29,7 @@ export function EditPost() { ...@@ -30,6 +29,7 @@ export function EditPost() {
user: post.user, user: post.user,
counts: post.counts, counts: post.counts,
_id: post._id, _id: post._id,
file: post.file,
}); });
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
...@@ -37,24 +37,17 @@ export function EditPost() { ...@@ -37,24 +37,17 @@ export function EditPost() {
const [disabled, setDisabled] = useState(false); const [disabled, setDisabled] = useState(false);
const [success, setSuccess] = useState(false); const [success, setSuccess] = useState(false);
useEffect(() => {
getFilesList(post._id);
}, []);
const getFilesList = async (postId: string) => {
const res = await postApi.getFileByPostId(postId);
setFilesList(res);
};
const imgArr = new Array(); const imgArr = new Array();
const updateImg2Db = async (filelist: FileList) => { // console.log("post.file", post.file);
const updateImg2Db = async (filelist: FileList | undefined) => {
const formdata = new FormData(); const formdata = new FormData();
formdata.append("title", user.title); formdata.append("title", user.title);
formdata.append("text", user.text); formdata.append("text", user.text);
formdata.append("theme", user.theme); formdata.append("theme", user.theme);
formdata.append("city", user.city); formdata.append("city", user.city);
if (filelist === undefined || filelist === null) { if (filelist === undefined) {
const res = await postApi.updateImgAndPost(user._id, formdata); const res = await postApi.updateImgAndPost(user._id, formdata);
} else { } else {
for (var i = 0; i < filelist.length; i++) { for (var i = 0; i < filelist.length; i++) {
...@@ -69,14 +62,12 @@ export function EditPost() { ...@@ -69,14 +62,12 @@ export function EditPost() {
try { try {
if (confirm("게시물을 수정하시겠습니까?") == true) { if (confirm("게시물을 수정하시겠습니까?") == true) {
setError(""); setError("");
// console.log("user data", user);
if (postingFormMatch(user) === true) { if (postingFormMatch(user) === true) {
setLoading(true); setLoading(true);
if (file) {
const res = updateImg2Db(file); const updateRes = await updateImg2Db(file);
// console.log(res); navigate("/board", { replace: true, state: updateRes });
}
navigate("/board", { replace: true });
setSuccess(true); setSuccess(true);
setError(""); setError("");
} }
...@@ -92,9 +83,12 @@ export function EditPost() { ...@@ -92,9 +83,12 @@ export function EditPost() {
} }
const handleInputPic = async (event: React.ChangeEvent<HTMLInputElement>) => { const handleInputPic = async (event: React.ChangeEvent<HTMLInputElement>) => {
setChange(true);
const maxImg = 10; const maxImg = 10;
const { files } = event.target; const { files } = event.target;
// console.log("update file", files);
if (!(files === null)) { if (!(files === null)) {
setFile(files); setFile(files);
} }
...@@ -118,18 +112,18 @@ export function EditPost() { ...@@ -118,18 +112,18 @@ export function EditPost() {
function postingFormMatch(user: PostType) { function postingFormMatch(user: PostType) {
if (!isLength(user.title ?? "", { min: 1 })) { if (!isLength(user.title ?? "", { min: 1 })) {
setError("제목을 입력해 주세요.");
alert("제목을 입력해 주세요."); alert("제목을 입력해 주세요.");
setError("제목을 입력해 주세요.");
return false; return false;
} else if (!isLength(user.text ?? "", { min: 1 })) { } else if (!isLength(user.text ?? "", { min: 1 })) {
alert("내용을 입력해 주세요."); alert("내용을 입력해 주세요.");
setError("내용을 입력해 주세요."); setError("내용을 입력해 주세요.");
return false; return false;
} else if (equals(user.city, "city")) { } else if (equals(city, "city")) {
alert("도시를 선택해 주세요."); alert("도시를 선택해 주세요.");
setError("도시를 선택해 주세요."); setError("도시를 선택해 주세요.");
return false; return false;
} else if (equals(user.theme, "theme")) { } else if (equals(theme, "theme")) {
alert("테마를 선택해 주세요."); alert("테마를 선택해 주세요.");
setError("테마를 선택해 주세요."); setError("테마를 선택해 주세요.");
return false; return false;
...@@ -170,96 +164,127 @@ export function EditPost() { ...@@ -170,96 +164,127 @@ export function EditPost() {
setUser(newUser); setUser(newUser);
}; };
const GoBack = () => {
if (confirm("취소하시겠습니까?") == true) {
navigate(-1);
}
};
const oldFileShow = (post: PostType) => {
const res = post.file?.map((file, i) => (
<img
key={i}
src={"http://localhost:3000/images/" + file.newfilename}
width={200}
height={200}
/>
));
// console.log("oldfiles", res);
return res;
};
const newFileShow = (imgSrc: string[] | undefined) => {
const res = imgSrc?.map((img, i) => (
<img key={i} src={img} width={200} height={200} />
));
return res;
};
return ( return (
<form onSubmit={reWriteSubmit} className="flex flex-col w-full"> <div>
<div className="flex flex-row h-10 gap-x-1 justify-end"> <form onSubmit={reWriteSubmit} className="flex flex-col w-full">
<div className="place-self-center w-16 h-6 border-2 border-sky-400 transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-gray-300 duration-300"> <div className="flex flex-row h-10 gap-x-1 justify-end">
<input <div className="place-self-center w-16 h-6 border-2 border-sky-400 transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-gray-300 duration-300">
id="files" <input
type="file" id="files"
multiple type="file"
onChange={handleInputPic} multiple
className="hidden" onChange={handleInputPic}
/> className="hidden"
<label htmlFor="files" className="text-xs grid place-items-center"> />
파일 선택 <label htmlFor="files" className="text-xs grid place-items-center">
</label> 파일 선택
</div> </label>
</div>
<select <select
name="city" name="city"
className="border-2 border-sky-400 text-xs h-6 place-self-center" className="border-2 border-sky-400 text-xs h-6 place-self-center"
onChange={cityChange} onChange={cityChange}
defaultValue={post.city} defaultValue={post.city}
> >
<option value="city">도시</option> <option value="city">도시</option>
<option value="Seoul">서울</option> <option value="Seoul">서울</option>
<option value="Busan">부산</option> <option value="Busan">부산</option>
<option value="Incheon">인천</option> <option value="Incheon">인천</option>
<option value="Daegu">대구</option> <option value="Daegu">대구</option>
<option value="Gwangju">광주</option> <option value="Gwangju">광주</option>
<option value="Daejeon">대전</option> <option value="Daejeon">대전</option>
<option value="Woolsan">울산</option> <option value="Woolsan">울산</option>
<option value="Sejong">세종</option> <option value="Sejong">세종</option>
<option value="Dokdo">독도</option> <option value="Dokdo">독도</option>
<option value="Jeju">제주</option> <option value="Jeju">제주</option>
</select> </select>
<select <select
name="theme" name="theme"
className="border-2 border-sky-400 text-xs h-6 place-self-center" className="border-2 border-sky-400 text-xs h-6 place-self-center"
onChange={themeChange} onChange={themeChange}
defaultValue={post.theme} defaultValue={post.theme}
> >
<option value="theme">테마</option> <option value="theme">테마</option>
<option value="cycling">사이클링</option> <option value="cycling">사이클링</option>
<option value="surfing">서핑</option> <option value="surfing">서핑</option>
<option value="activity">액티비티</option> <option value="activity">액티비티</option>
<option value="camping">캠핑</option> <option value="camping">캠핑</option>
<option value="sking">스키</option> <option value="sking">스키</option>
<option value="boat">보트</option> <option value="boat">보트</option>
<option value="desert">사막</option> <option value="desert">사막</option>
<option value="golf">골프</option> <option value="golf">골프</option>
<option value="cave">동굴</option> <option value="cave">동굴</option>
<option value="history">문화재</option> <option value="history">문화재</option>
<option value="zoo">동물원</option> <option value="zoo">동물원</option>
<option value="cycling">사이클링</option> <option value="cycling">사이클링</option>
</select> </select>
<button <button
type="submit" type="submit"
className="h-6 w-10 place-self-center place-self-center border-2 border-sky-400 text-xs text-center transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300" className="h-6 w-10 place-self-center place-self-center border-2 border-sky-400 text-xs text-center transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300"
> >
수정 수정
</button> </button>
</div> </div>
<div className="flex flex-col w-full border-y-2 border-sky-500"> <div className="flex flex-col w-full border-y-2 border-sky-500">
<textarea <textarea
name="title" defaultValue={post.title}
onChange={titleChange} name="title"
placeholder="제목을 입력해 주세요!" onChange={titleChange}
className="flex focus:outline-none" placeholder="제목을 입력해 주세요!"
/> className="flex focus:outline-none"
<div className="flex flex-col mt-1 mb-1 border-t-2 border-sky-200"> />
<div className="flex gap-x-2 h-44 overflow-x-auto "> <div className="flex flex-col mt-1 mb-1 border-t-2 border-sky-200">
{filesList?.map((file, i) => ( <div className="flex gap-x-2 h-44 overflow-x-auto ">
<img {change ? newFileShow(imgSrc) : oldFileShow(post)}
key={i} </div>
src={"http://localhost:3000/images/" + file.newfilename}
width={200}
height={200}
/>
))}
</div> </div>
<textarea
defaultValue={post.text}
onChange={textChange}
name="text"
placeholder="여행 후기를 알려주세요!"
className="flex h-44 border-t-2 border-sky-200 focus:outline-none "
/>
</div> </div>
<textarea </form>
onChange={textChange} <div className="flex md:mb-20 justify-center">
name="text" <button
placeholder="여행 후기를 알려주세요!" onClick={GoBack}
className="flex h-44 border-t-2 border-sky-200 focus:outline-none " className=" mt-5 h-12 w-40 text-lg border-2 border-sky-500 place-self-center"
/> >
취소
</button>
</div> </div>
</form> </div>
); );
} }
...@@ -8,39 +8,18 @@ export interface PostState { ...@@ -8,39 +8,18 @@ export interface PostState {
state: PostType; state: PostType;
} }
export interface FileType {
id: string;
post: string;
originalfilename: string;
newfilename: string;
picturepath: string;
}
export interface FilesList {
filesList: FileType[];
}
export function IntoPost() { export function IntoPost() {
const location = useLocation() as PostState; const location = useLocation() as PostState;
const post = location.state; const post = location.state;
const navigate = useNavigate(); const navigate = useNavigate();
const [filesList, setFilesList] = useState<FileType[]>();
// console.log(post); console.log("user info", post.user);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(""); const [error, setError] = useState("");
const [addSuccess, setAddSuccess] = useState(false); const [addSuccess, setAddSuccess] = useState(false);
const [delSuccess, setDelSuccess] = useState(false); const [delSuccess, setDelSuccess] = useState(false);
useEffect(() => {
getFilesList(post._id);
}, []);
const getFilesList = async (postId: string) => {
const res = await postApi.getFileByPostId(postId);
setFilesList(res);
};
const handleDeleteClick = async (event: MouseEvent<HTMLButtonElement>) => { const handleDeleteClick = async (event: MouseEvent<HTMLButtonElement>) => {
try { try {
if (confirm("삭제하시겠습니까?") == true) { if (confirm("삭제하시겠습니까?") == true) {
...@@ -79,7 +58,7 @@ export function IntoPost() { ...@@ -79,7 +58,7 @@ export function IntoPost() {
<div className="flex h-10 items-center border-t-2 border-sky-200 md:flex-row justify-between bg-slate-50 text-sm"> <div className="flex h-10 items-center border-t-2 border-sky-200 md:flex-row justify-between bg-slate-50 text-sm">
<div className="flex whitespace-nowrap pr-5 "> <div className="flex whitespace-nowrap pr-5 ">
작성자: {post.user.slice(0, 8)} 작성자: {post.user.name}
</div> </div>
<div className="flex divide-x divide-slate-300 "> <div className="flex divide-x divide-slate-300 ">
...@@ -95,7 +74,7 @@ export function IntoPost() { ...@@ -95,7 +74,7 @@ export function IntoPost() {
</div> </div>
<div className="flex border-t-2 border-sky-200 h-44 p-2 overflow-auto mb-5 "> <div className="flex border-t-2 border-sky-200 h-44 p-2 overflow-auto mb-5 ">
{filesList?.map((file, i) => ( {post.file?.map((file, i) => (
<img <img
key={i} key={i}
src={"http://localhost:3000/images/" + file.newfilename} src={"http://localhost:3000/images/" + file.newfilename}
......
import React, { FormEvent, useEffect, useState } from "react"; import React, { FormEvent, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
import isLength from "validator/lib/isLength"; import isLength from "validator/lib/isLength";
import equals from "validator/lib/equals"; import equals from "validator/lib/equals";
import { catchErrors } from "../helpers"; import { catchErrors } from "../helpers";
...@@ -21,9 +21,20 @@ export default function Posting() { ...@@ -21,9 +21,20 @@ export default function Posting() {
theme: "", theme: "",
city: "", city: "",
date: "", date: "",
user: "", user: {
_id: "",
name: "",
},
counts: 0, counts: 0,
_id: "", _id: "",
file: [
{
_id: "",
originalfilename: "",
newfilename: "",
picturepath: "",
},
],
}); });
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
...@@ -44,11 +55,15 @@ export default function Posting() { ...@@ -44,11 +55,15 @@ export default function Posting() {
formdata.append("picture", filelist?.[0]); formdata.append("picture", filelist?.[0]);
const res = await postApi.createFileAndPost(formdata); const res = await postApi.createFileAndPost(formdata);
return res;
} else { } else {
for (var i = 0; i < filelist.length; i++) { for (var i = 0; i < filelist.length; i++) {
formdata.append("picture", filelist?.[i]); formdata.append("picture", filelist?.[i]);
} }
const res = await postApi.createFileAndPost(formdata); const res = await postApi.createFileAndPost(formdata);
return res;
} }
} }
}; };
...@@ -58,16 +73,12 @@ export default function Posting() { ...@@ -58,16 +73,12 @@ export default function Posting() {
try { try {
if (confirm("게시물을 작성하시겠습니까?") == true) { if (confirm("게시물을 작성하시겠습니까?") == true) {
setError(""); setError("");
// console.log("user data", user); if (postingFormMatch(user, file)) {
if (!(imgSrc === undefined)) { setLoading(true);
if (postingFormMatch(user, imgSrc)) { if (file) {
setLoading(true); const postRes = await sendImg2Db(file);
if (file) { navigate("/board", { replace: true, state: postRes });
const res = sendImg2Db(file);
// console.log(res);
}
} }
navigate("/board", { replace: true });
setSuccess(true); setSuccess(true);
setError(""); setError("");
} }
...@@ -82,7 +93,7 @@ export default function Posting() { ...@@ -82,7 +93,7 @@ export default function Posting() {
} }
} }
function postingFormMatch(user: PostType, imgSrc: string[]) { function postingFormMatch(user: PostType, file: FileList | undefined) {
if (!isLength(user.title ?? "", { min: 1 })) { if (!isLength(user.title ?? "", { min: 1 })) {
alert("제목을 입력해 주세요."); alert("제목을 입력해 주세요.");
setError("제목을 입력해 주세요."); setError("제목을 입력해 주세요.");
...@@ -91,6 +102,10 @@ export default function Posting() { ...@@ -91,6 +102,10 @@ export default function Posting() {
alert("내용을 입력해 주세요."); alert("내용을 입력해 주세요.");
setError("내용을 입력해 주세요."); setError("내용을 입력해 주세요.");
return false; return false;
} else if (file === undefined) {
alert("사진을 첨부해 주세요.");
setError("사진을 첨부해 주세요.");
return false;
} else if (equals(city, "city")) { } else if (equals(city, "city")) {
alert("도시를 선택해 주세요."); alert("도시를 선택해 주세요.");
setError("도시를 선택해 주세요."); setError("도시를 선택해 주세요.");
...@@ -99,10 +114,6 @@ export default function Posting() { ...@@ -99,10 +114,6 @@ export default function Posting() {
alert("테마를 선택해 주세요."); alert("테마를 선택해 주세요.");
setError("테마를 선택해 주세요."); setError("테마를 선택해 주세요.");
return false; return false;
} else if (imgSrc === undefined || imgSrc === null) {
alert("사진을 첨부해 주세요.");
setError("사진을 첨부해 주세요.");
return false;
} else { } else {
return true; return true;
} }
...@@ -165,91 +176,107 @@ export default function Posting() { ...@@ -165,91 +176,107 @@ export default function Posting() {
} }
}; };
const GoBack = () => {
if (confirm("취소하시겠습니까?") == true) {
navigate(-1);
}
};
return ( return (
<form onSubmit={handlePostSubmit} className="flex flex-col w-full"> <div>
<div className="flex flex-row gap-x-1 justify-end h-10 "> <form onSubmit={handlePostSubmit} className="flex flex-col w-full">
<div className="place-self-center w-16 h-6 border-2 border-sky-400 transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-gray-300 duration-300"> <div className="flex flex-row gap-x-1 justify-end h-10 ">
<input <div className="place-self-center w-16 h-6 border-2 border-sky-400 transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-gray-300 duration-300">
id="files" <input
type="file" id="files"
multiple type="file"
onChange={handleInputPic} multiple
className="hidden" onChange={handleInputPic}
/> className="hidden"
<label htmlFor="files" className="text-xs grid place-items-center"> />
파일 선택 <label htmlFor="files" className="text-xs grid place-items-center">
</label> 파일 선택
</div> </label>
</div>
<select <select
name="city" name="city"
className="border-2 border-sky-400 text-xs h-6 place-self-center" className="border-2 border-sky-400 text-xs h-6 place-self-center"
onChange={cityChange} onChange={cityChange}
defaultValue="질문종류" defaultValue="질문종류"
> >
<option value="질문종류">도시</option> <option value="질문종류">도시</option>
<option value="Seoul">서울</option> <option value="Seoul">서울</option>
<option value="Busan">부산</option> <option value="Busan">부산</option>
<option value="Incheon">인천</option> <option value="Incheon">인천</option>
<option value="Daegu">대구</option> <option value="Daegu">대구</option>
<option value="Gwangju">광주</option> <option value="Gwangju">광주</option>
<option value="Daejeon">대전</option> <option value="Daejeon">대전</option>
<option value="Woolsan">울산</option> <option value="Woolsan">울산</option>
<option value="Sejong">세종</option> <option value="Sejong">세종</option>
<option value="Dokdo">독도</option> <option value="Dokdo">독도</option>
<option value="Jeju">제주</option> <option value="Jeju">제주</option>
</select> </select>
<select
name="theme"
className="border-2 border-sky-400 text-xs h-6 place-self-center"
onChange={themeChange}
defaultValue="질문종류"
>
<option value="질문종류">테마</option>
<option value="cycling">사이클링</option>
<option value="surfing">서핑</option>
<option value="activity">액티비티</option>
<option value="camping">캠핑</option>
<option value="sking">스키</option>
<option value="boat">보트</option>
<option value="desert">사막</option>
<option value="golf">골프</option>
<option value="cave">동굴</option>
<option value="history">문화재</option>
<option value="zoo">동물원</option>
<option value="cycling">사이클링</option>
</select>
<button <select
type="submit" name="theme"
className="h-6 place-self-center place-self-center border-2 border-sky-400 text-xs text-center transition ease-in-out delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300" className="border-2 border-sky-400 text-xs h-6 place-self-center"
> onChange={themeChange}
글쓰기 defaultValue="질문종류"
</button> >
</div> <option value="질문종류">테마</option>
<option value="cycling">사이클링</option>
<option value="surfing">서핑</option>
<option value="activity">액티비티</option>
<option value="camping">캠핑</option>
<option value="sking">스키</option>
<option value="boat">보트</option>
<option value="desert">사막</option>
<option value="golf">골프</option>
<option value="cave">동굴</option>
<option value="history">문화재</option>
<option value="zoo">동물원</option>
<option value="cycling">사이클링</option>
</select>
<div className="flex flex-col w-full border-y-2 border-sky-500"> <button
<textarea type="submit"
name="title" className="h-6 place-self-center place-self-center border-2 border-sky-400 text-xs text-center transition ease-in-out delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300"
onChange={titleChange} >
placeholder="제목을 입력해 주세요!" 글쓰기
className="flex focus:outline-none" </button>
/> </div>
<div className="flex flex-col mt-1 mb-1 border-t-2 border-sky-200">
<div className="flex gap-x-2 h-44 overflow-x-auto"> <div className="flex flex-col w-full border-y-2 border-sky-500">
{imgSrc?.map((img, i) => ( <textarea
<img key={i} src={img} width={200} height={200} /> name="title"
))} onChange={titleChange}
placeholder="제목을 입력해 주세요!"
className="flex focus:outline-none"
/>
<div className="flex flex-col mt-1 mb-1 border-t-2 border-sky-200">
<div className="flex gap-x-2 h-44 overflow-x-auto">
{imgSrc?.map((img, i) => (
<img key={i} src={img} width={200} height={200} />
))}
</div>
</div> </div>
<textarea
onChange={textChange}
name="text"
placeholder="여행 후기를 알려주세요!"
className="flex h-44 border-t-2 border-sky-200 focus:outline-none "
/>
</div> </div>
<textarea </form>
onChange={textChange} <div className="flex md:mb-20 justify-center">
name="text" <button
placeholder="여행 후기를 알려주세요!" onClick={GoBack}
className="flex h-44 border-t-2 border-sky-200 focus:outline-none " className=" mt-5 h-12 w-40 text-lg border-2 border-sky-500 place-self-center"
/> >
취소
</button>
</div> </div>
</form> </div>
); );
} }
...@@ -20,7 +20,18 @@ export interface PostType { ...@@ -20,7 +20,18 @@ export interface PostType {
date: string; date: string;
counts: number; counts: number;
_id: string; _id: string;
user: string; user: {
_id: string;
name: string;
};
file: [
{
_id: string;
originalfilename: string;
newfilename: string;
picturepath: string;
}
];
} }
export interface SignupUser { export interface SignupUser {
...@@ -37,7 +48,6 @@ export interface Profile { ...@@ -37,7 +48,6 @@ export interface Profile {
originalfilename: string; originalfilename: string;
newfilename: string; newfilename: string;
picturepath: string; picturepath: string;
nickname: string;
}; };
} }
......
...@@ -4,7 +4,11 @@ import { TypedRequest } from "../types"; ...@@ -4,7 +4,11 @@ import { TypedRequest } from "../types";
export const uploadFile = asyncWrap(async (reqExp, res, next) => { export const uploadFile = asyncWrap(async (reqExp, res, next) => {
const req = reqExp as TypedRequest; const req = reqExp as TypedRequest;
const form = formidable({ multiples: false, uploadDir: "uploads" }); const form = formidable({
multiples: false,
uploadDir: "uploads",
keepExtensions: true,
});
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
form.parse(req, (err, fields, files) => { form.parse(req, (err, fields, files) => {
...@@ -25,7 +29,11 @@ export const uploadFile = asyncWrap(async (reqExp, res, next) => { ...@@ -25,7 +29,11 @@ export const uploadFile = asyncWrap(async (reqExp, res, next) => {
export const uploadFiles = asyncWrap(async (reqExp, res, next) => { export const uploadFiles = asyncWrap(async (reqExp, res, next) => {
const req = reqExp as TypedRequest; const req = reqExp as TypedRequest;
const form = formidable({ multiples: true, uploadDir: "uploads" }); const form = formidable({
multiples: true,
uploadDir: "uploads",
keepExtensions: true,
});
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
form.parse(req, (err, fields, files) => { form.parse(req, (err, fields, files) => {
......
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import isLength from "validator/lib/isLength"; import isLength from "validator/lib/isLength";
import { TypedRequestAuth } from "./auth.controller";
import { asyncWrap } from "../helpers"; import { asyncWrap } from "../helpers";
import { mainimgDb } from "../db"; import { mainimgDb } from "../db";
import { TypedRequest } from "../types"; import { TypedRequest } from "../types";
import { ObjectId } from "mongoose"; import { ObjectId } from "mongoose";
import formidable from "formidable"; import formidable from "formidable";
import { TypedRequestAuth } from "./auth.controller";
export const createMainimg = asyncWrap(async (reqExp, res) => { export const createMainimg = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequestAuth<{ userId: ObjectId }>; const req = reqExp as TypedRequestAuth<{ userId: ObjectId }>;
...@@ -65,49 +65,58 @@ export const deleteMainimg = asyncWrap(async (req, res) => { ...@@ -65,49 +65,58 @@ export const deleteMainimg = asyncWrap(async (req, res) => {
}); });
export const updateMainimg = asyncWrap(async (reqExp, res) => { export const updateMainimg = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequestAuth<{ userId: ObjectId }>; const req = reqExp as TypedRequest;
const form = formidable({ // const { id } = reqExp.params;
uploadDir: "uploads", const { id, theme, city, title } = req.body;
keepExtensions: true, const { updatemainimg }: { updatemainimg: formidable.File } = req.files;
multiples: false, console.log("전부 제대로", id,theme, city, title, updatemainimg)
}); const img = await mainimgDb.updateOneMainimg(id, theme,city,title, updatemainimg);
form.parse(req, (err, fields, files) => { res.json(img);
if (!Array.isArray(files.updatemainimg)) { })
//파일 좁히기 중 // const form = formidable({
if ( // uploadDir: "uploads",
!( // keepExtensions: true,
Array.isArray(fields.id) || // multiples: false,
Array.isArray(fields.city) || // });
Array.isArray(fields.title) ||
Array.isArray(fields.theme) // form.parse(req, (err, fields, files) => {
) // if (!Array.isArray(files.updatemainimg)) {
) { // //파일 좁히기 중
const id = fields.id; // if (
const city = fields.city; // !(
const title = fields.title; // Array.isArray(fields.id) ||
const theme = fields.theme; // Array.isArray(fields.city) ||
console.log("error"); // Array.isArray(fields.title) ||
if (!(files.updatemainimg === undefined)) { // Array.isArray(fields.theme)
const originalfilename = files.updatemainimg?.originalFilename; // )
const newfilename = files.updatemainimg.newFilename; // ) {
if (!(originalfilename === null || newfilename === undefined)) { // const id = fields.id;
const imgRes = mainimgDb.updateOneMainimg( // const city = fields.city;
id, // const title = fields.title;
theme, // const theme = fields.theme;
city, // console.log("error");
title, // if (!(files.updatemainimg === undefined)) {
originalfilename, // const originalfilename = files.updatemainimg?.originalFilename;
newfilename // const newfilename = files.updatemainimg.newFilename;
); // if (!(originalfilename === null || newfilename === undefined)) {
return res.json(imgRes); // const imgRes = mainimgDb.updateOneMainimg(
} // id,
} else { // theme,
const imgRes = mainimgDb.updateOneMainimg(id, theme, city, title); // city,
return res.json(imgRes); // title,
} // // fileInfo
} // originalfilename,
} // newfilename
}); // );
}); // return res.json(imgRes);
// }
// } else {
// const imgRes = mainimgDb.updateOneMainimg(id, theme, city, title);
// return res.json(imgRes);
// }
// }
// }
// });
// });
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import formidable, { Fields, Files } from "formidable"; import formidable, { Fields, Files } from "formidable";
import { TypedRequestAuth } from "./auth.controller"; import { TypedRequestAuth } from "./auth.controller";
import equals from "validator/lib/equals";
import { asyncWrap } from "../helpers"; import { asyncWrap } from "../helpers";
import { postDb, userDb } from "../db"; import { postDb, userDb } from "../db";
import { TypedRequest } from "../types"; import { TypedRequest } from "../types";
import { Types } from "mongoose";
export const userByPostId = ( export const userByPostId = (
reqExp: Request, reqExp: Request,
...@@ -16,6 +18,60 @@ export const userByPostId = ( ...@@ -16,6 +18,60 @@ export const userByPostId = (
next(); next();
}; };
export const SubTract = (oldSet: Set<string>, newSet: Set<string>) => {
const keep = new Array<string>(); //유지
const drop = new Array<string>(); //삭제
const add = new Array<string>(); //추가
oldSet.forEach((oldname) => {
drop.push(oldname);
newSet.forEach((newname) => {
add.push(newname);
if (oldname === newname) {
keep.push(oldname);
}
});
});
const addSet = new Set(add);
const newAdd = [...addSet];
// console.log("before delete drop ", drop);
// console.log("before delete add ", add);
for (var i = 0; i < drop.length; i++) {
for (var j = 0; j < keep.length; j++) {
if (drop[i] === keep[j]) {
drop.splice(i, 1);
}
}
}
for (var i = 0; i < newAdd.length; i++) {
for (var j = 0; j < keep.length; j++) {
if (newAdd[i] === keep[j]) {
newAdd.splice(i, 1);
}
}
}
// console.log("spliced add", add);
const dropSet = new Set(drop);
const newDrop = [...dropSet];
const reAddSet = new Set(newAdd);
const reNewAdd = [...reAddSet];
const res = {
keep: keep,
drop: newDrop,
add: reNewAdd,
};
return res;
};
//Create //Create
export const createFileAndPost = asyncWrap(async (reqExp, res, next) => { export const createFileAndPost = asyncWrap(async (reqExp, res, next) => {
const req = reqExp as TypedRequestAuth<{ userId: string }>; const req = reqExp as TypedRequestAuth<{ userId: string }>;
...@@ -112,23 +168,22 @@ export const addCounts = asyncWrap(async (req, res) => { ...@@ -112,23 +168,22 @@ export const addCounts = asyncWrap(async (req, res) => {
return res.json(updateCounts); return res.json(updateCounts);
}); });
export const updatePost = asyncWrap(async (reqExp, res) => { export const updateOnePost = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequestAuth<{ userId: string }>; const req = reqExp as TypedRequestAuth<{ userId: string }>;
const { userId } = req.auth;
const userId = req.auth.userId;
const { postId } = req.params; const { postId } = req.params;
const oldSet = new Set<string>();
const newSet = new Set<string>();
const fileIdArr = new Array<Types.ObjectId>();
const form = formidable({ const form = formidable({
uploadDir: "uploads", uploadDir: "uploads",
keepExtensions: true, keepExtensions: true,
multiples: true, multiples: true,
}); });
const fileIdArr = new Array();
const oldSet = new Set();
const newSet = new Set();
form.parse(req, async (err, fields, files) => { form.parse(req, async (err, fields, files) => {
if (!Array.isArray(fields.title)) { if (!Array.isArray(fields.title)) {
const title = fields.title; const title = fields.title;
...@@ -138,83 +193,149 @@ export const updatePost = asyncWrap(async (reqExp, res) => { ...@@ -138,83 +193,149 @@ export const updatePost = asyncWrap(async (reqExp, res) => {
const theme = fields.theme; const theme = fields.theme;
if (!Array.isArray(fields.city)) { if (!Array.isArray(fields.city)) {
const city = fields.city; const city = fields.city;
if (!Array.isArray(fields.change)) {
const change = fields.change; console.log("check files", files);
const oldFiles = await postDb.getFilesByPostId(postId); if (files.picture === undefined || files.picture === null) {
if (!(oldFiles === undefined)) { const postRes2 = await postDb.updatePostRow(
for (var i = 0; (i = oldFiles.length); i++) { {
const oldFileName = postDb.getOriginalFileName(oldFiles[i]); title,
if (!(oldFileName === undefined)) { text,
oldSet.add(oldFileName); theme,
city,
date: Date.now(),
},
postId
);
console.log("no files update", postRes2);
} else {
if (Array.isArray(files.picture)) {
const oldFilesId = await postDb.getFilesByPostId(postId);
if (!(oldFilesId === undefined)) {
for (var i = 0; i < oldFilesId?.length; i++) {
const name = await postDb.getOriginalFileName(
oldFilesId[i]
);
if (!(name === undefined)) {
oldSet.add(name);
}
} }
} }
} console.log("OldSet", oldSet);
if (Array.isArray(files.picture)) { if (Array.isArray(files.picture)) {
for (var i = 0; i < files.picture.length; i++) { for (var i = 0; i < files.picture.length; i++) {
const newFileName = files.picture?.[i].originalFilename; const newFileName = files.picture?.[i].originalFilename;
if (!(newFileName === undefined)) { if (!(newFileName === undefined || newFileName === null)) {
newSet.add(newFileName); newSet.add(newFileName);
}
} }
} }
} console.log("NewSet", newSet);
const deleteFiles = new Array(); //유지, 삭제, 추가 구분하기
const addFiles = new Array(); const trdPart = SubTract(oldSet, newSet);
oldSet.forEach((oldName) => { console.log("keep", trdPart.keep);
newSet.forEach((newName) => { console.log("drop", trdPart.drop);
if (!(oldName === newName)) { console.log("add", trdPart.add);
deleteFiles.push(oldName);
addFiles.push(newName);
}
});
});
for (var i = 0; i < deleteFiles.length; i++) { // 삭제
const originalfilename = deleteFiles[i]; for (var i = 0; i < trdPart.drop.length; i++) {
const delRes = await postDb.deleteFileByName(originalfilename); const dropRes = await postDb.deleteFileByName(
} trdPart.drop[i]
);
console.log("delete counts", dropRes);
}
if (Array.isArray(files.picture)) { //유지
for (var i = 0; i < trdPart.keep.length; i++) {
const keepRes = await postDb.findByName(trdPart.keep[i]);
fileIdArr.push(keepRes[0]._id);
// console.log("keep Id", keepRes[0]._id);
}
//추가
for (var i = 0; i < files.picture.length; i++) { for (var i = 0; i < files.picture.length; i++) {
const originalfilename = files.picture?.[i].originalFilename; const originalfilename = files.picture?.[i].originalFilename;
const newfilename = files.picture?.[i].newFilename; const newfilename = files.picture?.[i].newFilename;
const filepath = files.picture?.[i].filepath; const filepath = files.picture?.[i].filepath;
for (var i = 0; i < addFiles.length; i++) { for (var j = 0; j < trdPart.add.length; j++) {
const original = addFiles[i]; const check = trdPart.add[j];
if (original === originalfilename) { if (originalfilename === check) {
const addRes = await postDb.createFilesRow( const addRes = await postDb.createFilesRow(
originalfilename, originalfilename,
newfilename, newfilename,
filepath filepath
); );
fileIdArr.push(addRes); fileIdArr.push(addRes._id);
} }
} }
} }
} } else {
const oldFilesId = await postDb.getFilesByPostId(postId);
if (!(oldFilesId === undefined)) {
for (var i = 0; i < oldFilesId?.length; i++) {
const name = await postDb.getOriginalFileName(
oldFilesId[i]
);
if (!(name === undefined)) {
oldSet.add(name);
}
}
}
console.log("OldSet", oldSet);
const updateRes = await postDb.updatedFileId(postId); const newFileName = files.picture.originalFilename;
const fileId = fileIdArr.concat(updateRes); if (!(newFileName === undefined || newFileName === null)) {
newSet.add(newFileName);
}
console.log("NewSet", newSet);
const postRes = await postDb.updatePostRow( //유지, 삭제, 추가 구분하기
{ const trdPart = SubTract(oldSet, newSet);
title,
text, //삭제
theme, for (var i = 0; i < trdPart.drop.length; i++) {
city, const dropRes = await postDb.deleteFileByName(
date: Date.now(), trdPart.drop[i]
user: userId, );
file: fileId, console.log("delete counts", dropRes);
}, }
postId
); //추가
console.log("plzplzplzpllzplzlpzplzzplz", postRes); const originalfilename = files.picture.originalFilename;
return res.json(postRes); const newfilename = files.picture.newFilename;
const filepath = files.picture.filepath;
for (var j = 0; j < trdPart.add.length; j++) {
const check = trdPart.add[j];
if (originalfilename === check) {
const addRes = await postDb.createFilesRow(
originalfilename,
newfilename,
filepath
);
fileIdArr.push(addRes._id);
}
}
}
} }
console.log("all fileId", fileIdArr);
//post정보 + file정보 update
const postRes1 = await postDb.updatePostRow(
{
title,
text,
theme,
city,
date: Date.now(),
file: fileIdArr,
},
postId
);
} }
} }
} }
...@@ -222,19 +343,11 @@ export const updatePost = asyncWrap(async (reqExp, res) => { ...@@ -222,19 +343,11 @@ export const updatePost = asyncWrap(async (reqExp, res) => {
}); });
}); });
//Delete // Delete
export const deleteOnePost = asyncWrap(async (req, res) => { export const deleteOnePost = asyncWrap(async (req, res) => {
const { postId } = req.params; const { postId } = req.params;
// console.log(postId);
const deleteCount = await postDb.deletePost(postId);
const deleteFileId = await postDb.getFilesByPostId(postId);
if (!(deleteFileId === undefined)) { const deleteCount = await postDb.deletePost(postId);
for (var i = 0; i < deleteFileId.length; i++) {
const deleteId = deleteFileId[i];
const deleteFile = await postDb.deleteFile(deleteId);
}
}
return res.json(deleteCount); return res.json(deleteCount);
}); });
export * as roleDb from "./role.db"; export * as roleDb from "./role.db";
export * as postDb from "./post.db"; export * as postDb from "./post.db";
export * as userDb from "./user.db"; export * as userDb from "./user.db";
export * as mainimgDb from "./mainimg.db" export * as mainimgDb from "./mainimg.db";
\ No newline at end of file
import { ObjectId } from "mongoose"; import { HydratedDocument, ObjectId } from "mongoose";
import { FileInfo, IFileInfo, Mainimg, MainimgType } from "../models"; import { FileInfo, IFileInfo, Mainimg, MainimgType } from "../models";
import fs from "fs/promises"; import fs from "fs/promises";
import { fileInfoCtrl } from "../controllers"; import { fileInfoCtrl } from "../controllers";
import formidable from "formidable";
export const createMainimg = async (mainimg: MainimgType, pic: IFileInfo) => { export const createMainimg = async (mainimg: MainimgType, pic: IFileInfo) => {
const newPic = await FileInfo.create({ const newPic = await FileInfo.create({
originalfilename: pic.originalfilename, originalfilename: pic.originalfilename,
newfilename: pic.newfilename, newfilename: pic.newfilename,
pictureauth: pic.picturepath, picturepath: pic.picturepath,
}); });
const newMainimg = await Mainimg.create({ const newMainimg = await Mainimg.create({
...@@ -43,41 +44,76 @@ export const updateOneMainimg = async ( ...@@ -43,41 +44,76 @@ export const updateOneMainimg = async (
theme: string, theme: string,
city: string, city: string,
title: string, title: string,
originalfilename?: string | null, fileInfo: formidable.File
newfilename?: string // originalfilename?: string | null,
// newfilename?: string
) => { ) => {
const newMainimg = await Mainimg.findById(_Id); // const newMainimg = await Mainimg.findById(_Id)
console.log("error2", _Id); const newMainimg = await Mainimg.findById(_Id).populate<{ fileInfo: IFileInfo }>(
if (!(newMainimg?.fileInfo === undefined)) { "fileInfo"
if (originalfilename === undefined) { );
await Mainimg.findByIdAndUpdate(newMainimg._id, {
theme: theme, console.log("error2", newMainimg);
city: city, if (!newMainimg) {
title: title, throw new Error("mainimg가 존재하지 않습니다")
}); }
console.log("errrror4"); if (
} else if ( fileInfo.originalFilename &&
!(originalfilename === undefined) && newMainimg?.fileInfo.originalfilename !== fileInfo.originalFilename
(!(theme === undefined) || ) {
!(city === undefined) || // 같지 않으면 기존의 파일을 디스크에서 삭제한 후
!(title === undefined)) try {
) { console.log("picturepath", newMainimg.fileInfo.picturepath)
await Mainimg.findByIdAndUpdate(newMainimg._id, { await fs.unlink(newMainimg.fileInfo.picturepath);
theme: theme, } catch (error) {
city: city, console.log("error", error);
title: title,
});
await FileInfo.findByIdAndUpdate(newMainimg.fileInfo._id, {
originalfilename: originalfilename,
newfilename: newfilename,
});
console.log("error6");
} else {
await FileInfo.findByIdAndUpdate(newMainimg.fileInfo._id, {
originalfilename: originalfilename,
newfilename: newfilename,
});
console.log("error5", newfilename, originalfilename, theme, city, title);
} }
} else console.log("error3", newMainimg); const mainimgAvatar = newMainimg.fileInfo as HydratedDocument<IFileInfo>;
}; // 기존 fileinfo의 파일이름과 경로 변경 설정
mainimgAvatar.originalfilename = fileInfo.originalFilename;
mainimgAvatar.newfilename = fileInfo.newFilename;
mainimgAvatar.picturepath = fileInfo.filepath;
await mainimgAvatar.save();
}
newMainimg.theme = theme;
newMainimg.city = city;
newMainimg.title = title;
await newMainimg.save();
console.log("mainimg updated", newMainimg);
return newMainimg;
}
// if (!(newMainimg?.fileInfo === undefined)) {
// if (originalfilename === undefined) {
// await Mainimg.findByIdAndUpdate(newMainimg._id, {
// theme: theme,
// city: city,
// title: title,
// });
// console.log("errrror4");
// } else if (
// !(originalfilename === undefined) &&
// (!(theme === undefined) ||
// !(city === undefined) ||
// !(title === undefined))
// ) {
// await Mainimg.findByIdAndUpdate(newMainimg._id, {
// theme: theme,
// city: city,
// title: title,
// });
// await FileInfo.findByIdAndUpdate(newMainimg.fileInfo._id, {
// originalfilename: originalfilename,
// newfilename: newfilename,
// });
// console.log("error6");
// } else {
// await FileInfo.findByIdAndUpdate(newMainimg.fileInfo._id, {
// originalfilename: originalfilename,
// newfilename: newfilename,
// });
// console.log("error5", newfilename, originalfilename, theme, city, title);
// }
// } else console.log("error3", newMainimg);
// };
\ No newline at end of file
import { Types, ObjectId } from "mongoose"; import { Types, ObjectId } from "mongoose";
import fs from "fs/promises";
import { Post, PostType } from "../models"; import { Post, PostType } from "../models";
import { FileInfo, IFileInfo } from "../models"; import { FileInfo, IFileInfo } from "../models";
...@@ -33,15 +34,14 @@ export const createFilesRow = async ( ...@@ -33,15 +34,14 @@ export const createFilesRow = async (
//Read //Read
export const getPosts = async () => { export const getPosts = async () => {
const posts = await Post.find({}).sort({ date: -1 }); const posts = await Post.find()
.populate("file")
.populate("user")
.sort({ date: -1 });
console.log("file nickname", posts);
return posts; return posts;
}; };
export const getFilesByPostId = async (postId: string) => {
const files = await Post.findOne({ _id: postId }).populate("file");
return files?.file;
};
//Update //Update
export const addOneCount = async (_id: string, counts: number) => { export const addOneCount = async (_id: string, counts: number) => {
const newCounts = await Post.findOneAndUpdate( const newCounts = await Post.findOneAndUpdate(
...@@ -61,7 +61,6 @@ export const updatePostRow = async (post: PostType, postId: string) => { ...@@ -61,7 +61,6 @@ export const updatePostRow = async (post: PostType, postId: string) => {
theme: post.theme, theme: post.theme,
city: post.city, city: post.city,
date: post.date, date: post.date,
user: post.user,
file: post.file, file: post.file,
}, },
{ new: true } { new: true }
...@@ -69,6 +68,11 @@ export const updatePostRow = async (post: PostType, postId: string) => { ...@@ -69,6 +68,11 @@ export const updatePostRow = async (post: PostType, postId: string) => {
return newPost; return newPost;
}; };
export const getFilesByPostId = async (postId: string) => {
const files = await Post.findOne({ _id: postId }).populate("file");
return files?.file; //file Types.ObjectId[]
};
export const getOriginalFileName = async (_id: Types.ObjectId) => { export const getOriginalFileName = async (_id: Types.ObjectId) => {
const file = await FileInfo.findOne({ _id: _id }); const file = await FileInfo.findOne({ _id: _id });
return file?.originalfilename; return file?.originalfilename;
...@@ -79,15 +83,26 @@ export const updatedFileId = async (_id: string) => { ...@@ -79,15 +83,26 @@ export const updatedFileId = async (_id: string) => {
return updatedFile?.file; return updatedFile?.file;
}; };
//Delete export const findByName = async (originalfilename: string) => {
export const deletePost = async (_id: string) => { const fileId = await FileInfo.find({ originalfilename });
const res = await Post.deleteOne({ _id: _id }); return fileId;
return res;
}; };
export const deleteFile = async (_id: Types.ObjectId) => { //Delete
const deleteOne = await FileInfo.deleteOne({ _id: _id }); export const deletePost = async (_id: string) => {
return deleteOne; const post = await Post.findById(_id);
if (!(post?.file === undefined)) {
for (var i = 0; i < post.file.length; i++) {
const fileId = post.file[i];
const ref = await FileInfo.findById(fileId);
if (!(ref?.newfilename === undefined)) {
await fs.unlink("../travel/uploads/" + ref?.newfilename);
}
await FileInfo.deleteOne({ _id: fileId });
}
const res = await Post.deleteOne({ _id: _id });
return res;
}
}; };
export const deleteFileByName = async (originalfilename: string) => { export const deleteFileByName = async (originalfilename: string) => {
......
...@@ -4,13 +4,11 @@ export interface IFileInfo { ...@@ -4,13 +4,11 @@ export interface IFileInfo {
originalfilename: string; originalfilename: string;
newfilename: string; newfilename: string;
picturepath: string; picturepath: string;
nickname?: string;
} }
const schema = new Schema<IFileInfo>({ const schema = new Schema<IFileInfo>({
originalfilename: { type: String, unique: true }, originalfilename: { type: String, unique: true },
newfilename: { type: String }, newfilename: { type: String },
nickname: { type: String },
picturepath: { type: String }, picturepath: { type: String },
}); });
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment