Commit 4fec5250 authored by 백승민's avatar 백승민
Browse files

rewrite done

parent c1d3b019
......@@ -2,4 +2,5 @@ node_modules/
.vscode/
package-lock.json
dist/
uploads/
\ No newline at end of file
uploads/
adminpics
\ No newline at end of file
......@@ -41,7 +41,6 @@ export function MySlide({ slides}: num) {
<div className="flex flex-row justify-center items-center ">
<button className="mx-3 w-6 h-6 rounded-full hover:bg-sky-100 hover:text-gray-400"onClick={leftClick} disabled={slide === 1}>
&lt;
{/* {slide.current} */}
</button>
<div
className={`m-3 md:m-5 md:basis-4/5 flex flex-row relative w-full overflow-hidden`}
......@@ -49,7 +48,7 @@ export function MySlide({ slides}: num) {
{slides.slice(page - 1, page + 2).map((slide) => (
<div key={Math.random()} className="min-w-full"
>
<div key={slide} className={`inline-grid grid-cols-5 ${style}`}>
<div key={slide} className={`inline-grid grid-cols-2 ${style}`}>
{slide}
</div>
</div>
......
let url = [
{
themeid:"surfing",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "1.종로 서핑"
},
{
themeid: "surfing",
cityid: "Busan",
url: "https://cdn.crowdpic.net/detail-thumb/thumb_d_1F5AF0BCBB2F43EF3C5B79DA763D3CFB.jpg",
name: "1.해운대 서핑"
},
{
themeid: "surfing",
cityid: "Daegoo",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "1.대구 서핑"
},
{
themeid: "activity",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2019/05/17/13/36/umbrella-4209724__340.jpg",
name: "1.서대문 번지점프"
},
{
themeid: "sking",
cityid: "Kwangjoo",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "1.광주 스키"
},
{
themeid: "camping",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2021/11/16/11/13/man-6800728__340.jpg",
name: "1.강남 캠핑"
},
{
themeid: "boat",
cityid: "Sejong",
url: "https://cdn.pixabay.com/photo/2018/02/19/22/21/water-3166432__340.jpg",
name: "1.조치원 보트"
},
{
themeid: "activity",
cityid: "Sejong",
url: "https://media.istockphoto.com/photos/vertical-woman-is-wraped-in-bungee-jumping-picture-id1391927451?b=1&k=20&m=1391927451&s=170667a&w=0&h=haNtVpNjhj58PsjRi8N_RbyYfxZsFfKdb3NJi7NPdDI=",
name: "1.번지점프"
},
{
themeid: "activity",
cityid: "Busan",
url:"https://cdn.pixabay.com/photo/2015/04/07/07/51/railroad-tracks-710614__480.jpg",
name: "1.레일바이크"
},
{
themeid: "activity",
cityid: "Daegoo",
url: "https://cdn.pixabay.com/photo/2017/06/17/10/55/hot-air-balloon-2411851__340.jpg",
name: "1.열기구"
},
{
themeid: "activity",
cityid: "Jeju",
url: "https://cdn.pixabay.com/photo/2012/10/10/05/07/combat-diver-60545__340.jpg",
name: "1.스카이다이빙"
},
{
themeid: "activity",
cityid: "Incheon",
url: "https://cdn.pixabay.com/photo/2015/03/11/15/19/divers-668777__480.jpg",
name: "1.인천 스쿠버다이빙"
},
{
themeid: "activity",
cityid: "Daejeon",
url: "https://media.istockphoto.com/photos/playing-water-skiing-or-wakeboard-picture-id1021580500?b=1&k=20&m=1021580500&s=170667a&w=0&h=dL-mrlLeoQGrNBhbyAS-rN0TcpFg9s41D3WVKUoZgNo=",
name: "1.수상스키"
},
{
themeid: "desert",
cityid: "Incheon",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "1.인천 사막"
},
{
themeid: "activity",
cityid: "Woolsan",
url: "https://cdn.pixabay.com/photo/2019/05/11/20/44/free-climbing-4196577__480.jpg",
name: "1.클라이밍"
},
{
themeid: "zoo",
cityid: "Daejeon",
url: "https://cdn.pixabay.com/photo/2020/06/10/18/45/africa-5283871__340.jpg",
name: "2.대전 동물원"
},
{
themeid: "activity",
cityid: "Dokdo",
url: "https://cdn.pixabay.com/photo/2020/04/19/08/03/adventure-5062314__340.jpg",
name: "2.산"
},
{
themeid: "cave",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2016/08/23/16/34/italy-1614931__340.jpg",
name: "2.서울 동굴"
},
{
themeid:"surfing",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "2.종로 서핑"
},
{
themeid: "surfing",
cityid: "Busan",
url: "https://cdn.crowdpic.net/detail-thumb/thumb_d_1F5AF0BCBB2F43EF3C5B79DA763D3CFB.jpg",
name: "2.해운대 서핑"
},
{
themeid: "surfing",
cityid: "Daegoo",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "2.대구 서핑"
},
{
themeid: "activity",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2019/05/17/13/36/umbrella-4209724__340.jpg",
name: "2.서대문 번지점프"
},
{
themeid: "sking",
cityid: "Kwangjoo",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "2.광주 스키"
},
{
themeid: "camping",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2021/11/16/11/13/man-6800728__340.jpg",
name: "2.강남 캠핑"
},
{
themeid: "boat",
cityid: "Sejong",
url: "https://cdn.pixabay.com/photo/2018/02/19/22/21/water-3166432__340.jpg",
name: "2.조치원 보트"
},
{
themeid: "activity",
cityid: "Sejong",
url: "https://media.istockphoto.com/photos/vertical-woman-is-wraped-in-bungee-jumping-picture-id1391927451?b=1&k=20&m=1391927451&s=170667a&w=0&h=haNtVpNjhj58PsjRi8N_RbyYfxZsFfKdb3NJi7NPdDI=",
name: "2.번지점프"
},
{
themeid: "activity",
cityid: "Busan",
url:"https://cdn.pixabay.com/photo/2015/04/07/07/51/railroad-tracks-710614__480.jpg",
name: "2.레일바이크"
},
{
themeid: "activity",
cityid: "Daegoo",
url: "https://cdn.pixabay.com/photo/2017/06/17/10/55/hot-air-balloon-2411851__340.jpg",
name: "2.열기구"
},
{
themeid: "activity",
cityid: "Jeju",
url: "https://cdn.pixabay.com/photo/2012/10/10/05/07/combat-diver-60545__340.jpg",
name: "2.스카이다이빙"
},
{
themeid: "activity",
cityid: "Incheon",
url: "https://cdn.pixabay.com/photo/2015/03/11/15/19/divers-668777__480.jpg",
name: "2.인천 스쿠버다이빙"
},
{
themeid: "activity",
cityid: "Daejeon",
url: "https://media.istockphoto.com/photos/playing-water-skiing-or-wakeboard-picture-id1021580500?b=1&k=20&m=1021580500&s=170667a&w=0&h=dL-mrlLeoQGrNBhbyAS-rN0TcpFg9s41D3WVKUoZgNo=",
name: "3.수상스키"
},
{
themeid: "desert",
cityid: "Incheon",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "3.인천 사막"
},
{
themeid: "activity",
cityid: "Woolsan",
url: "https://cdn.pixabay.com/photo/2019/05/11/20/44/free-climbing-4196577__480.jpg",
name: "3.클라이밍"
},
{
themeid: "zoo",
cityid: "Daejeon",
url: "https://cdn.pixabay.com/photo/2020/06/10/18/45/africa-5283871__340.jpg",
name: "3.대전 동물원"
},
{
themeid: "activity",
cityid: "Dokdo",
url: "https://cdn.pixabay.com/photo/2020/04/19/08/03/adventure-5062314__340.jpg",
name: "3.산"
},
{
themeid: "cave",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2016/08/23/16/34/italy-1614931__340.jpg",
name: "3.서울 동굴"
},
{
themeid:"surfing",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "3.종로 서핑"
},
{
themeid: "surfing",
cityid: "Busan",
url: "https://cdn.crowdpic.net/detail-thumb/thumb_d_1F5AF0BCBB2F43EF3C5B79DA763D3CFB.jpg",
name: "3.해운대 서핑"
},
{
themeid: "surfing",
cityid: "Daegoo",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "3.대구 서핑"
},
{
themeid: "activity",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2019/05/17/13/36/umbrella-4209724__340.jpg",
name: "3.서대문 번지점프"
},
{
themeid: "sking",
cityid: "Kwangjoo",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "3.광주 스키"
},
{
themeid: "camping",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2021/11/16/11/13/man-6800728__340.jpg",
name: "3.강남 캠핑"
},
{
themeid: "boat",
cityid: "Sejong",
url: "https://cdn.pixabay.com/photo/2018/02/19/22/21/water-3166432__340.jpg",
name: "3.조치원 보트"
},
{
themeid: "activity",
cityid: "Sejong",
url: "https://media.istockphoto.com/photos/vertical-woman-is-wraped-in-bungee-jumping-picture-id1391927451?b=1&k=20&m=1391927451&s=170667a&w=0&h=haNtVpNjhj58PsjRi8N_RbyYfxZsFfKdb3NJi7NPdDI=",
name: "3.번지점프"
},
{
themeid: "activity",
cityid: "Busan",
url:"https://cdn.pixabay.com/photo/2015/04/07/07/51/railroad-tracks-710614__480.jpg",
name: "3.레일바이크"
},
{
themeid: "activity",
cityid: "Daegoo",
url: "https://cdn.pixabay.com/photo/2017/06/17/10/55/hot-air-balloon-2411851__340.jpg",
name: "4.열기구"
},
{
themeid: "activity",
cityid: "Jeju",
url: "https://cdn.pixabay.com/photo/2012/10/10/05/07/combat-diver-60545__340.jpg",
name: "4.스카이다이빙"
},
{
themeid: "activity",
cityid: "Incheon",
url: "https://cdn.pixabay.com/photo/2015/03/11/15/19/divers-668777__480.jpg",
name: "4.인천 스쿠버다이빙"
},
{
themeid: "activity",
cityid: "Daejeon",
url: "https://media.istockphoto.com/photos/playing-water-skiing-or-wakeboard-picture-id1021580500?b=1&k=20&m=1021580500&s=170667a&w=0&h=dL-mrlLeoQGrNBhbyAS-rN0TcpFg9s41D3WVKUoZgNo=",
name: "4.수상스키"
},
{
themeid: "desert",
cityid: "Incheon",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "4.인천 사막"
},
{
themeid: "activity",
cityid: "Woolsan",
url: "https://cdn.pixabay.com/photo/2019/05/11/20/44/free-climbing-4196577__480.jpg",
name: "4.클라이밍"
},
{
themeid: "zoo",
cityid: "Daejeon",
url: "https://cdn.pixabay.com/photo/2020/06/10/18/45/africa-5283871__340.jpg",
name: "4.대전 동물원"
},
{
themeid: "activity",
cityid: "Dokdo",
url: "https://cdn.pixabay.com/photo/2020/04/19/08/03/adventure-5062314__340.jpg",
name: "4.산"
},
{
themeid: "cave",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2016/08/23/16/34/italy-1614931__340.jpg",
name: "4.서울 동굴"
},
{
themeid:"surfing",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "4.종로 서핑"
},
{
themeid: "surfing",
cityid: "Busan",
url: "https://cdn.crowdpic.net/detail-thumb/thumb_d_1F5AF0BCBB2F43EF3C5B79DA763D3CFB.jpg",
name: "4.해운대 서핑"
},
{
themeid: "surfing",
cityid: "Daegoo",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "4.대구 서핑"
},
{
themeid: "activity",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2019/05/17/13/36/umbrella-4209724__340.jpg",
name: "4.서대문 번지점프"
},
{
themeid: "sking",
cityid: "Kwangjoo",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "4.광주 스키"
},
{
themeid: "camping",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2021/11/16/11/13/man-6800728__340.jpg",
name: "4.강남 캠핑"
},
{
themeid: "boat",
cityid: "Sejong",
url: "https://cdn.pixabay.com/photo/2018/02/19/22/21/water-3166432__340.jpg",
name: "5.조치원 보트"
},
{
themeid: "activity",
cityid: "Sejong",
url: "https://media.istockphoto.com/photos/vertical-woman-is-wraped-in-bungee-jumping-picture-id1391927451?b=1&k=20&m=1391927451&s=170667a&w=0&h=haNtVpNjhj58PsjRi8N_RbyYfxZsFfKdb3NJi7NPdDI=",
name: "5.번지점프"
},
{
themeid: "activity",
cityid: "Busan",
url:"https://cdn.pixabay.com/photo/2015/04/07/07/51/railroad-tracks-710614__480.jpg",
name: "5.레일바이크"
},
{
themeid: "activity",
cityid: "Daegoo",
url: "https://cdn.pixabay.com/photo/2017/06/17/10/55/hot-air-balloon-2411851__340.jpg",
name: "5.열기구"
},
{
themeid: "activity",
cityid: "Jeju",
url: "https://cdn.pixabay.com/photo/2012/10/10/05/07/combat-diver-60545__340.jpg",
name: "5.스카이다이빙"
},
{
themeid: "activity",
cityid: "Incheon",
url: "https://cdn.pixabay.com/photo/2015/03/11/15/19/divers-668777__480.jpg",
name: "5.인천 스쿠버다이빙"
},
{
themeid: "activity",
cityid: "Daejeon",
url: "https://media.istockphoto.com/photos/playing-water-skiing-or-wakeboard-picture-id1021580500?b=1&k=20&m=1021580500&s=170667a&w=0&h=dL-mrlLeoQGrNBhbyAS-rN0TcpFg9s41D3WVKUoZgNo=",
name: "5.수상스키"
},
{
themeid: "desert",
cityid: "Incheon",
url: "https://cdn.pixabay.com/photo/2022/06/15/23/08/germany-7264701__340.jpg",
name: "5.인천 사막"
},
{
themeid: "activity",
cityid: "Woolsan",
url: "https://cdn.pixabay.com/photo/2019/05/11/20/44/free-climbing-4196577__480.jpg",
name: "5.클라이밍"
},
{
themeid: "zoo",
cityid: "Daejeon",
url: "https://cdn.pixabay.com/photo/2020/06/10/18/45/africa-5283871__340.jpg",
name: "5.대전 동물원"
},
{
themeid: "activity",
cityid: "Dokdo",
url: "https://cdn.pixabay.com/photo/2020/04/19/08/03/adventure-5062314__340.jpg",
name: "5.산"
},
{
themeid: "cave",
cityid: "Seoul",
url: "https://cdn.pixabay.com/photo/2016/08/23/16/34/italy-1614931__340.jpg",
name: "5.서울 동굴"
},
];
export function getPicure(){
return url;
};
\ No newline at end of file
......@@ -2,8 +2,8 @@ import axios from "axios";
import { MainimgType } from "../types";
import baseUrl from "./baseUrl";
export const mainimg = async (mainimg: MainimgType) => {
const { data } = await axios.post(`${baseUrl}/mainimg`, mainimg);
export const mainimg = async (formdata: FormData) => {
const { data } = await axios.post(`${baseUrl}/mainimg`, formdata);
return data;
};
......@@ -17,7 +17,7 @@ export const getmainimg = async () => {
return data;
};
export const updating = async (img: MainimgType) => {
const { data } = await axios.put(`${baseUrl}/mainimg/${img._id}`, img);
export const updateimg = async (formdata: FormData,_id : string) => {
const { data } = await axios.put(`${baseUrl}/mainimg/${_id}`, formdata);
return data;
};
\ No newline at end of file
import React, { FormEvent, useEffect, useState, MouseEvent } from "react";
import { Link } from "react-router-dom";
import { mainimgApi } from "../apis";
import { catchErrors } from "../helpers";
import { MainimgType } from "../types";
import { picture } from "../apis/profile.api";
import { catchErrors } from "../helpers";
import { MySlide } from "./adminslide";
// export interface ImgState {
// state: MainimgType;
// }
export default function Admin() {
// 이미지 전체 불러오기
const [getimgs, setGetimgs] = useState<MainimgType[]>([]);
......@@ -17,54 +19,57 @@ export default function Admin() {
const imgs = await mainimgApi.getmainimg();
setGetimgs(imgs)
};
useEffect(() => {
imgsData();
}, []);
// 이미지 추가하기
const [addimg, setAddimg] = useState<MainimgType>({
_id: "",
theme: "",
city: "",
url: "",
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;
console.log(value)
setAddimg({ ...addimg, [name]: value });
}
function handleInputeChange(event: React.ChangeEvent<HTMLInputElement>) {
const { name, value } = event.currentTarget;
setAddimg({ ...addimg, [name]: value });
}
};
async function handleSubmit(event: FormEvent) {
event.preventDefault();
try {
setError("");
console.log("img data", addimg);
setLoading(true);
const res = await mainimgApi.mainimg(addimg);
console.log("서버연결됬나요", res);
setAddSuccess(true);
setError("");
} catch (error) {
console.log("에러발생");
catchErrors(error, setError);
} finally {
setLoading(false);
function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0];
if (!(file === undefined)) {
setFile(file);
}
}
if (addSuccess) {
alert("img 추가되었습니다");
}
async function handleSubmit(event: FormEvent) {
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 추가되었습니다");
};
};
// 이미지 삭제하기
async function handleDeleteClick(event: MouseEvent<HTMLButtonElement>) {
try {
......@@ -76,6 +81,7 @@ export default function Admin() {
// setGetimgs(getimgs)
setDelSuccess(true);
setError("");
alert("img 삭제되었습니다");
} else {
return false;
}
......@@ -87,10 +93,7 @@ export default function Admin() {
setLoading(false);
};
};
if (delSuccess) {
alert("img 삭제되었습니다");
}
let limit = 15;
const numPages = Math.ceil(getimgs.length / 15);
......@@ -100,22 +103,22 @@ export default function Admin() {
const slides = []
for (let i = 0; i < numPages; i++) {
const k = [
getimgs.slice(i * limit, i * limit + limit).map((pic, index: number) => (
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={pic.url}
src={"http://localhost:3000/images/" + picture.pic.newfilename}
className="w-full h-10 md:h-20 object-center"
/>
<p className="text-center text-xs">{pic.title}</p>
<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/${pic._id}`} state={pic}>
<Link to={`/admin/${picture._id}`} state={picture}>
수정
</Link>
</button>
<button id={pic._id} onClick={handleDeleteClick} className="text-xs">
<button id={picture._id} onClick={handleDeleteClick} className="text-xs">
삭제
</button>
</div>
......@@ -170,10 +173,16 @@ export default function Admin() {
<option value="사이클링">사이클링</option>
</select>
<div className="flex items-center justify-end gap-3">
<p>url :</p>
<input name="url" className="border-2 border-sky-500"
onChange={handleInputeChange} />
{/* type="file"/> */}
<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>
......
import React, { FormEvent, useState} from "react";
import React, { FormEvent, useState } from "react";
import { Link, Outlet, useNavigate, useLocation } from "react-router-dom";
import { mainimgApi } from "../apis";
import isLength from "validator/lib/isLength";
......@@ -26,38 +26,82 @@ export default function ImgRewrite() {
_id: img._id,
theme: img.theme,
city: img.city,
url: img.url,
title: img.title,
pic: { originalfilename: "", newfilename: "" },
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const [disabled, setDisabled] = useState(false);
const [success, setSuccess] = useState(false);
const [file, setFile] = useState<File>();
const [imageSrc, setImageSrc] = useState("");
const PictureSrc = (fileBlob: Blob) => {
const reader = new FileReader();
reader.readAsDataURL(fileBlob);
reader.onload = (data) => {
if (typeof data.target?.result === "string") {
console.log(data.target?.result);
setImageSrc(data.target?.result);
}
};
};
const onUploadFile = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!(file === undefined)) {
setFile(file);
PictureSrc(file);
}
};
async function reWriteSubmit(event: FormEvent) {
event.preventDefault();
try {
if (confirm("수정하시겠습니까?") == true) {
setError("");
console.log("user data", imgdata);
if (infoFormMatch(imgdata) === true) {
setLoading(true);
const res = await mainimgApi.updating(imgdata);
console.log("clear", res);
navigate("/admin", { replace: true });
setSuccess(true);
setError("");
}
} else {
return false;
if (confirm("수정하시겠습니까?") == true) {
// try {
setError("");
console.log("user data", imgdata);
// if (infoFormMatch(imgdata) === true) {
// setLoading(true);
// const res = await mainimgApi.updating(imgdata);
// console.log("clear", res);
// navigate("/admin", { replace: true });
// setSuccess(true);
// setError("");
const formdata = new FormData();
formdata.append("id", imgdata._id)
console.log(imgdata._id)
formdata.append("city", imgdata.city);
formdata.append("theme", imgdata.theme);
formdata.append("title", imgdata.title);
console.log(formdata)
if (!(file === undefined)) {
formdata.append("updatemainimg", file);
console.log("formdata", formdata);
const res = await mainimgApi.updateimg(formdata,imgdata._id);
navigate("/admin", { replace: true });
console.log("확인 중 ", res);
}
} catch (error) {
console.log("에러발생");
catchErrors(error, setError);
} finally {
setLoading(false);
else {
console.log("ㅇ에러")
formdata.append("updatemainimg","");
console.log("formdata",formdata);
const res = await mainimgApi.updateimg(formdata,imgdata._id);
navigate("/admin", { replace: true });
console.log("확인 중 ", res);
}
// }
// } catch (error) {
// console.log("에러발생");
// catchErrors(error, setError);
// } finally {
// setLoading(false);
// }
} else {
return false;
}
}
// console.log(user._id)
......@@ -65,8 +109,8 @@ export default function ImgRewrite() {
if (!isLength(pic.title ?? "", { min: 1 })) {
setError("제목을 입력해 주세요.");
return false;
} else if (!isLength(pic.url ?? "", { min: 1 })) {
setError("url을 입력해 주세요.");
} else if (!isLength(pic.pic.newfilename ?? "", { min: 1 })) {
setError("파일을 선택해 주세요.");
return false;
} else if (equals(pic.city, "city")) {
setError("도시를 선택해 주세요.");
......@@ -103,9 +147,9 @@ export default function ImgRewrite() {
setImgData(newUser);
};
const urlChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const fileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const url = event.currentTarget.value;
const newUser = { ...imgdata, url: url };
const newUser = { ...imgdata, pic: { originalfilename: "", newfilename: url } };
setUrl(event.currentTarget.value);
setImgData(newUser);
};
......@@ -172,10 +216,26 @@ export default function ImgRewrite() {
url
</td>
<td>
<input className="border-2 border-sky-500 rounded w-full"
onChange={urlChange}
defaultValue={img.url}
/>
<input
type="file"
id="files"
className="hidden"
onChange={onUploadFile}
></input>
<label htmlFor="files" className="border-2 m-5" >
이미지 선택
</label>
{imageSrc ? (
<img
src={imageSrc}
className="object-cover object-center h-full"
/>
) : (
<img
src={"http://localhost:3000/images/" + img.pic.newfilename}
className="object-cover object-center h-full"
/>
)}
</td>
</tr>
<tr>
......
......@@ -2,16 +2,24 @@ import React, { useEffect, MouseEvent, useState, useRef } from "react";
import { Outlet, useSearchParams } from "react-router-dom";
import Theme from "./theme";
import Citylist from "../Pages/citylist";
import { getPicure } from "../Pages/pic";
import { MySlide } from "../Pages/myslide";
import { mainimgApi } from "../apis";
import { MainimgType } from "../types";
const initSearchParams = { theme: "", city: "" };
export default function Body() {
let limit = 15;
const [searchParams, setSearchParams] = useSearchParams(initSearchParams);
let getPics = getPicure();
const [getimgs, setGetimgs] = useState<MainimgType[]>([]);
async function imgsData() {
const imgs = await mainimgApi.getmainimg();
setGetimgs(imgs)
};
useEffect(() => {
imgsData();
}, []);
useEffect(() => {
console.log(searchParams.get("theme"), searchParams.get("city"));
......@@ -39,31 +47,34 @@ export default function Body() {
let themechange = searchParams.get("theme");
let citylistchange = searchParams.get("city");
const Idpics = getPics.filter((p) => {
const Idpics = getimgs.filter((p) => {
return (
(p.themeid == themechange && p.cityid == citylistchange) ||
(p.themeid == themechange && citylistchange == "") ||
(themechange == "" && p.cityid == citylistchange) ||
(p.theme == themechange && p.city == citylistchange) ||
(p.theme == themechange && citylistchange == "") ||
(themechange == "" && p.city == citylistchange) ||
(themechange == "" && citylistchange == "")
);
});
const numPages = Math.ceil(Idpics.length / 15);
let limit = 4;
const numPages = Math.ceil(Idpics.length / limit);
const slides = []
for (let i = 0; i < numPages; i++) {
const k = [
Idpics.slice(i * limit, i * limit + limit).map((pic, index: number) => (
<div
className={`m-1 shrink-0 bg-gray-200 rounded shadow-md `}
key={index}>
<img
src={pic.url}
className="w-full h-10 md:h-20 object-center"
/>
<p className="text-center text-xs">{pic.name}</p>
</div>
))]
Idpics.slice(i * limit, i * limit + limit).map((picture, index: number) => (
<div
className={`m-1 shrink-0 rounded shadow-md h-45 relative overflow-hidden`}
key={index}>
<img
src={"http://localhost:3000/images/" + picture.pic.newfilename}
className="w-full h-40 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">
<span >{picture.title}</span>
</div>
</div>
))]
slides.push(k);
}
......
......@@ -7,37 +7,37 @@ type ThemeProps = {
export default function Theme({ handleClick }: ThemeProps) {
return (
<div className="overflow-x-auto flex rounded md:justify-center">
<button id={"surfing"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"서핑"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
서핑
</button>
<button id={"activity"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"액티비티"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
액티비티
</button>
<button id={"camping"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300 ">
<button id={"캠핑"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300 ">
캠핑
</button>
<button id={"sking"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"스키"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
스키
</button>
<button id={"boat"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"보트"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
보트
</button>
<button id={"desert"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"사막"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
사막
</button>
<button id={"golf"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"골프"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
골프
</button>
<button id={"cave"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"동굴"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
동굴
</button>
<button id={"history"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"문화재"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
문화재
</button>
<button id={"zoo"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"동물원"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
동물원
</button>
<button id={"cycling"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
<button id={"사이클링"} onClick={handleClick} className="shrink-0 px-5 hover:text-sky-300">
사이클링
</button>
</div>
......
......@@ -9,70 +9,70 @@ export default function Citylist({ handleClick }: CityProps) {
<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>
<button
id={"Seoul"}
id={"서울"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
서울
</button>
<button
id={"Busan"}
id={"부산"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
부산
</button>
<button
id={"Incheon"}
id={"인천"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
인천
</button>
<button
id={"Daegoo"}
id={"대구"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
대구
</button>
<button
id={"Kwangjoo"}
id={"광주"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
광주
</button>
<button
id={"Daejeon"}
id={"대전"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
대전
</button>
<button
id={"Woolsan"}
id={"울산"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
울산
</button>
<button
id={"Sejong"}
id={"세종"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
세종
</button>
<button
id={"Dokdo"}
id={"독도"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
독도
</button>
<button
id={"Jeju"}
id={"제주"}
onClick={handleClick}
className="px-5 py-2 hover:underline shrink-0"
>
......
......@@ -43,6 +43,9 @@ export interface MainimgType {
_id: string;
theme: string;
city: string;
url: string;
title: string;
pic : {
originalfilename: string;
newfilename: string;
};
}
......@@ -12,6 +12,7 @@ app.use(cookieParser());
app.use("/api", router);
app.use("/images", express.static(path.join(__dirname, "..", "/uploads")));
app.use("/images", express.static(path.join(__dirname, "..", "/adminpics")));
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
console.log("익스프레스 에러: ", err);
......
......@@ -3,38 +3,77 @@ import isLength from "validator/lib/isLength";
import { TypedRequestAuth } from "./auth.controller";
import { asyncWrap } from "../helpers";
import { mainimgDb } from "../db";
import { TypedRequest } from "../types";
import { ObjectId } from "mongoose";
import formidable from "formidable";
export const createMainimg = asyncWrap(async (reqExp, res, next) => {
const req = reqExp as TypedRequestAuth<{ userId: string }>;
export const createMainimg = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequestAuth<{ userId: ObjectId }>;
const { userId } = req.auth
const { theme, city, url, title } = req.body as {
theme: string;
city: string;
url: string;
title: string;
};
// const { theme, city, url, title } = req.body as {
// theme: string;
// city: string;
// url: string;
// title: string;
// };
console.log("body", req.body);
// console.log("body", req.body);
if (!isLength(url ?? "", { min: 1 })) {
return res.status(422).send("이미지 url을 입력해주세요");
}
if (!isLength(title ?? "", { min: 1 })) {
return res.status(422).send("이미지 제목을 입력해주세요");
}
const newMainimg = await mainimgDb.createMainimg({
theme,
city,
url,
title,
const form = formidable({
uploadDir: "uploads",
keepExtensions: true,
multiples: false,
});
return res.json(newMainimg);
form.parse(req, (err, fields, files) => {
if (!Array.isArray(files.mainimg)) {
//파일 좁히기 중
if (
!(
Array.isArray(fields.city) ||
Array.isArray(fields.title) ||
Array.isArray(fields.theme)
)
) {
const city = fields.city;
const title = fields.title;
const theme = fields.theme;
const originalfilename = files.mainimg?.originalFilename;
const newfilename = files.mainimg.newFilename;
if (!(originalfilename === null || newfilename === undefined)) {
mainimgDb.createMainimg(
{ city, title, theme },
{
originalfilename,
newfilename,
}
);
}
}
}
});
res.json();
});
// if (!isLength(url ?? "", { min: 1 })) {
// return res.status(422).send("이미지 url을 입력해주세요");
// }
// if (!isLength(title ?? "", { min: 1 })) {
// return res.status(422).send("이미지 제목을 입력해주세요");
// }
// const newMainimg = await mainimgDb.createMainimg({
// theme,
// city,
// url,
// title,
// });
// return res.json(newMainimg);
// });
export const getMainimg = asyncWrap(async (req, res) => {
const mainimgs = await mainimgDb.getMainimg();
return res.json(mainimgs);
......@@ -49,25 +88,52 @@ export const deleteMainimg = asyncWrap(async (req, res) => {
return res.json(deleteCount);
});
export const updateMainimg = asyncWrap(async (req, res) => {
const { title, theme, city, url } = req.body as {
title: string;
url: string;
theme: string;
city: string;
};
const { imgId } = req.params;
export const updateMainimg = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequestAuth<{ userId: ObjectId }>;
const form = formidable({
uploadDir: "uploads",
keepExtensions: true,
multiples: false,
});
const updateImg = await mainimgDb.updateOnePost(
{
title,
theme,
city,
url,
},
imgId
);
return res.json(updateImg);
form.parse(req, (err, fields, files) => {
if (!Array.isArray(files.updatemainimg)) {
//파일 좁히기 중
if (
!(Array.isArray(fields.id) ||
Array.isArray(fields.city) ||
Array.isArray(fields.title) ||
Array.isArray(fields.theme)
)
) {
const id = fields.id;
const city = fields.city;
const title = fields.title;
const theme = fields.theme;
console.log("error")
if (!(files.updatemainimg ===undefined)){
const originalfilename = files.updatemainimg?.originalFilename;
const newfilename = files.updatemainimg.newFilename;
if (!(originalfilename === null || newfilename === undefined)) {
mainimgDb.updateOneMainimg(
id,
theme,
city,
title,
originalfilename,
newfilename
);
}
}
else {
mainimgDb.updateOneMainimg(id, theme, city, title)}
}
}
});
res.json();
});
import { userDb } from "../db";
import { asyncWrap } from "../helpers/asyncWrap";
import { Request } from "express";
import formidable, { Fields, Files } from "formidable";
import formidable from "formidable";
import { ObjectId } from "mongoose";
import fs from "fs";
......
import { Mainimg, MainimgType } from "../models";
import { Avatar, IAvatar, Mainimg, MainimgType } from "../models";
import { ObjectId } from "mongoose";
export const createMainimg = async (mainimg: MainimgType, pic: IAvatar) => {
const newPic = await Avatar.create({
originalfilename: pic.originalfilename,
newfilename: pic.newfilename,
pictureauth: pic.picturepath,
});
export const createMainimg = async (mainimg: MainimgType) => {
const newMainimg = await Mainimg.create({
theme: mainimg.theme,
city: mainimg.city,
url: mainimg.url,
pic: newPic._id,
title: mainimg.title,
});
return newMainimg;
};
export const getMainimg = async () => {
const users = await Mainimg.find({});
return users;
};
const img = await Mainimg.find({}).populate("pic");
return img;
};
export const deleteOneMainimg = async (_id: string) => {
const res = await Mainimg.deleteOne({ _id: _id });
return res;
};
export const updateOnePost = async (mainimg: MainimgType, _id: string) => {
const newMainimg = await Mainimg.findOneAndUpdate(
{ _id: _id },
{
theme: mainimg.theme,
city: mainimg.city,
url: mainimg.url,
title: mainimg.title,
},
{ new: true }
);
return newMainimg;
};
\ No newline at end of file
export const updateOneMainimg = async (
_Id: string,
theme: string,
city: string,
title: string,
originalfilename?: string | null,
newfilename?: string,
) => {
const newMainimg = await Mainimg.findById(_Id);
console.log("error2",_Id)
if (!(newMainimg?.pic === 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 Avatar.findByIdAndUpdate(newMainimg.pic._id, {
originalfilename: originalfilename,
newfilename: newfilename,
})
console.log("error6")
}
else {
await Avatar.findByIdAndUpdate(newMainimg.pic._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 bcrypt from "bcryptjs";
import { ObjectId } from "mongoose";
import { IUser, Role, Post, User, Avatar } from "../models";
import fs from "fs";
import fs from "fs/promises";
export const createUser = async (user: IUser) => {
// 비밀번호 암호화
......@@ -106,9 +106,7 @@ export const deleteUser = async (userId: ObjectId) => {
const user = await User.findById(userId);
if (!(user?.avatar === undefined)) {
const ref = await Avatar.findById(user.avatar._id);
fs.unlink("../travel/uploads/" + ref?.newfilename, (err) => {
console.log(err);
});
await fs.unlink("../travel/uploads/" + ref?.newfilename);
await Avatar.deleteOne({ _id: user.avatar._id });
await User.deleteOne({ _id: userId });
}
......
import {model, Schema } from "mongoose";
import {model, Schema, Types } from "mongoose";
export interface MainimgType {
theme: string;
city: string;
url: string;
title: string;
pic?: Types.ObjectId;
}
const MainimgSchema = new Schema<MainimgType>({
......@@ -15,13 +15,14 @@ const MainimgSchema = new Schema<MainimgType>({
city: {
type: String,
},
url : {
type: String,
},
title: {
type: String,
required: true,
},
pic: {
type : Schema.Types.ObjectId,
ref: "Avatar"
}
});
......
......@@ -11,7 +11,7 @@ router
router
.route("/:imgId")
.delete(authCtrl.requireLogin, mainimgCtrl.deleteMainimg)
.put(authCtrl.requireLogin, mainimgCtrl.updateMainimg);
.put(authCtrl.requireLogin, authCtrl.hasRole("admin"), mainimgCtrl.updateMainimg);
export default router;
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