위코드 2차 프로젝트로 오늘의집 사이트를 모티브로 은행의집 사이트를 제작했다. 자취하면서 인테리어에 관심갖게 되고 자주 들락날락 했었던 사이트. 우리집 인테리어에 많은 기여를 해줬던 사이트. 애정있는 사이트가 선정되어 시작부터 기분이 좋았다. 😀
이번 2차 프로젝트 팀원은 총 6명인데 그동안 교류를 잘 못했던 분들과 친목을 다질 수 있어서 좋았다 !
1차 때 한 번 해봤다고 2차 시작할 때는 금방금방 업무분장을 할 수 있었다. 이번에는 styled-component를 사용했는데 common.css 와 variable.css 등등을 적용해서 초기세팅하는 부분은 처음에 좀 혼란스러웠다.
BANK HOUSE (은행의 도움을 받아 집을 매매하는 현실을 반영..)
오늘의집 사이트 클론코딩. 네브 탭들이 많아서 선택과 집중을 해야 했다. 이커머스 기능은 1차 때 해봤으므로 패스..! 커뮤니티 부분에 집중을 했다. 사용자가 본인 집 인테리어를 직접 올려서 공유하고 소통하는 기능 위주로 구현했다. 메인페이지 클론을 해도 해당 탭 구현이 안되어 있기 때문에 구성을 조금 바꿨다. 메인페이지를 (기존 메인페이지의 배너 부분 + 사진 카테고리페이지)로 구성했다.
프론트 : HTML
, Styled-component
, JAVASCRIPT
, REACT (HOOKS)
백엔드 : PYTHON
, DJANGO
, DOKER
TRELLO
, GITHUB
, TRELLO
, SLACK
2주 (2021.05.24. ~ 06.04.)
프론트엔드 4명, 백엔드 2명
(내가 기여한 기능 볼드체 표시)
슬라이더 부분은 react-slick 라이브러리를 사용!
필터가 6개가 있다. 필터기능구현보다 해당 필터 선택시 색이 변하는 기능과 초기화 부분에 고생하셨다.
소셜로그인과 일반로그인 기능이 있다.
(gif가 왜 안올라갈까 !!!)
const timeForToday = postedTime => {
const today = new Date();
const timeValue = new Date(postedTime);
const betweenTime = Math.floor(
(today.getTime() - timeValue.getTime()) / 1000 / 60
);
if (betweenTime < 1) return '방금전';
if (betweenTime < 60) {
return `${betweenTime}분전`;
}
const betweenTimeHour = Math.floor(betweenTime / 60);
const betweenTimeDay = Math.floor(betweenTime / 60 / 24);
const betweenTimeMonth = Math.floor(betweenTime / 60 / 24 / 30);
if (betweenTimeHour < 24) {
return `${betweenTimeHour}시간전`;
}
if (betweenTimeDay < 31) {
return `${betweenTimeDay}일전`;
}
if (betweenTimeMonth < 12) {
return `${betweenTimeMonth}달전`;
}
return `${Math.floor(betweenTimeDay / 365)}년전`;
};
//2021-06-01T01:08:38.348Z 값을
//"2021-05-23T23:19:20+0000" 형식으로 변경
const postedDate = date => {
const timeSplit = date.slice(0, 19);
const posted = new Date(`${timeSplit}+0000`);
return timeForToday(posted.getTime());
};
(gif가 왜 안올라갈까 !!!...대체왜.. )
isBtnOnceClicked
state 를 false로 하고 올리기 버튼을 누를 때 true로 바꿨다.isBtnOnceClicked
가 true && 아래의 selectedCategory
가 비어져있다면 red 로 변경 const [selectedCategory, setSelectedCategory] = useState({
description: '',
livingtype: '',
space: '',
size: '',
style: '',
});
<SelectWrapper
isSelected={!!selectedCategory?.[menuName.menuNameValue]}
isBtnOnceClicked={isBtnOnceClicked}
>
<Option
// 생략
/>
))}
</SelectWrapper>
);
}
const SelectWrapper = styled.select`
border: 1px solid
${({ theme, isSelected, isBtnOnceClicked }) =>
!isSelected && isBtnOnceClicked ? 'red' : theme.inputGray};
<UploadInput
type="file"
name="photo"
id="photo"
accept="image/*"
onChange={onFileInput}
required
/>
const onFileInput = e => {
e.preventDefault();
const reader = new FileReader();
const file = e.target.files[0];
reader.readAsDataURL(file);
reader.onload = () => {
setPreviewURL(reader.result);
setFile(file);
};
};
사진 올리기 기능과 preview! 유진, 도은님께서 많은 도움을 주셨다 !
const onPost = () => {
const selectedInfo = JSON.stringify(selectedCategory);
// 스타일, 평수 등의 data는 JSON문자열로 변환한다.
const categoryData = new FormData();
// FormData 객체를 만든다.
categoryData.append('info', selectedInfo);
categoryData.append('image', file);
// 스타일, 평수 등의 data는 변환한 값을, file data는 변환하지 않은 값을 넣어준다. 'info', 'image'는 백과 값을 맞춰준다.
fetch('API', {
method: 'POST',
headers: {
Authorization: localStorage.getItem('access_token'),
},
body: categoryData,
})
.then(res => res.json())
.then(data => console.log(`data`, data));
history.push(`/`);
};
전투코딩 🪓🪓🪓ㅋㅋㅋㅋㅋㅋㅋㅋ 지연님이랑 프로젝트 못해본 거 너무너무 한....😢 이번에도 고생하셨어요💙💙