254 lines
8.9 KiB
Vue
254 lines
8.9 KiB
Vue
<script setup>
|
|
import MeetingsDashboard from "@/pages/provider/MeetingsDashboard.vue";
|
|
import store from '@/store';
|
|
import EcommerceStatistics from '@/views/dashboard/provider/EcommerceStatistics.vue';
|
|
|
|
import PatientQueueMobile from '@/views/dashboard/provider/PatientQueueMobile.vue';
|
|
import videoCameraOff from '@images/svg/video-camera-off.svg';
|
|
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue';
|
|
const isLoadingVisible = ref(false);
|
|
const getIsTonalSnackbarVisible = ref(false);
|
|
const errorMessage = ref(null);
|
|
const videoElement = ref(null);
|
|
const isCameraPermissionGranted = ref(false);
|
|
const isMicrophonePermissionGranted = ref(false);
|
|
const isCameraDisabled = ref(false);
|
|
const isMuted = ref(false);
|
|
const isMobile = ref(window.innerWidth <= 768);
|
|
const profileData = ref(null);
|
|
const profileName = ref(null);
|
|
const mediaStream = ref(null);
|
|
const enableCamBtn = ref(true)
|
|
const camIcon = computed(() => {
|
|
return isCameraDisabled.value ? 'mdi-video-off' : 'mdi-video';
|
|
});
|
|
const checkMobile = () => {
|
|
isMobile.value = window.innerWidth <= 768;
|
|
};
|
|
const camText = computed(() => {
|
|
return isCameraDisabled.value ? 'Turn on camera' : 'Turn off camera';
|
|
});
|
|
|
|
const camIconColor = computed(() => {
|
|
return isCameraDisabled.value ? 'red' : 'black';
|
|
});
|
|
|
|
const micIcon = computed(() => {
|
|
return isMuted.value ? 'mdi-microphone-off' : 'mdi-microphone';
|
|
});
|
|
|
|
const micText = computed(() => {
|
|
return isMuted.value ? 'Unmute Myself' : 'Mute Myself';
|
|
});
|
|
|
|
const micIconColor = computed(() => {
|
|
return isMuted.value ? 'red' : 'black';
|
|
});
|
|
|
|
const checkPermissions = async () => {
|
|
try {
|
|
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
|
|
if (stream) {
|
|
isCameraPermissionGranted.value = true;
|
|
isMicrophonePermissionGranted.value = true;
|
|
enableCamBtn.value = false
|
|
await nextTick();
|
|
videoElement.value.srcObject = stream;
|
|
mediaStream.value = stream;
|
|
|
|
}
|
|
} catch (error) {
|
|
isCameraDisabled.value = true;
|
|
enableCamBtn.value = false
|
|
getIsTonalSnackbarVisible.value = true;
|
|
errorMessage.value = "We can't access your camera and microphone.";
|
|
console.error('Error accessing media devices:', error);
|
|
}
|
|
};
|
|
|
|
onMounted(async () => {
|
|
window.addEventListener('resize', checkMobile);
|
|
await store.dispatch('getAgentProfile');
|
|
profileData.value = store.getters.getAgentProfile.ai_switch;
|
|
profileName.value = profileData.value.name;
|
|
console.log("profileData", profileData.value);
|
|
// await checkPermissions();
|
|
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
if (mediaStream.value) {
|
|
const tracks = mediaStream.value.getTracks();
|
|
tracks.forEach((track) => track.stop());
|
|
mediaStream.value = null;
|
|
}
|
|
});
|
|
|
|
const toggleCamera = () => {
|
|
if (!isCameraPermissionGranted.value) {
|
|
getIsTonalSnackbarVisible.value = true;
|
|
errorMessage.value = "We can't access your camera and microphone.";
|
|
} else {
|
|
isCameraDisabled.value = !isCameraDisabled.value;
|
|
|
|
// Stop the stream if the camera is being turned off
|
|
if (isCameraDisabled.value && mediaStream.value) {
|
|
const tracks = mediaStream.value.getTracks();
|
|
tracks.forEach((track) => track.stop());
|
|
mediaStream.value = null;
|
|
videoElement.value.srcObject = null;
|
|
}
|
|
|
|
// Start the stream if the camera is being turned on
|
|
if (!isCameraDisabled.value) {
|
|
checkPermissions();
|
|
}
|
|
}
|
|
};
|
|
|
|
const toggleMic = () => {
|
|
if (!isMicrophonePermissionGranted.value) {
|
|
getIsTonalSnackbarVisible.value = true;
|
|
errorMessage.value = "We can't access your camera and microphone.";
|
|
} else {
|
|
isMuted.value = !isMuted.value;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<VDialog v-model="isLoadingVisible" width="110" height="150" color="primary">
|
|
<VCardText class="" style="color: white !important;">
|
|
<div class="demo-space-x">
|
|
<VProgressCircular :size="40" color="primary" indeterminate />
|
|
</div>
|
|
</VCardText>
|
|
</VDialog>
|
|
<VSnackbar v-model="getIsTonalSnackbarVisible" :timeout="5000" location="top end" variant="flat" color="red">
|
|
{{ errorMessage }}
|
|
</VSnackbar>
|
|
<VRow>
|
|
|
|
<VCol cols="12" md="12">
|
|
<PatientQueueMobile v-if="isMobile" />
|
|
</VCol>
|
|
|
|
|
|
<VCol cols="12" md="9">
|
|
|
|
<EcommerceStatistics class="h-100" />
|
|
</VCol>
|
|
<VCol cols="12" md="3">
|
|
<VCard class="auth-card rounded-5 bg-black" :class="isCameraDisabled || enableCamBtn ? 'pa-2' : ''">
|
|
<div class="align-items-center justify-content-center" style="min-height:200px">
|
|
<!-- <v-menu v-if="isCameraPermissionGranted && isMicrophonePermissionGranted">
|
|
<template v-slot:activator="{ props }">
|
|
<v-btn icon="mdi-dots-horizontal" v-bind="props" class="menu-btn" size="small"
|
|
rounded="xl"></v-btn>
|
|
</template>
|
|
|
|
<v-list>
|
|
<v-list-item @click="toggleCamera()">
|
|
<v-list-item-title>
|
|
<VIcon :color="camIconColor" :icon="camIcon"></VIcon> {{ camText }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item @click="toggleMic()">
|
|
<v-list-item-title>
|
|
<VIcon :color="micIconColor" :icon="micIcon"></VIcon> {{ micText }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu> -->
|
|
<div v-if="isCameraPermissionGranted && isMicrophonePermissionGranted" class="video-icons">
|
|
<v-btn @click="toggleCamera()" :class="isCameraDisabled ? 'video-icon-red' : 'video-icon-black'"
|
|
:color="camIconColor" :icon="camIcon" size="small" rounded="xl"></v-btn>
|
|
<v-btn @click="toggleMic()" class="ml-1"
|
|
:class="isMuted ? 'video-icon-red' : 'video-icon-black'" :color="micIconColor"
|
|
:icon="micIcon" size="small" rounded="xl"></v-btn>
|
|
</div>
|
|
<div class="text-center" :class="isCameraDisabled ? 'video-single-icon mb-1 pb-0 px-2' : ''">
|
|
<VImg v-if="isCameraDisabled" :src="videoCameraOff" height="50" width="55"
|
|
class="video-camera mb-1 mt-3" />
|
|
<div v-if="isCameraPermissionGranted">
|
|
<!-- <video :ref="!isCameraDisabled ? 'videoElement' : ''" autoplay
|
|
:style="{ display: !isCameraDisabled ? 'block' : 'none' }" :muted="isMuted"></video> -->
|
|
<video ref="videoElement" autoplay
|
|
:style="{ display: !isCameraDisabled ? 'block' : 'none' }" :muted="isMuted"></video>
|
|
</div>
|
|
<div v-if="!enableCamBtn">
|
|
<small v-if="!isCameraPermissionGranted && !isMicrophonePermissionGranted">Allow access to
|
|
your cam/mic by
|
|
clicking on blocked cam icon in address bar.</small>
|
|
</div>
|
|
<div v-if="enableCamBtn" class="text-center"
|
|
:class="enableCamBtn ? 'video-single-icon mb-1 pb-0 px-2' : ''">
|
|
<VImg v-if="enableCamBtn" :src="videoCameraOff" height="50" width="55"
|
|
class="video-camera mb-1 mt-3" />
|
|
<small>Your webcam isn't enabled yet.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<v-btn v-if="enableCamBtn" class=" d-grid w-100 waves-effect waves-light text-capitalize" color="error"
|
|
variant="flat" @click="checkPermissions()">
|
|
Enable Camera
|
|
</v-btn>
|
|
</VCard>
|
|
<!-- <v-btn class="btn btn-primary mt-2 d-grid w-100 waves-effect waves-light text-capitalize" color="primary"
|
|
variant="flat">
|
|
Pre-call Test
|
|
</v-btn> -->
|
|
</VCol>
|
|
<VCol cols="12" md="9">
|
|
<MeetingsDashboard></MeetingsDashboard>
|
|
</VCol>
|
|
|
|
</VRow>
|
|
</template>
|
|
<style>
|
|
.video-single-icon {
|
|
margin: 0 auto;
|
|
position: absolute;
|
|
top: calc(35% - 10px);
|
|
width: 100%;
|
|
}
|
|
|
|
.menu-btn {
|
|
position: absolute;
|
|
background-color: #0000009c !important;
|
|
left: 10px;
|
|
z-index: 999;
|
|
top: 5px;
|
|
}
|
|
|
|
.video-icons {
|
|
position: absolute;
|
|
right: 10px;
|
|
z-index: 9999;
|
|
top: 5px;
|
|
}
|
|
|
|
.video-icon-red {
|
|
background-color: red;
|
|
color: white !important;
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.video-icon-black {
|
|
background-color: #0000009c !important;
|
|
color: white !important;
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.video-camera {
|
|
display: block;
|
|
position: relative;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
video {
|
|
width: 100%;
|
|
height: auto;
|
|
}
|
|
</style>
|