Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…ri-FE-01 into feature/CSID-DGU#6
  • Loading branch information
Minn-Choi committed Dec 5, 2024
2 parents 9e20d86 + d94bbea commit 3e0488b
Show file tree
Hide file tree
Showing 35 changed files with 560 additions and 2,647 deletions.
47 changes: 42 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,37 @@
## 🏗 설계 및 구현

- ### 📂 프로젝트 구조
- 프로젝트의 주요 디렉토리 구조와 설명을 포함합니다.

```
📦 프로젝트 루트
┣ 📂src
┃ ┣ 📂assets
┃ ┃ ┣ 📂data
┃ ┃ ┣ 📂fonts
┃ ┃ ┣ 📂Icons
┃ ┃ ┃ ┗ 📂akoming
┃ ┃ ┣ 📂images
┃ ┃ ┗ 📂styles
┃ ┣ 📂components # 공용 컴포넌트
┃ ┃ ┣ 📂common
┃ ┃ ┗ 📂layout
┃ ┣ 📂router # Vue Router
┃ ┣ 📂store # Vuex
┃ ┣ 📂views
┃ ┃ ┣ 📂akopolio # 아코폴리오 관련 페이지
┃ ┃ ┣ 📂calendar # 학사 일정 캘린더 관련 페이지
┃ ┃ ┣ 📂feed # 피드 관련 페이지
┃ ┃ ┣ 📂login # 로그인, 회원가입, 마이페이지 관련 페이지
┃ ┃ ┣ 📂mainpage # 메인 페이지 관련 파일
┃ ┃ ┗ 📜NotFound.vue # 404 에러 페이지
┣ 📂public
┣ 📂docs # 보고서 등 문서 폴더
┃ ┗ 📜README.md
┣ 📜App.vue
┣ 📜main.js
```



