-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from Triumers/feat/manager
[Feature] 직원 조회 기능 구현 및 직책 관리, 직급 관리 기능 구현
- Loading branch information
Showing
6 changed files
with
520 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
<template> | ||
<div class="container"> | ||
<div> | ||
<h1>직원 조회</h1> | ||
</div> | ||
<div style="height: 20px;"></div> | ||
<div class="search-container"> | ||
<input | ||
type="text" | ||
v-model="searchKeyword" | ||
placeholder="이름 검색" | ||
class="search-input" | ||
@input="searchEmployees" | ||
/> | ||
</div> | ||
<div v-if="employees.length === 0 && searchKeyword !== ''" class="no-results"> | ||
검색 결과가 없습니다. | ||
</div> | ||
<div class="employee-list"> | ||
<div | ||
v-for="employee in employees" | ||
:key="employee.id" | ||
class="employee-item" | ||
> | ||
<div class="employee-name">{{ employee.name }}</div> | ||
<div class="employee-email">{{ employee.email }}</div> | ||
<div class="employee-team">{{ employee.team.name }}</div> | ||
<div class="employee-position">{{ employee.position.name }}</div> | ||
<div class="employee-rank">{{ employee.rank.name }}</div> | ||
<div class="employee-start-date">{{ employee.startDate }}</div> | ||
<div class="employee-end-date">{{ employee.endDate }}</div> | ||
<div class="employee-phone-number">{{ employee.phoneNumber }}</div> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import { ref, onMounted } from 'vue'; | ||
import axios from 'axios'; | ||
const searchKeyword = ref(''); | ||
const employees = ref([]); | ||
onMounted(async () => { | ||
await searchEmployees(); | ||
}); | ||
async function searchEmployees() { | ||
try { | ||
const token = localStorage.getItem('token'); | ||
const response = await axios.post('http://localhost:5000/employee/find/name', { | ||
name: searchKeyword.value, | ||
}, { | ||
headers: { | ||
Authorization: token, | ||
}, | ||
}); | ||
employees.value = response.data.employee; | ||
} catch (error) { | ||
console.error('Failed to search employees:', error); | ||
alert('직원 검색에 실패했습니다. 다시 시도해주세요.'); | ||
} | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
.container { | ||
max-width: 800px; | ||
margin: 0 auto; | ||
padding: 20px; | ||
} | ||
.search-container { | ||
display: flex; | ||
align-items: center; | ||
margin-bottom: 20px; | ||
} | ||
.search-input { | ||
flex: 1; | ||
padding: 10px; | ||
border: 1px solid #ccc; | ||
border-radius: 4px; | ||
} | ||
.search-button-wrapper { | ||
margin-left: 10px; | ||
} | ||
.search-button { | ||
padding: 10px 20px; | ||
background-color: #042444; | ||
color: white; | ||
border: none; | ||
border-radius: 4px; | ||
cursor: pointer; | ||
transition: background-color 0.2s; | ||
} | ||
.search-button:hover { | ||
background-color: #1b2cba; | ||
} | ||
.no-results { | ||
text-align: center; | ||
font-style: italic; | ||
color: #888; | ||
margin-bottom: 20px; | ||
} | ||
.employee-list { | ||
display: grid; | ||
grid-template-columns: repeat(1, 1fr); | ||
gap: 20px; | ||
} | ||
.employee-item { | ||
background-color: #f5f5f5; | ||
padding: 20px; | ||
border-radius: 4px; | ||
} | ||
.employee-name { | ||
font-size: 18px; | ||
font-weight: bold; | ||
margin-bottom: 5px; | ||
} | ||
.employee-email, | ||
.employee-team, | ||
.employee-position, | ||
.employee-rank, | ||
.employee-start-date, | ||
.employee-end-date, | ||
.employee-phone-number { | ||
font-size: 14px; | ||
color: #888; | ||
margin-bottom: 5px; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
<template> | ||
<div class="container"> | ||
<h2>직책 관리</h2> | ||
<div class="form-container"> | ||
<h3>직책 생성</h3> | ||
<input type="text" v-model="newPosition" placeholder="새로운 직책명" /> | ||
<button @click="createPosition">생성</button> | ||
</div> | ||
<div class="form-container"> | ||
<h3>직책 수정</h3> | ||
<select v-model="selectedPositionId"> | ||
<option v-for="position in positions" :key="position.id" :value="position.id"> | ||
{{ position.name }} | ||
</option> | ||
</select> | ||
<input type="text" v-model="editedPosition" placeholder="수정할 직책명" /> | ||
<button @click="updatePosition">수정</button> | ||
</div> | ||
<div class="form-container"> | ||
<h3>직책 삭제</h3> | ||
<select v-model="selectedPositionIdToDelete"> | ||
<option v-for="position in positions" :key="position.id" :value="position.id"> | ||
{{ position.name }} | ||
</option> | ||
</select> | ||
<button @click="deletePosition">삭제</button> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import { ref, onMounted } from 'vue'; | ||
import axios from 'axios'; | ||
const positions = ref([]); | ||
const newPosition = ref(''); | ||
const selectedPositionId = ref(''); | ||
const editedPosition = ref(''); | ||
const selectedPositionIdToDelete = ref(''); | ||
onMounted(async () => { | ||
await fetchPositions(); | ||
}); | ||
async function fetchPositions() { | ||
try { | ||
const token = localStorage.getItem('token'); | ||
const response = await axios.get('http://localhost:5000/duty/find/position/all', { | ||
headers: { | ||
Authorization: token, | ||
}, | ||
}); | ||
positions.value = response.data.position; | ||
} catch (error) { | ||
console.error('Failed to fetch positions:', error); | ||
alert('직책 정보를 불러오는데 실패했습니다. 다시 시도해주세요.'); | ||
} | ||
} | ||
async function createPosition() { | ||
try { | ||
const token = localStorage.getItem('token'); | ||
await axios.post('http://localhost:5000/manager/duty/add/position', { | ||
positionName: newPosition.value, | ||
}, { | ||
headers: { | ||
Authorization: token, | ||
}, | ||
}); | ||
newPosition.value = ''; | ||
await fetchPositions(); | ||
} catch (error) { | ||
console.error('Failed to create position:', error); | ||
alert('직책 생성에 실패했습니다. 다시 시도해주세요.'); | ||
} | ||
} | ||
async function updatePosition() { | ||
try { | ||
const token = localStorage.getItem('token'); | ||
await axios.put('http://localhost:5000/manager/duty/edit/position', { | ||
positionId: selectedPositionId.value, | ||
positionName: editedPosition.value, | ||
}, { | ||
headers: { | ||
Authorization: token, | ||
}, | ||
}); | ||
editedPosition.value = ''; | ||
selectedPositionId.value = ''; | ||
await fetchPositions(); | ||
} catch (error) { | ||
console.error('Failed to update position:', error); | ||
alert('직책 수정에 실패했습니다. 다시 시도해주세요.'); | ||
} | ||
} | ||
async function deletePosition() { | ||
try { | ||
const token = localStorage.getItem('token'); | ||
await axios.delete('http://localhost:5000/manager/duty/remove/position', { | ||
data: { | ||
positionId: selectedPositionIdToDelete.value, | ||
}, | ||
headers: { | ||
Authorization: token, | ||
}, | ||
}); | ||
selectedPositionIdToDelete.value = ''; | ||
await fetchPositions(); | ||
} catch (error) { | ||
console.error('Failed to delete position:', error); | ||
alert('직책 삭제에 실패했습니다. 다시 시도해주세요.'); | ||
} | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
.container { | ||
max-width: 800px; | ||
margin: 0 auto; | ||
padding: 20px; | ||
} | ||
.form-container { | ||
margin-bottom: 20px; | ||
} | ||
h2 { | ||
font-size: 24px; | ||
margin-bottom: 20px; | ||
} | ||
h3 { | ||
font-size: 18px; | ||
margin-bottom: 10px; | ||
} | ||
input[type="text"] { | ||
width: 300px; | ||
padding: 10px; | ||
border: 1px solid #ccc; | ||
border-radius: 4px; | ||
margin-right: 10px; | ||
} | ||
select { | ||
width: 300px; | ||
padding: 10px; | ||
border: 1px solid #ccc; | ||
border-radius: 4px; | ||
margin-right: 10px; | ||
} | ||
button { | ||
padding: 10px 20px; | ||
background-color: #042444; | ||
color: white; | ||
border: none; | ||
border-radius: 4px; | ||
cursor: pointer; | ||
transition: background-color 0.2s; | ||
} | ||
button:hover { | ||
background-color: #1b2cba; | ||
} | ||
</style> |
Oops, something went wrong.