localhost-front/src/components/commuters/CommuterBtn.vue
2025-03-27 18:12:11 +09:00

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>