Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KDT0_KimTeukHee 직원관리서비스 #51

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e3fc88a
feat: 파일기본구성
turkey-kim Aug 9, 2023
1c13bbf
feat: 프로필 등록 폼 추가
turkey-kim Aug 9, 2023
d5d07ce
feat: 멤버리스트 레이아웃 추가
turkey-kim Aug 9, 2023
ceb8acd
feat: 프로필 등록폼 반응형으로 구현;
turkey-kim Aug 10, 2023
724f829
feat: DOM객체 상수화 및 스타일 수정
turkey-kim Aug 11, 2023
8698efd
set: AWS SDK 세팅
turkey-kim Aug 11, 2023
ceb5065
docs: 폴더구조 변경
turkey-kim Aug 11, 2023
33484f3
feat: 사진 및 프로필 정보 업로드 기능 추가
turkey-kim Aug 14, 2023
a56f8bd
refactor: api 분리 및 파일 구조 변경
turkey-kim Aug 14, 2023
35c64f9
refactor: 필요없는 코드 삭제
turkey-kim Aug 14, 2023
00284db
feat: 프로필 리스팅 구현
turkey-kim Aug 14, 2023
3f9ddaa
feat: Profile 상세페이지 추가
turkey-kim Aug 16, 2023
8ca963f
feat: profile 상세 로드 api 추가
turkey-kim Aug 16, 2023
e0a1f53
docs: 홈페이지 메인 스크립트 위치 변경
turkey-kim Aug 16, 2023
5896213
docs: profile.html 위치 변경
turkey-kim Aug 16, 2023
6f29b54
docs: constant.js 변경
turkey-kim Aug 16, 2023
bb938c3
style : 주석 제거 및 코드 위치 변경
turkey-kim Aug 16, 2023
5e62abd
feat: 프로필 페이지 주요 DOM 상수화
turkey-kim Aug 16, 2023
8a5deb1
feat: 프로필 수정 폼 추가
turkey-kim Aug 16, 2023
2cdc566
feat: 프로필 수정 기능 추가
turkey-kim Aug 16, 2023
6f25b05
feat: 프로필 삭제 기능 추가
turkey-kim Aug 16, 2023
b82d064
style: header 디자인 추가
turkey-kim Aug 17, 2023
e0eddf8
feat: 메인페이지 모달창 추가
turkey-kim Aug 17, 2023
7b103e3
feat: 프로필상세 페이지 모달 구현 및 기타
turkey-kim Aug 17, 2023
ced93f6
style: css 테마 및 일부 스타일 수정
turkey-kim Aug 17, 2023
9e175b6
comment: listProfile.js 주석추가
turkey-kim Aug 17, 2023
1862832
style: css 스타일 보완
turkey-kim Aug 18, 2023
eb7cd32
feat: 기본프로필 이미지 업로드 기능 추가
turkey-kim Aug 18, 2023
1fdae33
feat: aws설정변수 관리 파일 추가
turkey-kim Aug 18, 2023
ae9e86e
refactor: 폴더변경 및 에러코드제거
turkey-kim Aug 18, 2023
70e9de9
rename: api키 변수명 변경
turkey-kim Aug 18, 2023
380fffb
feat: 헤더 애니메이션 추가
turkey-kim Aug 18, 2023
231b1d1
docs: README 작성
turkey-kim Aug 18, 2023
4cc77dc
comments: 주석 추가
turkey-kim Aug 18, 2023
14de89b
docs: README 수정
turkey-kim Aug 18, 2023
954597a
docs: README 수정
turkey-kim Aug 18, 2023
805fb1e
docs: README 수정
turkey-kim Aug 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
key.js
92 changes: 46 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
## TK Company 직원 관리 서비스

# :camera: 직원 사진 관리 서비스

직원들의 사진을 관리할 수 있는 사진 관리자 서비스를 만들어 보세요.

