184 lines
4.9 KiB
Vue
184 lines
4.9 KiB
Vue
<template>
|
|
<div class="row g-0">
|
|
<div class="col-6 pe-1">
|
|
<button
|
|
class="btn border-3 w-100 py-0 h-px-50"
|
|
:class="workTime ? 'p-0 btn-primary pe-none' : 'btn-outline-primary'"
|
|
@click="setWorkTime"
|
|
>
|
|
<i v-if="!workTime" class="bx bx-run fs-2"></i>
|
|
<span v-if="workTime" class="ql-size-12px">{{ workTime }}</span>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="col-6 ps-1">
|
|
<button
|
|
class="btn border-3 w-100 py-0 h-px-50"
|
|
:class="!workTime ? 'btn-outline-secondary pe-none disabled' : 'btn-outline-secondary'"
|
|
@click="setLeaveTime"
|
|
:disabled="!workTime"
|
|
>
|
|
<i v-if="!leaveTime" class='bx bxs-door-open fs-2'></i>
|
|
<span v-if="leaveTime" class="ql-size-12px">{{ leaveTime }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, defineProps, defineEmits, onMounted, watch } from 'vue';
|
|
import $api from '@api';
|
|
import { useGeolocation } from '@vueuse/core';
|
|
|
|
const props = defineProps({
|
|
userId: {
|
|
type: Number,
|
|
required: false
|
|
},
|
|
checkedInProject: {
|
|
type: Object,
|
|
required: false
|
|
},
|
|
pendingProjectChange: {
|
|
type: Object,
|
|
default: null
|
|
}
|
|
});
|
|
|
|
const emit = defineEmits(['workTimeUpdated', 'leaveTimeUpdated', 'projectChangeComplete']);
|
|
|
|
const workTime = ref(null);
|
|
const leaveTime = ref(null)
|
|
const userLocation = ref(null);
|
|
|
|
// 위치 정보 가져오기 설정
|
|
const { coords, isSupported, error } = useGeolocation({
|
|
enableHighAccuracy: true,
|
|
});
|
|
|
|
// 주소 변환 함수
|
|
const getAddress = (lat, lng) => {
|
|
return new Promise((resolve, reject) => {
|
|
const geocoder = new kakao.maps.services.Geocoder();
|
|
const coord = new kakao.maps.LatLng(lat, lng);
|
|
|
|
geocoder.coord2Address(coord.getLng(), coord.getLat(), (result, status) => {
|
|
if (status === kakao.maps.services.Status.OK) {
|
|
const address = result[0].address.address_name;
|
|
resolve(address);
|
|
} else {
|
|
reject('주소를 가져올 수 없습니다.');
|
|
return;
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
// 위치 정보 가져오기 함수
|
|
const getLocation = async () => {
|
|
if (!isSupported.value) {
|
|
alert('브라우저가 위치 정보를 지원하지 않습니다.');
|
|
return null;
|
|
}
|
|
|
|
if (error.value) {
|
|
alert(`위치 정보를 가져오는데 실패했습니다: ${error.value.message}`);
|
|
return null;
|
|
}
|
|
|
|
if (coords.value) {
|
|
userLocation.value = {
|
|
lat: coords.value.latitude,
|
|
lng: coords.value.longitude,
|
|
};
|
|
|
|
try {
|
|
const address = await getAddress(coords.value.latitude, coords.value.longitude);
|
|
return address;
|
|
} catch (error) {
|
|
alert(error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
// 오늘 사용자의 출근 정보 조회
|
|
const todayCommuterInfo = async () => {
|
|
if (!props.userId) return;
|
|
|
|
const res = await $api.get(`commuters/today/${props.userId}`);
|
|
if (res.status === 200) {
|
|
const commuterInfo = res.data.data[0];
|
|
|
|
if (commuterInfo) {
|
|
workTime.value = commuterInfo.COMMUTCMT;
|
|
leaveTime.value = commuterInfo.COMMUTLVE;
|
|
|
|
// 부모 컴포넌트에 상태 업데이트 알림
|
|
emit('workTimeUpdated', workTime.value);
|
|
emit('leaveTimeUpdated', leaveTime.value);
|
|
}
|
|
}
|
|
};
|
|
|
|
// 출근 시간
|
|
const setWorkTime = async () => {
|
|
// 이미 출근 시간이 설정된 경우 중복 실행 방지
|
|
if (workTime.value) return;
|
|
|
|
// 현재 위치 주소 가져오기
|
|
const address = await getLocation();
|
|
|
|
$api.post('commuters/insert', {
|
|
memberSeq: props.userId,
|
|
projctSeq: props.checkedInProject.PROJCTSEQ,
|
|
commutLve: null,
|
|
commutArr: address,
|
|
}).then(res => {
|
|
if (res.status === 200) {
|
|
todayCommuterInfo();
|
|
|
|
emit('workTimeUpdated', true);
|
|
}
|
|
});
|
|
};
|
|
|
|
// 퇴근
|
|
const setLeaveTime = () => {
|
|
$api.patch('commuters/updateLve', {
|
|
memberSeq: props.userId,
|
|
commutLve: leaveTime.value || null,
|
|
projctLve: props.pendingProjectChange ? props.pendingProjectChange.projctSeq : props.checkedInProject.PROJCTSEQ
|
|
}).then(res => {
|
|
if (res.status === 200) {
|
|
todayCommuterInfo();
|
|
emit('leaveTimeUpdated');
|
|
}
|
|
});
|
|
};
|
|
|
|
// props 변경 감지
|
|
watch(() => props.userId, async () => {
|
|
if (props.userId) {
|
|
await todayCommuterInfo();
|
|
}
|
|
});
|
|
|
|
watch(() => props.checkedInProject, () => {
|
|
// 프로젝트가 변경되면 필요한 처리 수행
|
|
}, { deep: true });
|
|
|
|
onMounted(async () => {
|
|
await todayCommuterInfo();
|
|
});
|
|
|
|
// 외부에서 접근할 메서드 노출
|
|
defineExpose({
|
|
todayCommuterInfo,
|
|
workTime,
|
|
leaveTime
|
|
});
|
|
</script>
|