component
import { GetServerSideProps, NextPage } from "next";
import { useRouter } from "next/router";
import { CounterState } from "../../../store/types/state";
import { da, js } from "../../../type";
const Firstid = ({
main,
update,
}: {
main: CounterState;
update: () => void;
}) => {
const { query } = useRouter();
const id = query.id;
return (
<div>
{main.data.map((res: da, index: number) => {
if (res.idx == id) {
return (
<div key={index}>
<div className="section">
<h1 className="title" key={"title"}>
{res.text.title}
</h1>
<div className="time">
<div className="timetitle">약속 시간</div>
<div className="timecontent">
<div className="timedateinput">{res.text.time}</div>
<div className="timetimeinput">{res.text.date}</div>
</div>
</div>
<div className="mapinfo">
<div className="map">
<iframe
width="350"
height="550"
loading="lazy"
></iframe>
</div>
<div className="mapdes">
지도에
<h3>"{res.text.address}"</h3>
검색해주세요
</div>
</div>
<div className="content">
<h3 className="contitle">계획</h3>
<div className="condes">{res.text.content}</div>
</div>
<div className="tags">
{res.text.tags?.map((res, index) => {
return (
<div key={`tags${index}`} className="tag">
{res}
</div>
);
})}
</div>
<div className="buttons">
<div className="reset">
<button onClick={update}>수정</button>
</div>
<div className="finish">
<button>완료</button>
</div>
</div>
</div>
<style jsx>
{`
.section {
display: flex;
align-items: center;
flex-direction: column;
min-height: 900px;
background-color: #f5b467;
}
.section > .title {
margin: 1%;
color: #196aff;
}
.scetion > .time {
width: 100%;
}
.section > .time > .timetitle {
font-size: 28px;
font-weight: bolder;
width: 350px;
text-align: center;
margin: 2%;
display: flex;
flex-direction: column;
}
.section > .time > .timetitle::after {
content: " ";
border: 1px solid #636beb;
width: 90%;
margin: auto;
}
.section > .time > .timecontent {
font-size: 28px;
font-weight: bolder;
width: 350px;
text-align: center;
display: flex;
justify-content: space-around;
margin: 2%;
}
.section > .time > .timecontent > * {
font-size: 18px;
font-weight: bolder;
}
.section > .mapinfo {
border: 5px solid #636beb;
border-radius: 10px;
max-width: 354px;
margin: 1%;
}
.section > .mapinfo > .map {
background-color: whitesmoke;
}
.section > .mapinfo > .mapdes {
font-size: 20px;
text-align: center;
padding: 1%;
background-color: whitesmoke;
}
.section > .content {
min-width: 350px;
display: flex;
flex-direction: column;
margin: 1%;
border: 3px solid #636beb;
background-color: #eab7f5;
}
.section > .content > .contitle {
text-align: center;
color: #196aff;
font-size: 28px;
width: 100%;
display: flex;
flex-direction: column;
}
.section > .content > .contitle::after {
content: " ";
border: 1px solid #636beb;
width: 80%;
margin: auto;
}
.section > .content > .condes {
text-align: center;
font-weight: bolder;
font-size: 18px;
width: 100%;
}
.section > .tags {
width: 350px;
display: flex;
flex-flow: wrap;
justify-content: center;
}
.section > .tags > .tag {
border: 1px solid #636beb;
border-radius: 16px;
margin: 1%;
padding: 1%;
background-color: #636beb;
font-weight: bolder;
color: whitesmoke;
}
.section > .tags > .tag::before {
content: "#";
}
.section > .buttons {
display: flex;
justify-content: center;
width: 90%;
max-width: 350px;
}
.section > .buttons > * {
width: 200px;
}
.section > .buttons > * > * {
font-weight: bolder;
font-size: 28px;
margin: 5%;
max-width: 100%;
padding: 5%;
border-radius: 12px;
}
.section > .buttons > .finish {
display: flex;
justify-content: end;
}
.section > .buttons > .reset > * {
background-color: yellow;
border: 1px solid;
}
.section > .buttons > .finish > * {
background-color: #6856f8;
border: 1px solid;
display: flex;
justify-content: end;
}
`}
</style>
</div>
);
}
})}
</div>
);
};
export default Firstid;
container
import { NextPage } from "next";
import { useRouter } from "next/router";
import { useDispatch, useSelector } from "react-redux";
import Id from "../../../components/form/firstform/id";
import { RootState } from "../../../store/reducers";
import { CounterState } from "../../../store/types/state";
const FirstidContainer: NextPage = () => {
const dispatch = useDispatch();
const router = useRouter();
const { main }: { main: CounterState } = useSelector(
(state: RootState) => state
);
const update = () => {
router.push(`/form/firstform/update/${router.query.id}`);
};
return (
<div>
<Id main={main} update={update} />
</div>
);
};
export default FirstidContainer;
const { main }: { main: CounterState } = useSelector(
(state: RootState) => state
);
이부분은 redux에서 데이터를 가져오는 부분이다
const update = () => {
router.push(`/form/firstform/update/${router.query.id}`);
};
이부분은 수정 페이지로 이동하는 기능을 하게 됩니다.
router를 이용해서 페이지id를 가져와서 같은 id의update페이지로 이동하게 됩니다.
==============================================================================
component
import { NextPage } from "next";
import { MutableRefObject, RefObject } from "react";
const FirstForm = ({
titleref,
dateref,
timeref,
addressref,
contentref,
tagsref,
finish,
reset,
}: {
titleref: RefObject<HTMLInputElement>;
dateref: RefObject<HTMLInputElement>;
timeref: RefObject<HTMLInputElement>;
addressref: RefObject<HTMLInputElement>;
contentref: RefObject<HTMLTextAreaElement>;
tagsref: RefObject<HTMLInputElement>;
finish: () => void;
reset: () => void;
}) => {
return (
<div>
<div className="section">
<h1 className="title">
<input
className="titleinput"
ref={titleref}
placeholder="약속이름 작성"
/>
</h1>
<div className="time">
<div className="timetitle">약속 시간</div>
<div className="timecontent">
<input type="date" ref={dateref} className="timedateinput" />
<input type="time" ref={timeref} className="timetimeinput" />
</div>
</div>
<div className="mapinfo">
<div className="map">
<iframe
width="350"
height="350"
loading="lazy"
></iframe>
</div>
<div className="mapdes">
지도에
<h3>
<input
ref={addressref}
className="mapdesinput"
placeholder="주소 또는 장소 이름 작성"
/>
</h3>
검색해주세요
</div>
</div>
<div className="content">
<h3 className="contitle">계획</h3>
<div className="condes">
<textarea
ref={contentref}
className="condesinput"
placeholder="세부내용 작성"
/>
</div>
</div>
<input
ref={tagsref}
className="tagsinput"
placeholder="#으로 태그를 구분해주세요"
/>
<div className="tags">
<div className="tag">예시</div>
<div className="tag">예시</div>
<div className="tag">예시</div>
</div>
<div className="buttons">
<div className="reset">
<button onClick={reset}>초기화</button>
</div>
<div className="finish">
<button onClick={finish}>완료</button>
</div>
</div>
</div>
<style jsx>
{`
.section {
display: flex;
align-items: center;
flex-direction: column;
min-height: 900px;
background-color: #f5b467;
width: 100%;
}
.section > .title {
margin: 1%;
color: #196aff;
}
.section > .title > .titleinput {
font-size: 28px;
text-align: center;
font-weight: bolder;
width: 350px;
}
.scetion > .time {
width: 100%;
}
.section > .time > .timetitle {
font-size: 28px;
font-weight: bolder;
width: 350px;
text-align: center;
margin: 2%;
display: flex;
flex-direction: column;
}
.section > .time > .timetitle::after {
content: " ";
border: 1px solid #636beb;
width: 90%;
margin: auto;
}
.section > .time > .timecontent {
font-size: 28px;
font-weight: bolder;
width: 350px;
text-align: center;
display: flex;
justify-content: space-around;
margin: 2%;
}
.section > .time > .timecontent > * {
font-size: 18px;
font-weight: bolder;
}
.section > .mapinfo {
border: 5px solid #636beb;
border-radius: 10px;
max-width: 354px;
margin: 1%;
}
.section > .mapinfo > .map {
background-color: whitesmoke;
}
.section > .mapinfo > .mapdes {
font-size: 20px;
text-align: center;
padding: 1%;
background-color: whitesmoke;
}
.section > .mapinfo > .mapdes > h3 > .mapdesinput {
font-size: 20px;
text-align: center;
font-weight: bolder;
}
.section > .content {
min-width: 350px;
display: flex;
flex-direction: column;
margin: 1%;
border: 3px solid #636beb;
background-color: #eab7f5;
}
.section > .content > .contitle {
text-align: center;
color: #196aff;
font-size: 28px;
width: 100%;
display: flex;
flex-direction: column;
}
.section > .content > .contitle::after {
content: " ";
border: 1px solid #636beb;
width: 80%;
margin: auto;
}
.section > .content > .condes {
text-align: center;
font-weight: bolder;
font-size: 18px;
width: 100%;
}
.section > .content > .condes > .condesinput {
text-align: center;
font-weight: bolder;
font-size: 18px;
margin: 1%;
width: 80%;
height: 100px;
}
.tagsinput {
width: 350px;
font-size: 18px;
}
.section > .tags {
width: 350px;
display: flex;
flex-flow: wrap;
justify-content: center;
}
.section > .tags > .tag {
border: 1px solid #636beb;
border-radius: 16px;
margin: 1%;
padding: 1%;
background-color: #636beb;
font-weight: bolder;
color: whitesmoke;
}
.section > .tags > .tag::before {
content: "#";
}
.section > .buttons {
display: flex;
justify-content: center;
width: 90%;
max-width: 350px;
}
.section > .buttons > * {
width: 200px;
}
.section > .buttons > * > * {
font-weight: bolder;
font-size: 28px;
margin: 5%;
max-width: 100%;
padding: 5%;
border-radius: 12px;
}
.section > .buttons > .finish {
display: flex;
justify-content: end;
}
.section > .buttons > .reset > * {
background-color: yellow;
border: 1px solid;
}
.section > .buttons > .finish > * {
background-color: #6856f8;
border: 1px solid;
display: flex;
justify-content: end;
}
`}
</style>
</div>
);
};
export default FirstForm;
container
import { useRef } from "react";
import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import Index from "../../../components/form/firstform/index";
import { dataadd } from "../../../store/actions/action";
import { RootState } from "../../../store/reducers";
import { CounterState } from "../../../store/types/state";
import { da } from "../../../type";
const FirstindexContainer = () => {
const dispatch = useDispatch();
const { main }: { main: CounterState } = useSelector(
(state: RootState) => state
);
const titleref = useRef<HTMLInputElement>(null);
const dateref = useRef<HTMLInputElement>(null);
const timeref = useRef<HTMLInputElement>(null);
const addressref = useRef<HTMLInputElement>(null);
const contentref = useRef<HTMLTextAreaElement>(null);
const tagsref = useRef<HTMLInputElement>(null);
const reset: () => void = () => {
titleref.current!.value = "";
dateref.current!.value = "";
timeref.current!.value = "";
addressref.current!.value = "";
contentref.current!.value = "";
tagsref.current!.value = "";
};
const finish: () => void = () => {
console.log(main.data);
const data: da | undefined = makedata();
if (data != undefined) {
dispatch(dataadd(data));
if (main.common.login == "admin") {
alert(
`id를 기억하세요 id:${(
parseInt(main.data[main.data.length - 1].idx) + 1
).toString()}`
);
}
reset();
} else {
alert("태그 제외 모든 빈칸을 넣어주세요");
}
};
const makedata = () => {
if (
titleref.current?.value &&
dateref.current?.value &&
timeref.current?.value &&
addressref.current?.value &&
contentref.current?.value
) {
const tagarr: string[] | undefined = tagsref.current?.value.split("#");
tagarr?.splice(0, 1);
const data: da = {
idx: (parseInt(main.data[main.data.length - 1].idx) + 1).toString(),
currentform: "first",
maker: main.common.login,
text: {
address: addressref.current?.value,
content: contentref.current?.value,
date: dateref.current?.value,
tags: tagarr,
time: timeref.current?.value,
title: titleref.current?.value,
},
};
return data;
}
};
return (
<div>
<Index
titleref={titleref}
dateref={dateref}
timeref={timeref}
addressref={addressref}
contentref={contentref}
tagsref={tagsref}
finish={finish}
reset={reset}
/>
</div>
);
};
export default FirstindexContainer;
const reset: () => void = () => {
titleref.current!.value = "";
dateref.current!.value = "";
timeref.current!.value = "";
addressref.current!.value = "";
contentref.current!.value = "";
tagsref.current!.value = "";
};
함수실행시 input부분을 빈칸으로 비워주는 기능을하게 됩니다.
const finish: () => void = () => {
console.log(main.data);
const data: da | undefined = makedata();
if (data != undefined) {
dispatch(dataadd(data));
if (main.common.login == "admin") {
alert(
`id를 기억하세요 id:${(
parseInt(main.data[main.data.length - 1].idx) + 1
).toString()}`
);
}
reset();
} else {
alert("태그 제외 모든 빈칸을 넣어주세요");
}
};
makedata로 데이터를 만들고 login이 admin이면 비회원이므로 id를 기억해서 찾을수 있도록 했습니다.
또한 데이터가 비어있으면 작동이 하지 않도록 설정했습니다.
const makedata = () => {
if (
titleref.current?.value &&
dateref.current?.value &&
timeref.current?.value &&
addressref.current?.value &&
contentref.current?.value
) {
const tagarr: string[] | undefined = tagsref.current?.value.split("#");
tagarr?.splice(0, 1);
const data: da = {
idx: (parseInt(main.data[main.data.length - 1].idx) + 1).toString(),
currentform: "first",
maker: main.common.login,
text: {
address: addressref.current?.value,
content: contentref.current?.value,
date: dateref.current?.value,
tags: tagarr,
time: timeref.current?.value,
title: titleref.current?.value,
},
};
return data;
}
};
데이터를 생성하는 함수 입니다.
const titleref = useRef<HTMLInputElement>(null);
const dateref = useRef<HTMLInputElement>(null);
const timeref = useRef<HTMLInputElement>(null);
const addressref = useRef<HTMLInputElement>(null);
const contentref = useRef<HTMLTextAreaElement>(null);
const tagsref = useRef<HTMLInputElement>(null);
ref로 input부분에 데이터를 가져오거나 업데이트 가능하도록 했습니다.
'next+ts' 카테고리의 다른 글
next+ts 기본 페이지 전체 코드 둘러보기(Component+container) (0) | 2022.05.04 |
---|---|
next+ts 폼선택 페이지 전체 코드 둘러보기(Component+container) (0) | 2022.05.04 |
next+ts 업데이터 페이지 전체 코드 둘러보기 (Component+container) (0) | 2022.05.02 |
next+ts18일차 link연결 +redux에서 route사용 (0) | 2022.04.30 |
next+ts17일차 update 페이지 (0) | 2022.04.29 |