과제 수행 및 리뷰 기간은 별도 공지를 참고하세요!
## [과제 수행 및 제출 방법]
1. 현재 저장소를 로컬에 클론(Clone)합니다.
2. 자신의 본명으로 브랜치를 생성합니다.(구분 가능하도록 본명을 꼭 파스칼케이스로 표시하세요, git branch KDT0_이름)
3. 자신의 본명 브랜치에서 과제를 수행합니다.
4. 과제 수행이 완료되면, 자신의 본명 브랜치를 원격 저장소에 푸시(Push)합니다.(main 브랜치에 푸시하지 않도록 꼭 주의하세요, git push origin KDT0_이름)
5. 저장소에서 main 브랜치를 대상으로 Pull Request 생성하면, 과제 제출이 완료됩니다!(E.g, main <== KDT0_이름)
6. Pull Request 링크를 LMS로도 제출해 주셔야 합니다.
7. main 혹은 다른 사람의 브랜치로 절대 병합하지 않도록 주의하세요!
8. Pull Request에서 보이는 설명을 다른 사람들이 이해하기 쉽도록 꼼꼼하게 작성하세요!
9. Pull Request에서 과제 제출 후 절대 병합(Merge)하지 않도록 주의하세요!
10. 과제 수행 및 제출 과정에서 문제가 발생한 경우, 바로 담당 멘토나 강사에서 얘기하세요!

## [필수 요구사항]
- “AWS S3 / Firebase 같은 서비스”를 이용하여 사진을 관리할 수 있는 페이지를 구현하세요.
- 프로필 페이지를 개발하세요.
- 스크롤이 가능한 형태의 리스팅 페이지를 개발하세요.
- 전체 페이지 데스크탑-모바일 반응형 페이지를 개발하세요.
- 사진을 등록, 수정, 삭제가 가능해야 합니다.
- 유저 플로우를 제작하여 리드미에 추가하세요.
* CSS
* 애니메이션 구현
* 상대수치 사용(rem, em)
* JavaScript
* DOM event 조작

## [선택 요구사항]
- 사진 관리 페이지와 관련된 기타 기능도 고려해 보세요.
- 페이지가 보여지기 전에 로딩 애니메이션이 보이도록 만들어보세요.
- 직원을 등록, 수정, 삭제가 가능하게 해보세요.
- 직원 검색 기능을 추가해 보세요.
- infinity scroll 기능을 추가해 보세요.
- 사진을 편집할 수 있는 기능을 추가해 보세요.
- LocalStorage 사용

