Commit 14bcff90 authored by Lee Soobeom's avatar Lee Soobeom
Browse files

Merge remote-tracking branch 'origin/MK20' into develop

parents 35f41d6b 154cb55a
...@@ -14,9 +14,9 @@ export const App = () => { ...@@ -14,9 +14,9 @@ export const App = () => {
<BrowserRouter> <BrowserRouter>
<Routes> <Routes>
<Route element={<Layout />}> <Route element={<Layout />}>
<Route path="login" element={<Login />} />
<Route path="signup" element={<Signup />} />
<Route path="/" element={<Header />}> <Route path="/" element={<Header />}>
<Route path="login" element={<Login />} />
<Route path="signup" element={<Signup />} />
<Route index element={<Body />} /> <Route index element={<Body />} />
<Route <Route
path="posting" path="posting"
......
...@@ -3,21 +3,21 @@ import { MainimgType } from "../types"; ...@@ -3,21 +3,21 @@ import { MainimgType } from "../types";
import baseUrl from "./baseUrl"; import baseUrl from "./baseUrl";
export const mainimg = async (formdata: FormData) => { export const mainimg = async (formdata: FormData) => {
const { data } = await axios.post(`${baseUrl}/mainimg`, formdata); const { data } = await axios.post(`${baseUrl}/mainimg`, formdata);
return data; return data;
}; };
export const delmainimg = async (_id : string) => { export const delmainimg = async (_id: string) => {
const { data } = await axios.delete(`${baseUrl}/mainimg/${_id}`); const { data } = await axios.delete(`${baseUrl}/mainimg/${_id}`);
return data; return data;
}; };
export const getmainimg = async () => { export const getmainimg = async () => {
const { data } = await axios.get(`${baseUrl}/mainimg`); const { data } = await axios.get(`${baseUrl}/mainimg`);
return data; return data;
}; };
export const updateimg = async (formdata: FormData,_id : string) => { export const updateimg = async (formdata: FormData, _id: string) => {
const { data } = await axios.put(`${baseUrl}/mainimg/${_id}`, formdata); const { data } = await axios.put(`${baseUrl}/mainimg/${_id}`, formdata);
return data; return data;
}; };
\ No newline at end of file
...@@ -6,14 +6,11 @@ export const profile = async () => { ...@@ -6,14 +6,11 @@ export const profile = async () => {
return data; return data;
}; };
export const picture = async (formdata: FormData) => { export const profileUpload = async (formdata: FormData) => {
await axios.post(`${baseUrl}/profile`, formdata);
};
export const nickname = async (formdata: FormData) => {
await axios.post(`${baseUrl}/profile`, formdata); await axios.post(`${baseUrl}/profile`, formdata);
}; };
export const deleteUser = async () => { export const deleteUser = async () => {
await axios.post(`${baseUrl}/profile/delete`); const success = await axios.delete(`${baseUrl}/profile/delete`);
return success;
}; };
...@@ -7,9 +7,7 @@ export const RequireAuth: FC<{ children: JSX.Element }> = ({ children }) => { ...@@ -7,9 +7,7 @@ export const RequireAuth: FC<{ children: JSX.Element }> = ({ children }) => {
const location = useLocation(); const location = useLocation();
if (!user.isLoggedIn) { if (!user.isLoggedIn) {
return ( return <Navigate to={"/"} state={{ from: location.pathname }} replace />;
<Navigate to={"/login"} state={{ from: location.pathname }} replace />
);
} }
return children; return children;
}; };
import React, { FormEvent, useEffect, useState, MouseEvent } from "react"; import React, { FormEvent, useEffect, useState, MouseEvent } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { mainimgApi } from "../apis"; import { mainimgApi } from "../apis";
// import { profileUpload } from "../apis/profile.api";
import { catchErrors } from "../helpers";
import { MainimgType } from "../types"; import { MainimgType } from "../types";
import { picture } from "../apis/profile.api"; import { picture } from "../apis/profile.api";
import { catchErrors } from "../helpers";
import { MySlide } from "./adminslide"; import { MySlide } from "./adminslide";
// export interface ImgState { // export interface ImgState {
// state: MainimgType; // state: MainimgType;
// } // }
export default function Admin() { export default function Admin() {
// 이미지 전체 불러오기 // 이미지 전체 불러오기
const [getimgs, setGetimgs] = useState<MainimgType[]>([]); const [getimgs, setGetimgs] = useState<MainimgType[]>([]);
async function imgsData() { async function imgsData() {
const imgs = await mainimgApi.getmainimg(); const imgs = await mainimgApi.getmainimg();
setGetimgs(imgs) setGetimgs(imgs);
}; }
useEffect(() => { useEffect(() => {
imgsData(); imgsData();
}, []); }, []);
// 이미지 추가하기
const [addimg, setAddimg] = useState<MainimgType>({
_id: "",
theme: "",
city: "",
title: "",
pic: { originalfilename: "", newfilename: "" },
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const [addSuccess, setAddSuccess] = useState(false);
const [delSuccess, setDelSuccess] = useState(false);
const [file, setFile] = useState<File>();
function handleSelectChange(event: React.ChangeEvent<HTMLSelectElement>) { // 이미지 추가하기
const { name, value } = event.currentTarget; const [addimg, setAddimg] = useState<MainimgType>({
console.log(value) _id: "",
setAddimg({ ...addimg, [name]: value }); theme: "",
} city: "",
function handleInputeChange(event: React.ChangeEvent<HTMLInputElement>) { title: "",
const { name, value } = event.currentTarget; pic: { originalfilename: "", newfilename: "" },
setAddimg({ ...addimg, [name]: value }); });
}; const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const [addSuccess, setAddSuccess] = useState(false);
const [delSuccess, setDelSuccess] = useState(false);
const [file, setFile] = useState<File>();
function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) { function handleSelectChange(event: React.ChangeEvent<HTMLSelectElement>) {
const file = e.target.files?.[0]; const { name, value } = event.currentTarget;
if (!(file === undefined)) { console.log(value);
setFile(file); setAddimg({ ...addimg, [name]: value });
} }
} function handleInputeChange(event: React.ChangeEvent<HTMLInputElement>) {
const { name, value } = event.currentTarget;
setAddimg({ ...addimg, [name]: value });
}
async function handleSubmit(event: FormEvent) { function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
event.preventDefault(); const file = e.target.files?.[0];
const formdata = new FormData(); if (!(file === undefined)) {
console.log(addimg); setFile(file);
formdata.append("city", addimg.city); }
formdata.append("theme", addimg.theme); }
formdata.append("title", addimg.title);
if (!(file === undefined)) {
formdata.append("mainimg", file);
console.log(formdata);
const res = await mainimgApi.mainimg(formdata);
console.log("확인 중 ", res);
alert("img 추가되었습니다");
};
};
// 이미지 삭제하기
async function handleDeleteClick(event: MouseEvent<HTMLButtonElement>) {
try {
if (confirm("삭제하시겠습니까?") == true) {
const picId = event.currentTarget.id;
console.log("picId : ", picId)
const res = await mainimgApi.delmainimg(picId);
console.log("delete img", res);
// setGetimgs(getimgs)
setDelSuccess(true);
setError("");
alert("img 삭제되었습니다");
} else {
return false;
}
}
catch (error) {
console.log("에러발생");
catchErrors(error, setError);
} finally {
setLoading(false);
};
};
let limit = 15;
const numPages = Math.ceil(getimgs.length / 15);
// const location = useLocation() as ImgState; async function handleSubmit(event: FormEvent) {
// const img = location.state; event.preventDefault();
const formdata = new FormData();
console.log(addimg);
formdata.append("city", addimg.city);
formdata.append("theme", addimg.theme);
formdata.append("title", addimg.title);
if (!(file === undefined)) {
formdata.append("mainimg", file);
console.log(formdata);
const res = await mainimgApi.mainimg(formdata);
console.log("확인 중 ", res);
alert("img 추가되었습니다");
}
}
const slides = [] // 이미지 삭제하기
for (let i = 0; i < numPages; i++) { async function handleDeleteClick(event: MouseEvent<HTMLButtonElement>) {
const k = [ try {
getimgs.slice(i * limit, i * limit + limit).map((picture, index: number) => ( if (confirm("삭제하시겠습니까?") == true) {
<div key={index}> const picId = event.currentTarget.id;
<div className={`m-1 shrink-0 bg-gray-200 rounded shadow-md `}> console.log("picId : ", picId);
<img const res = await mainimgApi.delmainimg(picId);
src={"http://localhost:3000/images/" + picture.pic.newfilename} console.log("delete img", res);
className="w-full h-10 md:h-20 object-center" // setGetimgs(getimgs)
/> setDelSuccess(true);
<p className="text-center text-xs">{picture.title}</p> setError("");
</div> alert("img 삭제되었습니다");
<div className="text-end"> } else {
<button className="border-r-2 border-r-indigo-500 text-xs"> return false;
<Link to={`/admin/${picture._id}`} state={picture}> }
수정 } catch (error) {
</Link> console.log("에러발생");
</button> catchErrors(error, setError);
<button id={picture._id} onClick={handleDeleteClick} className="text-xs"> } finally {
삭제 setLoading(false);
</button>
</div>
</div>
))]
slides.push(k);
} }
}
return ( let limit = 15;
<div> const numPages = Math.ceil(getimgs.length / 15);
<form onSubmit={handleSubmit}>
<div className="flex flex-wrap justify-center gap-3">
<div className="gap-3 md:flex ">
<select
name="city"
id="Questions"
className="border border-3 border-black w-20 my-5"
defaultValue="질문종류"
onChange={handleSelectChange}
>
<option value="질문종류">도시</option>
<option value="서울">서울</option>
<option value="부산">부산</option>
<option value="인천">인천</option>
<option value="대구">대구</option>
<option value="광주">광주</option>
<option value="대전">대전</option>
<option value="울산">울산</option>
<option value="세종">세종</option>
<option value="독도">독도</option>
<option value="제주">제주</option>
</select>
<select
name="theme"
id="Questions"
className="border border-3 border-black w-20 my-5"
defaultValue="질문종류"
onChange={handleSelectChange}
>
<option value="질문종류">테마</option>
<option value="사이클링">사이클링</option>
<option value="서핑">서핑</option>
<option value="액티비티">액티비티</option>
<option value="캠핑">캠핑</option>
<option value="스키">스키</option>
<option value="보트">보트</option>
<option value="사막">사막</option>
<option value="골프">골프</option>
<option value="동굴">동굴</option>
<option value="문화재">문화재</option>
<option value="동물원">동물원</option>
<option value="사이클링">사이클링</option>
</select>
<div className="flex items-center justify-end gap-3">
<input
type="file"
id="files"
className="hidden"
onChange={handleFileChange}
></input>
<label htmlFor="files" className="border-2 m-5">
이미지 선택
</label>
</div> // const location = useLocation() as ImgState;
<div className="flex items-center justify-end gap-3 mt-2 md:mt-0"> // const img = location.state;
<p>title :</p>
<input name="title" className="border-2 border-sky-500"
onChange={handleInputeChange} />
</div>
</div>
<div className="my-5 flex items-center">
<button className="border-2 border-gray-500 rounded ">추가</button>
</div>
</div>
</form>
<div className="flex justify-center">
<MySlide key={Math.random()}
slides={slides}
/>
const slides = [];
for (let i = 0; i < numPages; i++) {
const k = [
getimgs
.slice(i * limit, i * limit + limit)
.map((picture, index: number) => (
<div key={index}>
<div className={`m-1 shrink-0 bg-gray-200 rounded shadow-md `}>
<img
src={"http://localhost:3000/images/" + picture.pic.newfilename}
className="w-full h-10 md:h-20 object-center"
/>
<p className="text-center text-xs">{picture.title}</p>
</div>
<div className="text-end">
<button className="border-r-2 border-r-indigo-500 text-xs">
<Link to={`/admin/${picture._id}`} state={picture}>
수정
</Link>
</button>
<button
id={picture._id}
onClick={handleDeleteClick}
className="text-xs"
>
삭제
</button>
</div>
</div>
)),
];
slides.push(k);
}
return (
<div>
<form onSubmit={handleSubmit}>
<div className="flex flex-wrap justify-center gap-3">
<div className="gap-3 md:flex ">
<select
name="city"
id="Questions"
className="border border-3 border-black w-20 my-5"
defaultValue="질문종류"
onChange={handleSelectChange}
>
<option value="질문종류">도시</option>
<option value="서울">서울</option>
<option value="부산">부산</option>
<option value="인천">인천</option>
<option value="대구">대구</option>
<option value="광주">광주</option>
<option value="대전">대전</option>
<option value="울산">울산</option>
<option value="세종">세종</option>
<option value="독도">독도</option>
<option value="제주">제주</option>
</select>
<select
name="theme"
id="Questions"
className="border border-3 border-black w-20 my-5"
defaultValue="질문종류"
onChange={handleSelectChange}
>
<option value="질문종류">테마</option>
<option value="사이클링">사이클링</option>
<option value="서핑">서핑</option>
<option value="액티비티">액티비티</option>
<option value="캠핑">캠핑</option>
<option value="스키">스키</option>
<option value="보트">보트</option>
<option value="사막">사막</option>
<option value="골프">골프</option>
<option value="동굴">동굴</option>
<option value="문화재">문화재</option>
<option value="동물원">동물원</option>
<option value="사이클링">사이클링</option>
</select>
<div className="flex items-center justify-end gap-3">
<input
type="file"
id="files"
className="hidden"
onChange={handleFileChange}
></input>
<label htmlFor="files" className="border-2 m-5">
이미지 선택
</label>
</div>
<div className="flex items-center justify-end gap-3 mt-2 md:mt-0">
<p>title :</p>
<input
name="title"
className="border-2 border-sky-500"
onChange={handleInputeChange}
/>
</div> </div>
</div>
<div className="my-5 flex items-center">
<button className="border-2 border-gray-500 rounded ">추가</button>
</div>
</div> </div>
); </form>
}; <div className="flex justify-center">
<MySlide key={Math.random()} slides={slides} />
</div>
</div>
);
}
...@@ -3,4 +3,4 @@ export { default as Signup } from "./signup"; ...@@ -3,4 +3,4 @@ export { default as Signup } from "./signup";
export { default as Profile } from "./profile"; export { default as Profile } from "./profile";
export { RequireAuth } from "./RequireAuth"; export { RequireAuth } from "./RequireAuth";
export { default as Admin } from "./admin"; export { default as Admin } from "./admin";
export {default as ImgRewrite} from "./imgrewrite" export { default as ImgRewrite } from "./imgrewrite";
...@@ -36,7 +36,7 @@ export default function Login() { ...@@ -36,7 +36,7 @@ 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") { if (user.email == "admin@korea.ac.kr" && user.password == "111111") {
navigate("/admin", { replace: true }) navigate("/admin", { replace: true });
} else { } else {
navigate("/", { replace: true }); navigate("/", { replace: true });
} }
...@@ -54,9 +54,9 @@ export default function Login() { ...@@ -54,9 +54,9 @@ export default function Login() {
return ( return (
<div className="flex flex-col items-center my-10"> <div className="flex flex-col items-center my-10">
<div className="bg-white w-1/2 md:w-1/3 my-8 text-center text-2xl"> <div className="bg-white w-1/2 md:w-1/3 my-8 text-center text-2xl">
<Link to="/">Travel Report</Link> <Link to="/">로그인</Link>
</div> </div>
<div className="flex flex-col w-full md:w-2/5 p-8 md:p-4"> <div className="flex flex-col w-full md:w-3/5 p-8 md:p-4">
<form <form
onSubmit={handleSubmit} onSubmit={handleSubmit}
className="flex flex-col md:flex-row md:justify-around border-2 border-black rounded-xl p-8 gap-y-4" className="flex flex-col md:flex-row md:justify-around border-2 border-black rounded-xl p-8 gap-y-4"
......
...@@ -47,32 +47,39 @@ export default function Profile() { ...@@ -47,32 +47,39 @@ export default function Profile() {
const userChange = async () => { const userChange = async () => {
const profile = await handleProfile(); const profile = await handleProfile();
setEmail(profile.email); setEmail(profile.email);
setPicturename(profile.avatar.newfilename); setPicturename(profile.fileInfo.newfilename);
setPlaceholder(profile.avatar.nickname); setPlaceholder(profile.fileInfo.nickname);
}; };
const handleClick = async ( const handleClick = async (
e: React.MouseEvent<HTMLButtonElement, globalThis.MouseEvent> e: React.MouseEvent<HTMLButtonElement, globalThis.MouseEvent>
) => { ) => {
e.preventDefault();
const formdata = new FormData(); const formdata = new FormData();
if (!(file === undefined || nickname === "")) { if (!(file === undefined || nickname === "")) {
formdata.append("picture", file); formdata.append("picture", file);
formdata.append("nickname", nickname); formdata.append("nickname", nickname);
console.log("both"); console.log("both");
await profileApi.picture(formdata); console.log(formdata);
} else if (!(nickname === "")) { await profileApi.profileUpload(formdata);
} else if (!(file === undefined) && nickname === "") {
formdata.append("picture", file);
await profileApi.profileUpload(formdata);
} else if (file === undefined && !(nickname === "")) {
formdata.append("nickname", nickname); formdata.append("nickname", nickname);
console.log("picture"); await profileApi.profileUpload(formdata);
await profileApi.picture(formdata);
} else { } else {
alert("수정할 정보를 입력해주세요."); alert("수정할 정보를 입력해주세요.");
} }
}; };
const deleteClick = async () => { const deleteClick = async () => {
await profileApi.deleteUser().then(() => { if (confirm("삭제하시겠습니까?") == true) {
logout(); const success = await profileApi.deleteUser();
console.log("test"); if (success) {
}); await logout();
}
} else {
}
}; };
useEffect(() => { useEffect(() => {
...@@ -80,22 +87,24 @@ export default function Profile() { ...@@ -80,22 +87,24 @@ export default function Profile() {
}, []); }, []);
return ( return (
<div className="grid md:px-60"> <div className="grid ">
<form className="justify-items-center"> <form className="justify-items-center">
<div className="ml-20 mt-10">프로필 수정</div> <div className=" mt-10">프로필 수정</div>
<div className="grid mt-20 border-0 border-y-2 "> <div className="grid mt-10 border-0 border-y-2 border-gray-400 ">
<div className="flex"> <div className="flex h-20">
<div className="py-10 basis-1/5 border-0 border-r-2 bg-gray-100 grid place-items-center shrink-0"> <div className=" basis-1/5 border-0 border-r-2 bg-gray-100 grid place-items-center shrink-0">
Email Email
</div> </div>
<div className="basis-full my-5 p-5">{email}</div> <div className=" basis-full grid place-items-center justify-items-stretch px-4">
{email}
</div>
</div> </div>
<div className="flex border-0 border-t-2"> <div className="flex border-0 border-t-2">
<div className="py-10 basis-1/5 border-0 border-r-2 bg-gray-100 grid place-items-center shrink-0"> <div className="basis-1/5 border-0 border-r-2 bg-gray-100 grid place-items-center shrink-0">
사진 사진
</div> </div>
<div className="basis-full p-2 "> <div className="basis-full py-4 ">
<div className="overflow-hidden w-40 h-40 rounded-full border-2 m-5"> <div className="overflow-hidden w-28 h-28 rounded-full border-2 m-5">
{imageSrc ? ( {imageSrc ? (
<img <img
src={imageSrc} src={imageSrc}
...@@ -119,17 +128,16 @@ export default function Profile() { ...@@ -119,17 +128,16 @@ export default function Profile() {
</label> </label>
</div> </div>
</div> </div>
<div className="flex border-0 border-t-2"> <div className="flex border-0 border-t-2 h-20">
<div className="py-10 basis-1/5 border-0 border-r-2 bg-gray-100 grid place-items-center shrink-0"> <div className="basis-1/5 border-0 border-r-2 bg-gray-100 grid place-items-center shrink-0">
별명 별명
</div> </div>
<div className="basis-full ">
<input <input
placeholder={placeholder} placeholder={placeholder}
className="basis-full placeholder:text-black my-10 ml-5 border-2" className="basis-1/5 placeholder:text-black my-6 ml-5 border-2 "
onChange={onNickChange} onChange={onNickChange}
/> />
</div>
</div> </div>
</div> </div>
<div className="grid grid-cols-2 my-4 md:mb-20 justify-items-center"> <div className="grid grid-cols-2 my-4 md:mb-20 justify-items-center">
......
...@@ -69,61 +69,61 @@ export default function Signup() { ...@@ -69,61 +69,61 @@ export default function Signup() {
return ( return (
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<div className="p-12 md:w-40 mt-8 bg-red-400 rounded-2xl"> <div className=" md:w-40 mt-8 text-center text-2xl rounded-2xl">
<Link to="/">Travel Report</Link> <Link to="/">회원가입</Link>
</div> </div>
<form
onSubmit={handleSubmit}
className="flex flex-col items-center mt-16 gap-y-4"
>
<input
className="placeholder:text-slate-300 bg-white border border-slate-500 rounded-2xl py-2 pl-9 pr-3 focus:border-black"
placeholder="이름"
type="text"
name="name"
onChange={handleChange}
/>
<input <form onSubmit={handleSubmit} className="flex flex-col mt-16 gap-y-4">
className="placeholder:text-slate-300 bg-white border border-slate-500 rounded-2xl py-2 pl-9 pr-3 focus:border-black" <div className="flex flex-col">
placeholder="이메일" <div className="flex">
type="email" <div className="basis-1/5 shrink-0">이름</div>
name="email" <input
onChange={handleChange} className="border-2 focus:border-black"
/> type="text"
name="name"
<input onChange={handleChange}
className="placeholder:text-slate-300 />
bg-white border border-slate-500 rounded-2xl </div>
py-2 pl-9 pr-3 <div className="flex">
focus:border-black" <div className="basis-1/5 shrink-0">이메일</div>
placeholder="비밀번호" <input
type="password" className="border-2 focus:border-black"
name="password" type="email"
onChange={handleChange} name="email"
/> onChange={handleChange}
/>
<input
className="placeholder:text-slate-300
bg-white border border-slate-500 rounded-2xl
py-2 pl-9 pr-3
focus:border-black"
placeholder="비밀번호 확인"
type="password"
name="password2"
onChange={handleChange}
/>
{error && (
<div className="text-red-500 text-sm">
<p>{error}</p>
</div> </div>
)} <div className="flex">
<button disabled={disabled} className="border-b border-white"> <div className="basis-1/5 shrink-0">비밀번호</div>
{loading && ( <input
<SpinnerIcon className="animate-spin h-5 w-5 mr-1 text-slate" /> className="border-2 focus:border-black"
type="password"
name="password"
onChange={handleChange}
/>
</div>
<div className="flex">
<div className="basis-1/5 shrink-0">비밀번호 확인</div>
<input
className="border-2 focus:border-black"
type="password"
name="password2"
onChange={handleChange}
/>
</div>
{error && (
<div className="text-red-500 text-sm">
<p>{error}</p>
</div>
)} )}
회원가입
</button> <button disabled={disabled} className="border-b border-white">
{loading && (
<SpinnerIcon className="animate-spin h-5 w-5 mr-1 text-slate" />
)}
회원가입
</button>
</div>
</form> </form>
</div> </div>
); );
......
...@@ -6,61 +6,72 @@ import "tailwindcss/tailwind.css"; ...@@ -6,61 +6,72 @@ import "tailwindcss/tailwind.css";
export default function Header() { export default function Header() {
const { logout } = useAuth(); const { logout } = useAuth();
return ( const [search, setSearch] = useState("");
<div className="flex flex-col ">
<div className="flex py-10 ">
<button className="shrink-0 mx-5">
<Link to="/" className="hover:text-sky-300 focus:text-purple-500">
Travel Report
</Link>
</button>
<input const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
className="md:ml-20 placeholder:text-white focus:outline-none focus:border-y-4 focus:border-l-4 focus:border-sky-500 md:placeholder:text-slate-400 w-20 md:w-1/2 border-y-4 border-l-4 border-sky-300 pl-9 rounded-l-full focus:border-0" const newvalue = e.target.value;
placeholder="어디로 여행가고 싶나요?" setSearch(newvalue);
/> };
<button className="shrink-0 border-y-4 border-r-4 border-sky-500 rounded-r-full pr-4">
검색
</button>
<div className="shrink-0 p-3 md:ml-40 h-12"> return (
{useAuth().user.isLoggedIn ? ( <div className="flex flex-col md:px-56 ">
<div className="flex"> <div className="flex flex-col-reverse pt-3 pb-12 border-b-2 ">
<Link to="/profile" className="mr-2 "> <div className="flex mt-5 justify-between pr-3">
프로필 <button className="ml-3 shrink-0 text-2xl">
</Link> <Link to="/" className="hover:text-sky-300 active:text-purple-500">
<div className="border-0 border-r-2"></div> Travel Report
<div></div> </Link>
<button </button>
className="ml-2 mr-2" <div className="flex ">
onClick={() => { <input
logout(); 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"
}} onChange={handleChange}
> />
로그아웃 <button className="shrink-0 bg-white border-y-4 border-r-4 border-sky-500 rounded-r-full pr-4">
</button> 검색
<div className="border-0 border-r-2"></div>
<div></div>
</div>
) : (
<button className="shrink-0 bg-white ">
<Link
className="hover:text-sky-300 focus:text-purple-500"
to="/login"
>
로그인
</Link>
</button> </button>
)} </div>
</div>
<div className="flex justify-end">
<div className=" p-3 bg-transparent ">
{useAuth().user.isLoggedIn ? (
<div className="flex text-xs">
<Link to="/profile" className="mr-2 ">
프로필
</Link>
<div className="border-0 border-r-2 border-black "></div>
<div></div>
<button
className="ml-2 mr-2 text-xs"
onClick={() => {
logout();
}}
>
로그아웃
</button>
<div className="border-0 border-r-2 border-black"></div>
<div></div>
</div>
) : (
<button className="shrink-0 bg-transparent pb-1">
<Link
className="hover:text-sky-300 focus:text-purple-500 text-xs"
to="/login"
>
로그인
</Link>
</button>
)}
</div>
<button className="shrink-0 bg-transparent pr-3 text-xs">
<Link
to="/board"
className="hover:text-sky-300 focus:text-purple-500"
>
게시판
</Link>
</button>
</div> </div>
<button className="shrink-0 bg-white">
<Link
to="/board"
className="hover:text-sky-300 focus:text-purple-500"
>
게시판
</Link>
</button>
</div> </div>
<Outlet /> <Outlet />
......
...@@ -6,38 +6,82 @@ type ThemeProps = { ...@@ -6,38 +6,82 @@ type ThemeProps = {
export default function Theme({ handleClick }: ThemeProps) { export default function Theme({ handleClick }: ThemeProps) {
return ( return (
<div className="overflow-x-auto flex rounded md:justify-center"> <div className="overflow-x-auto flex rounded md:justify-center py-2 border-b-2 divide-x-2">
<button id={"서핑"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"surfing"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
서핑 서핑
</button> </button>
<button id={"액티비티"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"activity"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
액티비티 액티비티
</button> </button>
<button id={"캠핑"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300 "> <button
id={"camping"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300 "
>
캠핑 캠핑
</button> </button>
<button id={"스키"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"sking"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
스키 스키
</button> </button>
<button id={"보트"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"boat"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
보트 보트
</button> </button>
<button id={"사막"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"desert"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
사막 사막
</button> </button>
<button id={"골프"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"golf"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
골프 골프
</button> </button>
<button id={"동굴"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"cave"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
동굴 동굴
</button> </button>
<button id={"문화재"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"history"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
문화재 문화재
</button> </button>
<button id={"동물원"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"zoo"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
동물원 동물원
</button> </button>
<button id={"사이클링"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300"> <button
id={"cycling"}
onClick={handleClick}
className="shrink-0 px-5 hover:text-sky-300"
>
사이클링 사이클링
</button> </button>
</div> </div>
......
...@@ -7,74 +7,74 @@ type CityProps = { ...@@ -7,74 +7,74 @@ type CityProps = {
export default function Citylist({ handleClick }: CityProps) { export default function Citylist({ handleClick }: CityProps) {
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-center px-5 py-2 bg-sky-300 shrink-0">도시</div> <div className="text-start px-5 py-2 bg-white shrink-0">도시</div>
<button <button
id={"서울"} id={"서울"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
서울 서울
</button> </button>
<button <button
id={"부산"} id={"부산"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
부산 부산
</button> </button>
<button <button
id={"인천"} id={"인천"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
인천 인천
</button> </button>
<button <button
id={"대구"} id={"대구"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
대구 대구
</button> </button>
<button <button
id={"광주"} id={"광주"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
광주 광주
</button> </button>
<button <button
id={"대전"} id={"대전"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
대전 대전
</button> </button>
<button <button
id={"울산"} id={"울산"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
울산 울산
</button> </button>
<button <button
id={"세종"} id={"세종"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
세종 세종
</button> </button>
<button <button
id={"독도"} id={"독도"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
독도 독도
</button> </button>
<button <button
id={"제주"} id={"제주"}
onClick={handleClick} onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0" className="text-start px-5 py-2 hover:underline shrink-0"
> >
제주 제주
</button> </button>
......
...@@ -31,7 +31,7 @@ export interface SignupUser { ...@@ -31,7 +31,7 @@ export interface SignupUser {
export interface Profile { export interface Profile {
_id: string; _id: string;
email: string; email: string;
avatar: { fileInfo: {
originalfilename: string; originalfilename: string;
newfilename: string; newfilename: string;
picturepath: string; picturepath: string;
...@@ -44,7 +44,7 @@ export interface MainimgType { ...@@ -44,7 +44,7 @@ export interface MainimgType {
theme: string; theme: string;
city: string; city: string;
title: string; title: string;
pic : { pic: {
originalfilename: string; originalfilename: string;
newfilename: string; newfilename: string;
}; };
......
...@@ -3,21 +3,13 @@ import isLength from "validator/lib/isLength"; ...@@ -3,21 +3,13 @@ import isLength from "validator/lib/isLength";
import { TypedRequestAuth } from "./auth.controller"; 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 { ObjectId } from "mongoose"; import { ObjectId } from "mongoose";
import formidable from "formidable"; import formidable from "formidable";
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 }>;
const { userId } = req.auth const { userId } = req.auth;
// const { theme, city, url, title } = req.body as {
// theme: string;
// city: string;
// url: string;
// title: string;
// };
// console.log("body", req.body);
const form = formidable({ const form = formidable({
uploadDir: "uploads", uploadDir: "uploads",
...@@ -55,7 +47,6 @@ export const createMainimg = asyncWrap(async (reqExp, res) => { ...@@ -55,7 +47,6 @@ export const createMainimg = asyncWrap(async (reqExp, res) => {
res.json(); res.json();
}); });
// if (!isLength(url ?? "", { min: 1 })) { // if (!isLength(url ?? "", { min: 1 })) {
// return res.status(422).send("이미지 url을 입력해주세요"); // return res.status(422).send("이미지 url을 입력해주세요");
// } // }
...@@ -79,7 +70,6 @@ export const getMainimg = asyncWrap(async (req, res) => { ...@@ -79,7 +70,6 @@ export const getMainimg = asyncWrap(async (req, res) => {
return res.json(mainimgs); return res.json(mainimgs);
}); });
export const deleteMainimg = asyncWrap(async (req, res) => { export const deleteMainimg = asyncWrap(async (req, res) => {
const { imgId } = req.params; const { imgId } = req.params;
console.log(imgId); console.log(imgId);
...@@ -90,7 +80,6 @@ export const deleteMainimg = asyncWrap(async (req, res) => { ...@@ -90,7 +80,6 @@ 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 TypedRequestAuth<{ userId: ObjectId }>;
const form = formidable({ const form = formidable({
uploadDir: "uploads", uploadDir: "uploads",
...@@ -102,7 +91,8 @@ export const updateMainimg = asyncWrap(async (reqExp, res) => { ...@@ -102,7 +91,8 @@ export const updateMainimg = asyncWrap(async (reqExp, res) => {
if (!Array.isArray(files.updatemainimg)) { if (!Array.isArray(files.updatemainimg)) {
//파일 좁히기 중 //파일 좁히기 중
if ( if (
!(Array.isArray(fields.id) || !(
Array.isArray(fields.id) ||
Array.isArray(fields.city) || Array.isArray(fields.city) ||
Array.isArray(fields.title) || Array.isArray(fields.title) ||
Array.isArray(fields.theme) Array.isArray(fields.theme)
...@@ -112,28 +102,25 @@ export const updateMainimg = asyncWrap(async (reqExp, res) => { ...@@ -112,28 +102,25 @@ export const updateMainimg = asyncWrap(async (reqExp, res) => {
const city = fields.city; const city = fields.city;
const title = fields.title; const title = fields.title;
const theme = fields.theme; const theme = fields.theme;
console.log("error") console.log("error");
if (!(files.updatemainimg ===undefined)){ if (!(files.updatemainimg === undefined)) {
const originalfilename = files.updatemainimg?.originalFilename; const originalfilename = files.updatemainimg?.originalFilename;
const newfilename = files.updatemainimg.newFilename; const newfilename = files.updatemainimg.newFilename;
if (!(originalfilename === null || newfilename === undefined)) { if (!(originalfilename === null || newfilename === undefined)) {
mainimgDb.updateOneMainimg( mainimgDb.updateOneMainimg(
id, id,
theme, theme,
city, city,
title, title,
originalfilename, originalfilename,
newfilename newfilename
); );
} }
} else {
mainimgDb.updateOneMainimg(id, theme, city, title);
} }
else {
mainimgDb.updateOneMainimg(id, theme, city, title)}
} }
} }
}); });
res.json(); res.json();
}); });
...@@ -4,6 +4,7 @@ import { Request } from "express"; ...@@ -4,6 +4,7 @@ import { Request } from "express";
import formidable from "formidable"; import formidable from "formidable";
import { ObjectId } from "mongoose"; import { ObjectId } from "mongoose";
import fs from "fs"; import fs from "fs";
import { TypedRequest } from "../types";
export interface TypedRequestAuth<T> extends Request { export interface TypedRequestAuth<T> extends Request {
auth: T; auth: T;
...@@ -30,45 +31,43 @@ export const getProfile = asyncWrap(async (reqExp, res) => { ...@@ -30,45 +31,43 @@ export const getProfile = asyncWrap(async (reqExp, res) => {
}); });
export const postPicture = asyncWrap(async (reqExp, res) => { export const postPicture = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequestAuth<{ userId: ObjectId }>; const req = reqExp as TypedRequest;
const { userId } = req.auth; const { userId } = req.auth;
const field = req.body;
const file = req.files;
const form = formidable({ if (!Array.isArray(file.picture)) {
uploadDir: "uploads", //파일 좁히기 중
keepExtensions: true, if (!Array.isArray(field.nickname)) {
multiples: false, const nickname = field.nickname;
}); if (!(file.picture === undefined)) {
const originalfilename = file.picture.originalFilename;
form.parse(req, (err, fields, files) => { const newfilename = file.picture.newFilename;
if (!Array.isArray(files.picture)) { const picturepath = file.picture.filepath;
//파일 좁히기 중 userDb.postPicture(
if (!Array.isArray(fields.nickname)) { userId,
const nickname = fields.nickname; nickname,
if (!(files.picture === undefined)) { originalfilename,
const originalfilename = files.picture.originalFilename; newfilename,
const newfilename = files.picture.newFilename; picturepath
const picturepath = files.picture.filepath; );
userDb.postPicture( } else {
userId, userDb.postPicture(userId, nickname);
nickname,
originalfilename,
newfilename,
picturepath
);
} else {
userDb.postPicture(userId, nickname);
}
} }
} }
}); }
res.json(); res.json();
}); });
export const deleteUser = asyncWrap(async (reqExp, res) => { export const deleteUser = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequestAuth<{ userId: ObjectId }>; // 앞에서는 토큰으로써 사용하기 때문에 JwtPayload 를 사용하고 여기서는 verify 에서 토큰을 디코딩했기에 ObjectId 타입의 string으로 바뀌게 된다. const req = reqExp as TypedRequestAuth<{ userId: string }>; // 앞에서는 토큰으로써 사용하기 때문에 JwtPayload 를 사용하고 여기서는 verify 에서 토큰을 디코딩했기에 ObjectId 타입의 string으로 바뀌게 된다.
const { userId } = req.auth; const { userId } = req.auth;
const profile = await userDb.deleteUser(userId); const finish = await userDb.deleteUser(userId);
res.json(profile); if (finish?.deletedCount === 1) {
res.json(true);
} else {
res.status(422).send("삭제에 실패하였습니다.");
}
}); });
import { Avatar, IAvatar, Mainimg, MainimgType } from "../models";
import { ObjectId } from "mongoose"; import { ObjectId } from "mongoose";
import { FileInfo, IFileInfo, Mainimg, MainimgType } from "../models";
export const createMainimg = async (mainimg: MainimgType, pic: IAvatar) => { export const createMainimg = async (mainimg: MainimgType, pic: IFileInfo) => {
const newPic = await Avatar.create({ const newPic = await FileInfo.create({
originalfilename: pic.originalfilename, originalfilename: pic.originalfilename,
newfilename: pic.newfilename, newfilename: pic.newfilename,
pictureauth: pic.picturepath, pictureauth: pic.picturepath,
...@@ -34,36 +34,40 @@ export const updateOneMainimg = async ( ...@@ -34,36 +34,40 @@ export const updateOneMainimg = async (
city: string, city: string,
title: string, title: string,
originalfilename?: string | null, originalfilename?: string | null,
newfilename?: string, newfilename?: string
) => { ) => {
const newMainimg = await Mainimg.findById(_Id); const newMainimg = await Mainimg.findById(_Id);
console.log("error2",_Id) console.log("error2", _Id);
if (!(newMainimg?.pic === undefined)) { if (!(newMainimg?.pic === undefined)) {
if (originalfilename === undefined) { if (originalfilename === undefined) {
await Mainimg.findByIdAndUpdate(newMainimg._id, { await Mainimg.findByIdAndUpdate(newMainimg._id, {
theme: theme, theme: theme,
city: city, city: city,
title: title, title: title,
}) });
console.log("errrror4") console.log("errrror4");
} } else if (
else if(!(originalfilename === undefined)&&(!(theme === undefined)||!(city === undefined)||!(title === undefined))){ !(originalfilename === undefined) &&
(!(theme === undefined) ||
!(city === undefined) ||
!(title === undefined))
) {
await Mainimg.findByIdAndUpdate(newMainimg._id, { await Mainimg.findByIdAndUpdate(newMainimg._id, {
theme: theme, theme: theme,
city: city, city: city,
title: title, title: title,
}) });
await Avatar.findByIdAndUpdate(newMainimg.pic._id, { await FileInfo.findByIdAndUpdate(newMainimg.pic._id, {
originalfilename: originalfilename, originalfilename: originalfilename,
newfilename: newfilename, newfilename: newfilename,
}) });
console.log("error6") console.log("error6");
} } else {
else { await FileInfo.findByIdAndUpdate(newMainimg.pic._id, {
await Avatar.findByIdAndUpdate(newMainimg.pic._id, {
originalfilename: originalfilename, originalfilename: originalfilename,
newfilename: newfilename, newfilename: newfilename,
}) });
console.log("error5",newfilename,originalfilename,theme,city,title)} console.log("error5", newfilename, originalfilename, theme, city, title);
}else(console.log("error3",newMainimg)) }
} } else console.log("error3", newMainimg);
\ No newline at end of file };
...@@ -6,7 +6,7 @@ import fs from "fs/promises"; ...@@ -6,7 +6,7 @@ import fs from "fs/promises";
export const createUser = async (user: IUser) => { export const createUser = async (user: IUser) => {
// 비밀번호 암호화 // 비밀번호 암호화
const hash = await bcrypt.hash(user.password, 10); const hash = await bcrypt.hash(user.password, 10);
const newAvatar = await FileInfo.create({}); const newFileInfo = await FileInfo.create({});
// 사용자 역할 추가: 기본값은 "user" // 사용자 역할 추가: 기본값은 "user"
let userRole = null; let userRole = null;
if (user.role) { if (user.role) {
...@@ -19,7 +19,7 @@ export const createUser = async (user: IUser) => { ...@@ -19,7 +19,7 @@ export const createUser = async (user: IUser) => {
password: hash, password: hash,
role: userRole, role: userRole,
isNew: true, isNew: true,
avatar: newAvatar, fileInfo: newFileInfo._id,
}); });
const retUser = await newUser.save(); const retUser = await newUser.save();
return retUser; return retUser;
...@@ -44,7 +44,7 @@ export const findUserByPostId = async (postId: string) => { ...@@ -44,7 +44,7 @@ export const findUserByPostId = async (postId: string) => {
}; };
export const getProfile = async (userId: string) => { export const getProfile = async (userId: string) => {
const profile = await User.findById(userId).populate("avatar"); const profile = await User.findById(userId).populate("fileInfo");
return profile; //이름 수정 return profile; //이름 수정
}; };
...@@ -80,19 +80,22 @@ export const postPicture = async ( ...@@ -80,19 +80,22 @@ export const postPicture = async (
) => { ) => {
const profile = await User.findById(userId); const profile = await User.findById(userId);
if (!(profile?.avatar === undefined)) { if (!(profile?.fileInfo === undefined)) {
if (originalfilename === null) { if (originalfilename === null) {
await FileInfo.findByIdAndUpdate(profile.avatar._id, { await FileInfo.findByIdAndUpdate(profile.fileInfo._id, {
nickname: nickname, nickname: nickname,
}); });
} else if (nickname === "") { } else if (nickname === "") {
await FileInfo.findByIdAndUpdate(profile.avatar._id, { const ref = FileInfo.findById(profile.fileInfo._id);
console.log(ref);
await FileInfo.findByIdAndUpdate(profile.fileInfo._id, {
originalfilename: originalfilename, originalfilename: originalfilename,
newfilename: newfilename, newfilename: newfilename,
picturepath: picturepath, picturepath: picturepath,
}); });
} else { } else {
await FileInfo.findByIdAndUpdate(profile.avatar._id, { const ref = await FileInfo.findByIdAndUpdate(profile.fileInfo._id, {
originalfilename: originalfilename, originalfilename: originalfilename,
newfilename: newfilename, newfilename: newfilename,
picturepath: picturepath, picturepath: picturepath,
...@@ -102,12 +105,15 @@ export const postPicture = async ( ...@@ -102,12 +105,15 @@ export const postPicture = async (
} }
}; };
export const deleteUser = async (userId: ObjectId) => { export const deleteUser = async (userId: string) => {
const user = await User.findById(userId); const user = await User.findById(userId);
if (user && user.avatar) { if (!(user?.fileInfo === undefined)) {
const file = await FileInfo.findById(user.avatar._id); const ref = await FileInfo.findById(user.fileInfo._id);
await fs.unlink("../travel/uploads/" + file?.newfilename); if (!(ref?.newfilename === undefined)) {
await FileInfo.deleteOne({ _id: user.avatar._id }); await fs.unlink("../travel/uploads/" + ref?.newfilename);
return await user.deleteOne(); }
await FileInfo.deleteOne({ _id: user.fileInfo._id });
const finish = await User.deleteOne({ _id: userId });
return finish;
} }
}; };
...@@ -8,7 +8,7 @@ export interface IFileInfo { ...@@ -8,7 +8,7 @@ export interface IFileInfo {
} }
const schema = new Schema<IFileInfo>({ const schema = new Schema<IFileInfo>({
originalfilename: { type: String }, originalfilename: { type: String, unique: true },
newfilename: { type: String }, newfilename: { type: String },
nickname: { type: String }, nickname: { type: String },
picturepath: { type: String }, picturepath: { type: String },
......
import {model, Schema, Types } from "mongoose"; import { model, Schema, Types } from "mongoose";
export interface MainimgType { export interface MainimgType {
theme: string;
theme: string; city: string;
city: string; title: string;
title: string; fileInfo?: Types.ObjectId;
pic?: Types.ObjectId;
} }
const MainimgSchema = new Schema<MainimgType>({ const MainimgSchema = new Schema<MainimgType>({
theme: { theme: {
type: String, type: String,
}, },
city: { city: {
type: String, type: String,
}, },
title: { title: {
type: String, type: String,
required: true, required: true,
}, },
pic: { fileInfo: { type: Schema.Types.ObjectId, ref: "Fileinfo" },
type : Schema.Types.ObjectId,
ref: "Avatar"
}
}); });
export default model<MainimgType>("Mainimg", MainimgSchema); export default model<MainimgType>("Mainimg", MainimgSchema);
...@@ -5,7 +5,7 @@ export interface IUser { ...@@ -5,7 +5,7 @@ export interface IUser {
name?: string; name?: string;
password: string; password: string;
role?: Types.ObjectId; role?: Types.ObjectId;
avatar?: Types.ObjectId; fileInfo?: Types.ObjectId;
} }
const validateEmail = (email: string) => { const validateEmail = (email: string) => {
...@@ -22,7 +22,7 @@ const schema = new Schema<IUser>( ...@@ -22,7 +22,7 @@ const schema = new Schema<IUser>(
validate: [validateEmail, "이메일을 입력해주세요"], validate: [validateEmail, "이메일을 입력해주세요"],
}, },
name: { type: String }, name: { type: String },
avatar: { type: Schema.Types.ObjectId, ref: "Avatar" }, fileInfo: { type: Schema.Types.ObjectId, ref: "FileInfo" },
password: { type: String, required: true, select: false }, password: { type: String, required: true, select: false },
role: { type: Schema.Types.ObjectId, ref: "Role" }, role: { type: Schema.Types.ObjectId, ref: "Role" },
}, },
......
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