- ### 🧩 다이어그램
아키텍처 다이어그램, 서비스 흐름, 데이터 흐름 등을 그림으로 표현합니다.
Expand All @@ -69,8 +99,9 @@
![osori](https://github.com/user-attachments/assets/d90a2ae9-aac0-4ba0-92bf-fd08abee8d4b)


- ### 📑 API 명세서
- 각 API의 설명, 요청 및 응답 예시를 포함합니다.
- ### 📑 API 명세서 일부
    ![1](https://github.com/user-attachments/assets/21191f05-1f77-4c98-878c-f3b5ddaa6f99)


<br>

Expand Down Expand Up @@ -105,9 +136,15 @@

## ▶ 실행 방법

1. **환경 설정**: 프로젝트 실행을 위한 필수 환경 변수 및 설정 정보를 포함합니다.
2. **의존성 설치**: 프로젝트의 종속성을 설치하는 단계입니다.
1. **환경 설정**: Node.js, npm, vue-cli를 설치합니다.
```bash
npm install -g @vue/cli
2. **의존성 설치**:<br>
```bash
npm install
3. **프로젝트 실행**: 실행 명령어로 프로젝트를 시작합니다.
```bash
npm run dev

<br>

Expand Down
17 changes: 9 additions & 8 deletions docs/회의록.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
| 8차 | 2024년 10월 16일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 이소은 | https://www.notion.so/8-12db4ba0516b81178342cc75df07750b |
| 9차 | 2024년 10월 21일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정지원 | https://www.notion.so/9-12db4ba0516b8164b602fd248747296b |
| 10차 | 2024년 10월 23일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 최민 | https://www.notion.so/10-12db4ba0516b81d9a131f2c52ae5ee89 |
| 11차 | 2024년 10월 28일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정예빈 | https://www.notion.so/11-12db4ba0516b8071b0f8fcce55a7a442?pvs=4 |
| 12차 | 2024년 10월 30일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 이소은 | https://www.notion.so/12-bf84f851b63442adba1b69159a772725?pvs=4 |
| 13차 | 2024년 11월 4일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정지원 | https://www.notion.so/13-a6297b09e7bd45fa904862463bca54c4?pvs=4 |
| 14차 | 2024년 11월 6일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 최민 | https://www.notion.so/14-416a0ab074c54e1f945a72cd3c3acb18?pvs=4 |
| 15차 | 2024년 11월 11일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정예빈 | https://www.notion.so/15-29633aca525242d983483ebc20b8871d?pvs=4 |
| 16차 | 2024년 11월 18일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 이소은 | https://www.notion.so/16-dce780571dbe4f9a84e4bb58be834e66?pvs=4 |
| 17차 | 2024년 11월 20일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정지원 | https://www.notion.so/17-476981be247b4d339ff70ae25a91d80e?pvs=4 |

| 11차 | 2024년 10월 28일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정예빈 | https://www.notion.so/11-12db4ba0516b8071b0f8fcce55a7a442 |
| 12차 | 2024년 10월 30일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 이소은 | https://www.notion.so/12-bf84f851b63442adba1b69159a772725 |
| 13차 | 2024년 11월 4일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정지원 | https://www.notion.so/13-a6297b09e7bd45fa904862463bca54c4 |
| 14차 | 2024년 11월 6일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 최민 | https://www.notion.so/14-416a0ab074c54e1f945a72cd3c3acb18 |
| 15차 | 2024년 11월 11일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정예빈 | https://www.notion.so/15-29633aca525242d983483ebc20b8871d |
| 16차 | 2024년 11월 18일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 이소은 | https://www.notion.so/16-dce780571dbe4f9a84e4bb58be834e66 |
| 17차 | 2024년 11월 20일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정지원 | https://www.notion.so/17-476981be247b4d339ff70ae25a91d80e |
| 18차 | 2024년 11월 27일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 최민 | https://www.notion.so/17-476981be247b4d339ff70ae25a91d80e |
| 19차 | 2024년 12월 4일 | 정기 회의 | 이소은, 최민, 정지원, 정예빈 | 정예빈 | https://www.notion.so/17-476981be247b4d339ff70ae25a91d80e |
42 changes: 37 additions & 5 deletions src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import FeedLayout from '@/components/layout/FeedLayout.vue'
import akopolioCreate from '@/views/akopolio/create/akopolioCreate.vue'
import akopolioMain from '@/views/akopolio/main/akopolioMain.vue'


// 자동 임포트 함수 (src/views 내의 모든 .vue 파일을 임포트)
function importAllViews() {
const viewFiles = require.context('@/views', true, /\.vue$/)
Expand Down Expand Up @@ -81,8 +80,7 @@ const routes = [
path: 'edit/:id',
name: 'akopolioEdit',
component: importedViews['akopolioEdit'] // 자동 임포트 적용
},

}
]
},
{
Expand Down Expand Up @@ -138,6 +136,40 @@ const router = createRouter({
routes
})

//라우터 가드 설정(세션 기반 쿠기, 나중에 수정 필요)
// meta: { requiresAuth: true } // 인증이 필요한 페이지
//라우터 가드 설정
// 글로벌 가드 추가
router.beforeEach(async (to, from, next) => {
const isAuthPage = to.matched.some((record) =>
record.path.startsWith('/auth')
)

try {
// 세션 상태 확인 API 호출
const response = await fetch(
`${process.env.VUE_APP_BE_API_URL}/api/quests/status`,
{
method: 'GET',
credentials: 'include' // 세션 쿠키 포함
}
)

if (response.ok) {
if (isAuthPage) {
next('/main') // 이미 인증된 상태라면 메인 페이지로 이동
} else {
next() // 정상적으로 페이지 이동
}
} else {
if (isAuthPage) {
next() // 인증 경로로는 접근 가능
} else {
next('/auth/login') // 인증되지 않았으면 로그인 페이지로 이동
}
}
} catch (error) {
console.error('Error during authentication check:', error)
next('/auth/login') // 오류 발생 시 로그인 페이지로 이동
}
})

export default router
69 changes: 35 additions & 34 deletions src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,61 @@
import { createStore } from 'vuex';
import auth from '../views/test/auth.js'; // auth 모듈 import
import login from './modules/login.js'; // 로그인 모듈 import
import { v4 as uuidv4 } from 'uuid'; // UUID를 사용하여 고유 ID 생성
import { createStore } from 'vuex'
import login from './modules/login.js' // 로그인 모듈 import
import { v4 as uuidv4 } from 'uuid' // UUID를 사용하여 고유 ID 생성

// 로컬 스토리지에서 포트폴리오 가져오기
const getStoredPortfolios = () => {
const storedPortfolios = localStorage.getItem('portfolios');
return storedPortfolios ? JSON.parse(storedPortfolios) : [];
};
const storedPortfolios = localStorage.getItem('portfolios')
return storedPortfolios ? JSON.parse(storedPortfolios) : []
}

const store = createStore({
state: {
portfolios: getStoredPortfolios(), // 로컬 스토리지에서 포트폴리오 초기화
portfolios: getStoredPortfolios() // 로컬 스토리지에서 포트폴리오 초기화
},
mutations: {
ADD_PORTFOLIO(state, portfolio) {
const newPortfolio = { ...portfolio, id: uuidv4() }; // 고유 ID 추가
state.portfolios.push(newPortfolio); // 포트폴리오 추가
localStorage.setItem('portfolios', JSON.stringify(state.portfolios)); // 로컬 스토리지에 저장
const newPortfolio = { ...portfolio, id: uuidv4() } // 고유 ID 추가
state.portfolios.push(newPortfolio) // 포트폴리오 추가
localStorage.setItem('portfolios', JSON.stringify(state.portfolios)) // 로컬 스토리지에 저장
},
DELETE_PORTFOLIO(state, portfolioId) {
state.portfolios = state.portfolios.filter(portfolio => portfolio.id !== portfolioId);
localStorage.setItem('portfolios', JSON.stringify(state.portfolios)); // 로컬 스토리지에 삭제 후 저장
state.portfolios = state.portfolios.filter(
(portfolio) => portfolio.id !== portfolioId
)
localStorage.setItem('portfolios', JSON.stringify(state.portfolios)) // 로컬 스토리지에 삭제 후 저장
},
// 수정 기능을 위한 UPDATE_PORTFOLIO 뮤테이션 추가
UPDATE_PORTFOLIO(state, updatedPortfolio) {
const index = state.portfolios.findIndex(portfolio => portfolio.id === updatedPortfolio.id);
// 수정 기능을 위한 UPDATE_PORTFOLIO 뮤테이션 추가
UPDATE_PORTFOLIO(state, updatedPortfolio) {
const index = state.portfolios.findIndex(
(portfolio) => portfolio.id === updatedPortfolio.id
)
if (index !== -1) {
state.portfolios.splice(index, 1, updatedPortfolio); // 기존 항목을 업데이트된 항목으로 교체
localStorage.setItem('portfolios', JSON.stringify(state.portfolios)); // 로컬 스토리지에 업데이트 후 저장
state.portfolios.splice(index, 1, updatedPortfolio) // 기존 항목을 업데이트된 항목으로 교체
localStorage.setItem('portfolios', JSON.stringify(state.portfolios)) // 로컬 스토리지에 업데이트 후 저장
}
},
}
},
actions: {
addPortfolio({ commit }, portfolio) {
commit('ADD_PORTFOLIO', portfolio); // mutation 호출
commit('ADD_PORTFOLIO', portfolio) // mutation 호출
},
deletePortfolio({ commit }, portfolioId) {
commit('DELETE_PORTFOLIO', portfolioId);
},
// 수정 기능을 위한 updatePortfolio 액션 추가
updatePortfolio({ commit }, updatedPortfolio) {
commit('UPDATE_PORTFOLIO', updatedPortfolio); // UPDATE_PORTFOLIO 뮤테이션 호출
commit('DELETE_PORTFOLIO', portfolioId)
},
// 수정 기능을 위한 updatePortfolio 액션 추가
updatePortfolio({ commit }, updatedPortfolio) {
commit('UPDATE_PORTFOLIO', updatedPortfolio) // UPDATE_PORTFOLIO 뮤테이션 호출
}
},
getters: {
getPortfolios(state) {
return state.portfolios; // 포트폴리오 목록 반환
},
return state.portfolios // 포트폴리오 목록 반환
}
},
modules: {
login, // 로그인 모듈
auth, // auth 모듈
},
});

export default store;

login // 로그인 모듈
// auth 모듈
}
})

export default store
53 changes: 31 additions & 22 deletions src/views/akopolio/Edit/akopolioEdit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
</label>

<div v-show="isDropdownOpen" class="tag-container">
<button
v-for="tag in tags"
:key="tag"
@click="toggleTag(tag)"
:class="{ active: selectedTags.includes(tag) }"
>
{{ tag }}
</button>
<div
v-for="tag in tags"
:key="tag"
@click="toggleTag(tag)"
:class="{ active: selectedTags.includes(tag), 'tag-div': true }"
>
{{ tag }}
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -75,16 +75,21 @@
<div class="image-preview-container" v-if="images.length">
<div class="image-card" v-for="(image, index) in images" :key="index">
<div class="image-preview-card">
<img :src="image.previewUrl" :alt="`Uploaded Image ${index + 1}`" class="image-preview" />
<button @click="removeImage(index)" class="delete-image-btn">X</button>
<img
v-if="image.previewUrl"
:src="image.previewUrl"
:alt="`Uploaded Image ${index + 1}`"
class="image-preview"
/>
<div @click="removeImage(index)" class="delete-image-btn">X</div>
</div>
</div>
</div>
</div>

<div class="button-container">
<button @click="saveData" class="save-button">저장하기</button>
</div>
<div @click="saveData" class="save-button">저장하기</div>
</div>
<MainFooter />
</div>
</template>
Expand Down Expand Up @@ -155,7 +160,7 @@ textarea {
font-size: 12px;
}
button {
.tag-div {
display: inline-block;
margin: 3px;
padding: 5px 10px;
Expand All @@ -165,8 +170,13 @@ button {
border: 1px solid #eec092;
}
button.active {
background-color: #f6b87a;
.tag-div.active {
background-color: #f7c088;
}
.tag-div:hover {
background-color: #f7c088;
cursor: pointer;
}
/* 분야 설정 박스 */
Expand Down Expand Up @@ -208,12 +218,14 @@ button.active {
font-size: 0.875rem;
font-weight: 500;
border-radius: 9999px;
text-align: center;
transition: background-color 0.3s ease;
margin-bottom: 20px;
}
.save-button:hover {
background-color: #e5a769;
cursor: pointer;
}
.experience-container h3,
Expand Down Expand Up @@ -269,16 +281,15 @@ label {
top: 5px;
right: 5px;
color: black;
border: none;
background: none; /* 배경색 제거 */
font-size: 16px; /* X 아이콘이 더 잘 보이도록 크기 조정 */
background: none;
font-size: 15px;
cursor: pointer;
transition: color 0.3s; /* 색상 전환 애니메이션 추가 */
transition: color 0.3s;
}
.delete-image-btn:hover {
color: white;
color:#d9d9d9;
}
Expand All @@ -302,12 +313,10 @@ label {
object-fit: contain; /* 이미지가 컨테이너 내에서 비율을 유지하면서 크기 조정 */
}
/* 기본 input[type="file"] 숨기기 */
input[type="file"] {
display: none;
}
/* 커스텀 버튼 스타일 */
.custom-file-upload {
background-color: #faf5f0;
color: #f3ab62;
Expand Down
Loading

0 comments on commit 3e0488b

Please sign in to comment.