## [화면 예시]
![Untitled (1)](https://github.com/KDT1-FE/Y_FE_JAVASCRIPT_PICTURE/assets/38754963/5dda6755-2501-4af4-bc3e-b63a353c44c2)

![Untitled (2)](https://github.com/KDT1-FE/Y_FE_JAVASCRIPT_PICTURE/assets/38754963/6c1805f1-2b00-453e-a729-2b483612726d)

## [흐름]
![Untitled](https://github.com/KDT1-FE/Y_FE_JAVASCRIPT_PICTURE/assets/38754963/e2934c05-26f6-4ef6-88d4-beed76aa007a)
- 가상회사 TK company의 직원 DB 개발
- 개발 기간 : 2023.08.08 ~ 2023.08.18
- [배포주소](https://deploy--peaceful-heliotrope-44df2b.netlify.app/)

### 주요 기능

- 직원 정보 등록 (사진 & 인적사항)
- 직원 정보 상세 보기
- 직원 정보 수정 / 삭제

### 주요 기능 상세

| 기능 | 이미지 | 설명 |
| :---------------: | :-----------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------ |
| 1. 직원 조회 | <img src="https://turkey-mm-bucket.s3.ap-northeast-2.amazonaws.com/home.png" width="500"> | - S3의 직원목록 로드 |
| 2. 직원 등록 | <img src="https://turkey-mm-bucket.s3.ap-northeast-2.amazonaws.com/enroll.png" width="500"> | - 모달창 구현 <br> - 업로드 사진 미리보기 <br> - 사진 미등록 시, <br>기본프로필 이미지 설정 |
| 3. 정보 수정 | <img src="https://turkey-mm-bucket.s3.ap-northeast-2.amazonaws.com/edit.gif" width="500"> | - 모달창 구현 <br> - 사진/인적사항 변경 |
| 4. 직원 정보 삭제 | <img src="https://turkey-mm-bucket.s3.ap-northeast-2.amazonaws.com/delete.gif" width="500"> |
| 5. 반응형 웹 | <img src="https://turkey-mm-bucket.s3.ap-northeast-2.amazonaws.com/mobile.gif" width="500"> |

### 스택

<img src="https://img.shields.io/badge/html5-E34F26?style=for-the-badge&logo=html5&logoColor=white"> <img src="https://img.shields.io/badge/css3-1572B6?style=for-the-badge&logo=css3&logoColor=white"> <img src="https://img.shields.io/badge/js-F7DF1E?style=for-the-badge&logo=javascript&logoColor=white"> <img src="https://img.shields.io/badge/AMAZON S3-569A31?style=for-the-badge&logo=amazons3&logoColor=white">

<br>

### USER-FLOW

<img src="https://turkey-mm-bucket.s3.ap-northeast-2.amazonaws.com/userFlow.png" width="700">

### 요구사항

1. 필수

- [x] “AWS S3 / Firebase 같은 서비스”를 이용하여 사진을 관리할 수 있는 페이지를 구현하세요.
- [x] 프로필 페이지를 개발하세요.
- [x] 스크롤이 가능한 형태의 리스팅 페이지를 개발하세요.
- [x] 전체 페이지 데스크탑-모바일 반응형 페이지를 개발하세요.
- [x] 사진을 등록, 수정, 삭제가 가능해야 합니다.
- [x] 유저 플로우를 제작하여 리드미에 추가하세요.
- [x] 애니메이션 구현
- [x] DOM 조작

2. 선택

- [x] 직원을 등록, 수정, 삭제가 가능하게 해보세요.
- [x] LocalStorage 사용
Binary file added assets/.DS_Store
Binary file not shown.
Binary file added assets/img/.DS_Store
Binary file not shown.
Binary file added assets/img/profile.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 112 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="/styles/general.css" />
<link rel="stylesheet" href="/styles/theme.css" />
<link rel="stylesheet" href="/styles/main.css" />
<link rel="stylesheet" href="/styles/header.css" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+KR:wght@200;300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1433.0.min.js"></script>
</head>
<body>
<header class="header">
<a id="header-title" href="/">TK company MemberDB</a>
</header>
<main id="home">
<h1 class="title text-xl">우리 회사 직원들</h1>
<div class="control-container">
<div class="control-container_button-container">
<button class="text-m" id="open-enroll-form">등록</button>
</div>
</div>

<div id="modal">
<form class="enroll-form bg-main150">
<div class="enroll-form__container">
<div class="enroll-form__photoBox bg-gray">
<img id="preview" src="/assets/img/profile.jpeg" />
<label class="photo-input__label" for="photo-input"
>Upload Image</label
>
<input id="photo-input" type="file" />
</div>
<div class="enroll-form__inputBox">
<label for="name-input">이름</label>
<input id="name-input" autocomplete="off" />
<label for="email-input">이메일</label>
<input id="email-input" autocomplete="off" />
<label for="phoneNum-input">전화번호</label>
<input id="phoneNum-input" autocomplete="off" />
<label for="position-input">포지션</label>
<input id="position-input" autocomplete="off" />
<button class="enroll-form__submit bg-blue text-s" type="submit">
submit
</button>
<button class="enroll-form__cancel bg-pink text-s">cancel</button>
</div>
</div>
</form>
</div>

<div class="member-info">
<div class="member-info__header bg-main100">
<div class="member-info__img">사진</div>
<div class="member-info__name">이름</div>
<div class="member-info__phoneNum">전화번호</div>
<div class="member-info__email">이메일</div>
<div class="member-info__position">포지션</div>
</div>
</div>
</main>
<script type="module" src="js/config/key.js"></script>
<script type="module" src="/js/constant/home.js"></script>
<script type="module" src="/js/api/uploadProfile.js"></script>
<script type="module" src="/js/api/listProfile.js"></script>
<script type="module">
import {
btn_openEnrollForm,
enrollForm,
btn_addProfile,
btn_closeEnrollForm,
enroll_photo,
} from "/js/constant/home.js";

import { uploadProfileToS3 } from "/js/api/uploadProfile.js";
import { listProfileFromS3 } from "/js/api/listProfile.js";

btn_openEnrollForm.addEventListener("click", openForm); // 프로필 등록 폼 열기
btn_closeEnrollForm.addEventListener("click", closeForm); // 프로필 등록 폼 닫기
enroll_photo.addEventListener("change", previewImg); // 이미지 프리뷰

listProfileFromS3(); // 프로필 불러오기 (Read)
btn_addProfile.addEventListener("click", uploadProfileToS3); // s3로 프로필업로드

function previewImg() {
const imageSrc = URL.createObjectURL(enroll_photo.files[0]);
document.getElementById("preview").src = imageSrc;
}

function openForm(e) {
e.preventDefault();
const modal = document.querySelector("#modal");
modal.style.visibility = "visible";
}

function closeForm(e) {
e.preventDefault();
const modal = document.querySelector("#modal");
modal.style.visibility = "hidden";
}

const photo = enroll_photo.files[0];
</script>
</body>
</html>
35 changes: 35 additions & 0 deletions js/api/deleteProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { accessKeyId, accessKey } from "/js/config/key.js";

import { bucketName, region } from "/js/constant/aws.js";

AWS.config.update({
region,
credentials: new AWS.Credentials(accessKeyId, accessKey),
});

const s3 = new AWS.S3({
apiVersion: "2006-03-01",
params: { Bucket: bucketName },
});

const key = localStorage.getItem("profile");
const params01 = {
Bucket: bucketName,
Key: `${key}/profile_photo`,
};
const params02 = {
Bucket: bucketName,
Key: `${key}/profile_detail`,
};

export const deleteProfile = async function () {
try {
await s3.deleteObject(params01).promise();
console.log("photo deleteted");
await s3.deleteObject(params02).promise();
console.log("info deleteted");
window.location.href = window.location.origin;
} catch (error) {
console.error(error);
}
};
64 changes: 64 additions & 0 deletions js/api/editProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { accessKeyId, accessKey } from "/js/config/key.js";

import { bucketName, region } from "/js/constant/aws.js";

import {
edit_photo,
edit_name,
edit_email,
edit_phoneNum,
edit_position,
} from "../constant/profile.js";

AWS.config.update({
region,
credentials: new AWS.Credentials(accessKeyId, accessKey),
});

const s3 = new AWS.S3({
apiVersion: "2006-03-01",
params: { Bucket: bucketName },
});

export const editProfile = function (e) {
e.preventDefault();
const photo = edit_photo.files[0]; // 수정할 프로필 사진

const profileInfo = {
name: edit_name.value,
email: edit_email.value,
phoneNum: edit_phoneNum.value,
position: edit_position.value,
}; // 사진을 제외한 프로필 정보

const key = localStorage.getItem("profile");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분처럼 local에 저장해놓고 사용했으면 정보 가져오기 편했을 것 같아요 ~

const folerPath = `${key}/`; // 사진과 정보가 들어갈 S3폴더명(로컬스토리지)

const params_photo = photo
? {
Bucket: bucketName,
Key: folerPath + "profile_photo",
Body: photo,
}
: null; // 수정할 사진이 채워지지 않을 경우 null;

const params_info = {
Bucket: bucketName,
Key: folerPath + "profile_detail",
Body: JSON.stringify(profileInfo),
};

const edit = async () => {
try {
params_photo ? await s3.upload(params_photo).promise() : null;
console.log("photo edit complete");
await s3.upload(params_info).promise();
console.log("info edit complete");
location.reload();
} catch (err) {
console.error(err);
}
};

edit();
};
42 changes: 42 additions & 0 deletions js/api/getProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { accessKeyId, accessKey } from "/js/config/key.js";

import { bucketName, region, S3endpoint } from "/js/constant/aws.js";

AWS.config.update({
region,
credentials: new AWS.Credentials(accessKeyId, accessKey),
});

const s3 = new AWS.S3({
apiVersion: "2006-03-01",
params: { Bucket: bucketName },
});

export const getProfile = () => {
s3.listObjectsV2({ Bucket: bucketName }, (err, data) => {
if (err) {
console.err(err);
} else {
console.log(data);
}
});

const key = localStorage.getItem("profile");
const photo = document.getElementById("profile-photo");
photo.src = S3endpoint + "/" + key + "/profile_photo";

s3.getObject(
{ Bucket: bucketName, Key: `${key}/profile_detail` },
(err, data) => {
let info = JSON.parse(data.Body.toString());
for (let key in info) {
let obj = document.getElementsByClassName(`profile__${key}`)[0];
let detail = document.createElement("span");
detail.innerText = info[key];
obj.appendChild(detail);
}
}
);
};

getProfile();
Loading