purityselect/resources/js/pages/overview.vue
2024-10-25 01:05:27 +05:00

874 lines
32 KiB
Vue

<script setup>
// import LabKit from '@/views/pages/overview/LabKit.vue';
import UpcomingAppiontment from "@/pages/patient/upcomingAppiontment.vue";
// import Prescription from '@/views/pages/patient/prescription.vue';
import Echo from "laravel-echo";
import { useRouter } from "vue-router";
const router = useRouter();
// import moment from 'moment';
import moment from "moment-timezone";
import Pusher from "pusher-js";
import { onMounted } from "vue";
import { useStore } from "vuex";
const store = useStore();
// import HeathCare from '@images/pages/healthcare-wellness-wellbeing-first-aid-box-word-graphic.jpg';
const isLoadingVisible = ref(false);
const showTimeBar = ref(false);
const planName = ref("");
const planAmount = ref("");
const loginuser = ref("");
const email = ref("");
const phoneNumber = ref("");
const shippingAddress = ref("");
const address = ref("");
const city = ref("");
const state = ref("");
const zip_code = ref("");
const country = ref("");
const dob = ref("");
const gender = ref("");
const height = ref("");
const weight = ref("");
const scheduleDate = ref("");
const scheduleTime = ref("");
const timeZone = ref("");
const timeDifference = ref();
const timeUntilMeeting = ref("");
const callEnd = ref("");
const patientId = ref("");
const appiontmentId = ref("");
const doctorName = ref("");
const itemsPrescriptions = ref([]);
const orders = ref([]);
const patientLabkit = ref([]);
const order_id = ref();
const notifications = ref([]);
const notes = ref([]);
const items = ref([]);
const status = ref();
const shippingAmmount = ref();
const appoinmentList = ref([]);
const upcomingAppoinmentList = ref([]);
const patientsStats = ref([]);
onMounted(async () => {
await fetchApiData();
await getPatientprescription();
await orderPtaientList();
await historyNotes();
store.dispatch("updateIsLoading", false);
});
const fetchApiData = async () => {
store.dispatch("updateIsLoading", true);
await store.dispatch("getPatientInfo");
await store.dispatch("getPlanInfo");
await store.dispatch("getPatientAppointment");
await store.dispatch("getDashboardStats");
patientsStats.value = store.getters.getPatientsStats;
// appendItemHistoryToStats(patientsStats.value);
// console.log("patientsStats", patientsStats.value);
appoinmentList.value = store.getters.getBookedAppointment;
upcomingAppoinmentList.value =
store.getters.getPatientUpcomingAppiontments.upcoming_appointments;
console.log("final", upcomingAppoinmentList.value);
loginuser.value =
store.getters.getPatient.first_name +
" " +
store.getters.getPatient.last_name;
let diffInMinutes = store.getters.getTimeDiff;
// console.log("diffInMinutes", diffInMinutes);
timeZone.value = store.getters.getBookedAppointment.timezone;
order_id.value = store.getters.getBookedAppointment.order_id;
doctorName.value = store.getters.getBookedAppointment.agent_name;
status.value = store.getters.getBookedAppointment.status;
appiontmentId.value = store.getters.getBookedAppointment.appiontmentId;
console.log("appiontmentId", store.getters.getBookedAppointment);
const time = store.getters.getBookedAppointment.appointment_time;
callEnd.value = store.getters.getBookedAppointment.end_time;
let dateString = store.getters.getPatient.dob;
let parts = dateString.split("-");
dob.value = `${parts[1]}-${parts[2]}-${parts[0]}`;
let appointmentDate = convertUtcDateTimeToLocal(
store.getters.getBookedAppointment.appointment_date,
store.getters.getBookedAppointment.appointment_time,
"date"
);
let appointmentTime = convertUtcDateTimeToLocal(
store.getters.getBookedAppointment.appointment_date,
store.getters.getBookedAppointment.appointment_time,
"time"
);
// console.log("appointmentOverview------", appointmentDate, appointmentTime);
scheduleDate.value = moment(appointmentDate, "YYYY-MM-DD").format(
"MMMM DD, YYYY"
);
scheduleTime.value = moment(appointmentTime, "HH:mm:ss").format("hh:mm A");
// console.log("scheduleDate------------------", scheduleDate.value, scheduleTime.value);
timeDifference.value = relativeTimeFromDate(
appointmentDate,
appointmentTime
);
// console.log("timeDifference--------", timeDifference.value);
items.value = store.getters.getBookedAppointment.items.items_list;
shippingAmmount.value = store.getters.getBookedAppointment.items.total;
// console.log("shippingAmmount", shippingAmmount.value);
};
const upComing = computed(() => {
appoinmentList.value = store.getters.getBookedAppointment;
return appoinmentList.value.map((appiontment) => ({
...appiontment,
timeZone: appiontment.timezone,
order_id: appiontment.order_id,
doctorName: appiontment.agent_name,
status: appiontment.status,
appiontmentId: appiontment.appiontmentId,
// console.log("appiontmentId", store.getters.getBookedAppointment);
time: appiontment.appointment_time,
callEnd: appiontment.end_time,
// let dateString = store.getters.getPatient.dob
// let parts = dateString.split("-");
// dob.value = `${parts[1]}-${parts[2]}-${parts[0]}`;
appointmentDate: convertUtcDateTimeToLocal(
appiontment.appointment_date,
appiontment.appointment_time,
"date"
),
appointmentTime: convertUtcDateTimeToLocal(
appiontment.appointment_date,
appiontment.appointment_time,
"time"
),
timeDifference: relativeTimeFromDate(appointmentDate, appointmentTime),
// scheduleDate.value = moment(appointmentDate, "YYYY-MM-DD").format("MMMM DD, YYYY"),
// scheduleTime.value = moment(appointmentTime, "HH:mm:ss").format("hh:mm A")
// items = store.getters.getBookedAppointment.items.items_list,
// shippingAmmount = store.getters.getBookedAppointment.items.total,
// console.log("shippingAmmount", shippingAmmount.value);
}));
});
const relativeTimeFromDate = (dateString, timeString) => {
// Combine the date and time into a full datetime, treated as local time
const eventDateTime = new Date(dateString + "T" + timeString);
// Get the current date and time
const now = new Date();
// Calculate the difference in milliseconds between the event time and now
const diffMs = eventDateTime - now;
// Check if the event time is in the past and log it to the console if it is
if (diffMs > 0) {
showTimeBar.value = true;
console.log("The event time is in the past.");
}
// Convert the difference to an absolute value
const absDiffMs = Math.abs(diffMs);
// Calculate differences in days, hours, and minutes
const minutes = Math.floor(absDiffMs / 60000) % 60;
const hours = Math.floor(absDiffMs / 3600000) % 24;
const days = Math.floor(absDiffMs / 86400000);
// Determine the appropriate suffix based on whether the date is in the future or past
const suffix = diffMs < 0 ? " ago" : " left";
// Result formulation based on the above logic
if (days > 0) {
return `${days} day${days > 1 ? "s" : ""}${suffix}`;
} else {
// Compose hours and minutes
let result = [];
if (hours > 0) {
result.push(`${hours} hour${hours > 1 ? "s" : ""}`);
}
if (minutes > 0) {
result.push(`${minutes} minute${minutes > 1 ? "s" : ""}`);
}
if (result.length === 0) {
return "just now";
}
return result.join(" ") + suffix;
}
};
const historyNotes = async () => {
// console.log('...........', patientId, appointmentId);
await store.dispatch("patientsShippingActivity");
// notes.value = store.getters.getPatientNotes;
notifications.value =
store.getters.getPatientsShippingActivity.item_history;
console.log("notifications", notifications.value);
};
const orderPtaientList = async () => {
await store.dispatch("orderPtaientList");
orders.value = store.getters.getPatientOrderList;
console.log("orders Test", orders.value);
// await store.dispatch("getPatientLabKit");
// patientLabkit.value = store.getters.getPatientLabKit;
store.dispatch("updateIsLoading", false);
};
const convertUtcDateTimeToLocal = (utcDate, utcTime, type) => {
const utcDateTime = `${utcDate}T${utcTime}Z`; // Use Z to denote UTC timezone explicitly
const momentObj = moment.utc(utcDateTime).local(); // Convert UTC to local time
if (type === "date") {
return momentObj.format("YYYY-MM-DD"); // Return local date
} else if (type === "time") {
return momentObj.format("HH:mm:ss"); // Return local time
} else {
throw new Error("Invalid type specified. Use 'date' or 'time'.");
}
};
const getPatientprescription = async () => {
// await store.dispatch('getPatientPrescriptions')
// itemsPrescriptions.value = store.getters.getPrescription
await store.dispatch("getPatientPrescriptionsByID", {
appointment_id: appiontmentId.value,
});
let prescriptions = store.getters.getPrescriptionList;
if (prescriptions) {
// itemsPrescriptions.value = store.getters.getPrescriptionList
for (let data of prescriptions) {
let dataObject = {};
dataObject.brand = data.brand;
dataObject.direction_one = data.direction_one;
dataObject.direction_quantity = data.direction_quantity;
dataObject.direction_two = data.direction_two;
dataObject.date = formatDateDate(data.created_at);
dataObject.dosage = data.dosage;
dataObject.from = data.from;
dataObject.name = data.name;
dataObject.quantity = data.quantity;
dataObject.refill_quantity = data.refill_quantity;
dataObject.status = data.status;
dataObject.comments = data.comments;
itemsPrescriptions.value.push(dataObject);
}
itemsPrescriptions.value.sort((a, b) => {
return b.id - a.id;
});
} else {
itemsPrescriptions.value = "";
}
console.log("OverviewItem", itemsPrescriptions.value);
};
const formatDateDate = (date) => {
const messageDate = new Date(date);
const options = {
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
};
return messageDate.toLocaleDateString("en-US", options).replace(/\//g, "-");
};
onMounted(() => {
store.dispatch("updateIsLoading", true);
window.Pusher = Pusher;
const key = "bc8bffbbbc49cfa39818";
const cluster = "mt1";
let echo = new Echo({
broadcaster: "pusher",
key: key,
cluster: cluster,
forceTLS: true,
auth: {
headers: {
Authorization: "Bearer " + localStorage.getItem("access_token"),
},
},
});
echo.private(
"patient-end-call-" + localStorage.getItem("patient_id")
).listen("AppointmentCallEnded", async (e) => {
console.log("OverviewAppointmentCallEnded", e);
fetchApiData();
});
store.dispatch("updateIsLoading", false);
});
const getStatusColor = (status) => {
switch (status) {
case "pending":
return "warning"; // Use Vuetify's warning color (typically yellow)
case "shipped":
return "#45B8AC"; // Use Vuetify's primary color (typically blue)
case "delivered":
return "green";
case "returned":
return "red";
case "results":
return "blue";
default:
return "grey"; // Use Vuetify's grey color for any other status
}
};
const desserts = [
{
dessert: "Blood Test",
calories: "pending",
},
{
dessert: "Cancer",
calories: "pending",
},
];
const viewOrder = (orderId) => {
router.push({ name: "order-detail", params: { id: orderId } });
};
const formatDate = (date) => {
const messageDate = new Date(date);
const options = {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric", // Change from '2-digit' to 'numeric'
minute: "2-digit",
hour12: true, // Add hour12: true to get 12-hour format with AM/PM
};
const formattedDate = messageDate
.toLocaleString("en-US", options)
.replace(/\//g, "-")
.replace(",", ""); // Remove the comma
return `${formattedDate} `;
};
const formatCurrency = (amount) => {
let formattedAmount = amount.toString();
// Remove '.00' if present
if (formattedAmount.includes(".00")) {
formattedAmount = formattedAmount.replace(".00", "");
}
// Split into parts for integer and decimal
let parts = formattedAmount.split(".");
// Format integer part with commas
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// Return formatted number
return parts.join(".");
};
const headers = [
{
title: "#Order",
key: "id",
},
{
title: "Date",
key: "updated_at",
},
{
title: "Price",
key: "total_amount",
},
{
title: "status",
key: "status",
},
];
const historyDetail = (history) => {
console.log("history", history.id);
// router.push("/patient/complete-appintment-detail/" + history.id);
router.push("/order-detail/" + history.id);
};
</script>
<template>
<VContainer class="px-0">
<VDialog
v-model="store.getters.getIsLoading"
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>
<!-- <VAlert color="rgb(var(--v-theme-yellow))" text-white v-if="showTimeBar">
<span>
<p class="text-white mb-0"><b>Remaining Time: </b> &nbsp; {{ timeDifference }}</p>
</span>
</VAlert> -->
<!-- <VAlert type="success" variant="outlined">Password Has been set
</VAlert> -->
<h3 class="text-center mt-3"></h3>
<VRow class="match-height">
<!-- 👉 Congratulation John -->
<!-- 👉 Ecommerce Transition -->
<VCol cols="12" md="7" lg="12">
<VCard>
<VCardTitle class="pb-0"
><b> Welcome {{ loginuser }},</b>
</VCardTitle>
<VCardText class="m-0">
<p class="mt-0">
Here you'll find your order, Appointments, and
subcriptions from HGH.
</p>
</VCardText>
<VCardText class="pt-6">
<VRow class="">
<VCol cols="6" md="3">
<div class="d-flex align-center gap-4">
<VAvatar
color="info"
variant="tonal"
size="42"
>
<VIcon icon="tabler-chart-pie-2" />
</VAvatar>
<div class="d-flex flex-column">
<span
class="text-h5 font-weight-medium"
>{{
patientsStats.total_meetings
}}</span
>
<span class="text-sm"> Completed </span>
</div>
</div>
</VCol>
<VCol cols="6" md="3">
<div class="d-flex align-center gap-4">
<VAvatar
color="primary"
variant="tonal"
size="42"
>
<VIcon icon="tabler-chart-pie-2" />
</VAvatar>
<div class="d-flex flex-column">
<span
class="text-h5 font-weight-medium"
>{{
patientsStats.upcoming_meetings
}}</span
>
<span class="text-sm"> Upcoming </span>
</div>
</div>
</VCol>
<VCol cols="6" md="3">
<div class="d-flex align-center gap-4">
<VAvatar
color="error"
variant="tonal"
size="42"
>
<VIcon icon="tabler-shopping-cart" />
</VAvatar>
<div class="d-flex flex-column">
<span
class="text-h5 font-weight-medium"
>{{
patientsStats.total_orders
}}</span
>
<span class="text-sm"> Orders </span>
</div>
</div>
</VCol>
<VCol cols="6" md="3">
<div class="d-flex align-center gap-4">
<VAvatar
color="success"
variant="tonal"
size="42"
>
<VIcon icon="tabler-currency-dollar" />
</VAvatar>
<div class="d-flex flex-column">
<span
class="text-h5 font-weight-medium"
>{{
patientsStats.total_subscription
}}</span
>
<span class="text-sm">
Subscription
</span>
</div>
</div>
</VCol>
</VRow>
</VCardText>
<!-- </VCardText>-->
</VCard>
</VCol>
</VRow>
<VRow>
<VCol cols="12" md="6">
<!-- <VCardTitle class="text-wrap" color="errors">Lab Kit
<RouterLink class="text-primary" to="/labs">
<small style="font-size: 12px; font-weight: normal;">(see all)</small>
</RouterLink>
</VCardTitle>
<LabKit :time="scheduleTime" :timezone="timeZone" :timeDiff="timeDifference" /> -->
<VCardTitle class="text-wrap"
><b>Upcoming Appointment</b>
<RouterLink class="text-primary" to="/complete">
<small style="font-size: 12px; font-weight: normal">
(see all)
</small>
</RouterLink>
</VCardTitle>
<!-- <UpcomingAppiontment /> -->
<UpcomingAppiontment
:upcommingAppiontmetns="upcomingAppoinmentList"
:iscallEnd="callEnd"
:orderid="order_id"
:date="scheduleDate"
:time="scheduleTime"
:timezone="timeZone"
:isStatus="status"
:timeDiff="timeDifference"
:isShippmentAmmount="shippingAmmount"
:showShipment="false"
color="rgb(var(--v-theme-yellow))"
:isItem="items"
/>
</VCol>
<VCol cols="12" md="6">
<VCardTitle class="text-wrap"
><b>Orders</b>
<RouterLink class="text-primary" to="/orders-list">
<small style="font-size: 12px; font-weight: normal">
(see all)
</small>
</RouterLink>
</VCardTitle>
<template v-if="items && items.length > 0">
<VCard
class="rounded-5"
style="
min-height: 150px;
overflow-y: scroll;
overflow: hidden;
border-radius: 10px;
"
>
<VDataTable
:headers="headers"
:items="orders"
item-value="id"
class="text-no-wrap"
>
<!-- <template #item.title="{ item }">
<div class="d-flex gap-x-3">
<VAvatar size="34" variant="tonal" :image="item.image_url" rounded />
<div class="d-flex flex-column align-center">
<h6 style="margin-bottom: 0px;">
{{ item.title }}
</h6>
<span class="text-sm text-start align-self-start">
{{ item.list_sub_title }}
</span>
</div>
</div>
</template> -->
<template #item.id="{ item }">
<span
@click="historyDetail(item)"
style="cursor: pointer"
><b> {{ item.id }} </b></span
>
</template>
<template #item.total_amount="{ item }">
<span>
<b
>${{
formatCurrency(item.total_amount)
}}
</b></span
>
</template>
<template #item.updated_at="{ item }">
<span>{{ formatDate(item.updated_at) }}</span>
</template>
<template #item.status="{ item }">
<span>
<VChip
variant="tonal"
:color="getStatusColor(item.status)"
size="small"
>
{{ item.status }}
</VChip>
</span>
</template>
<template #bottom />
</VDataTable>
<!-- <VTable class="text-no-wrap">
<thead>
<tr>
<th class="text-uppercase">
<b>Order ID</b>
</th>
<th class="text-uppercase">
<b>Date</b>
</th>
<th class="text-uppercase">
<b>Amount</b>
</th>
<th class="text-uppercase text-center">
<b>Status</b>
</th>
</tr>
</thead>
<tbody>
<tr v-for=" order in orders " :key="order">
<td>
<div @click="viewOrder(order.id)">{{ order.id }} </div>
</td>
<td class="text-center">
{{ formatDate(order.updated_at) }}
</td>
<td class="text-center">
${{ formatCurrency(order.total_amount) }}
</td>
<td class="text-center">
<v-chip x-small class="mr-2" outlined>{{ order.status }} </v-chip>
</td>
</tr>
</tbody>
</VTable>
<VDivider class="m-0" /> -->
</VCard>
</template>
<template v-else>
<VAlert border="start" color="rgb(var(--v-theme-yellow))">
<div class="text-center">No data found</div>
</VAlert>
</template>
<!-- <VCardTitle class="pt-3">
<b>
Lab Kits
</b>
</VCardTitle>
<template v-if="patientLabkit && patientLabkit.length > 0">
<VCard class="rounded-5"
style="min-height:150px; overflow-y:scroll; overflow: hidden; border-radius: 10px; ">
<VTable class="text-no-wrap">
<thead>
<tr>
<th class="text-uppercase">
<b>Name</b>
</th>
<th class="text-uppercase text-center">
<b>Status</b>
</th>
</tr>
</thead>
<tbody>
<tr v-for=" item in patientLabkit " :key="item.id">
<td>
{{ item.name }}
</td>
<td class="text-center">
<VChip variant="tonal" :color="getStatusColor(item.status)" size="small">
{{ item.status }}
</VChip>
</td>
</tr>
</tbody>
</VTable>
</VCard>
</template>
<template v-else>
<VAlert border="start" color="rgb(var(--v-theme-yellow))" variant="tonal">
<div class="text-center">No data found</div>
</VAlert>
</template> -->
<!-- <VTimeline truncate-line="both" align="start" side="end" line-inset="10" line-color="primary"
density="compact" class="v-timeline-density-compact">
<template v-if="historyNotes">
<VTimelineItem dot-color="primary" size="x-small" v-for="(p_note, index) of notes" :key="index">
<div class="d-flex justify-space-between align-center mb-3">
<span class="app-timeline-title">{{ p_note.note }}</span>
<span class="app-timeline-meta">{{ p_note.date }}</span>
</div>
<VDivider />
</VTimelineItem>
</template>
<template v-else>
<VCard>
<VAlert border="start" color="rgb(var(--v-theme-yellow))" variant="tonal">
<div class="text-center">No data found</div>
</VAlert>
</VCard>
</template>
</VTimeline> -->
<!-- </VCardText> -->
<!-- </VCard> -->
<!-- <template v-else>
<VCard>
<VAlert border="start" color="rgb(var(--v-theme-yellow))" variant="tonal">
<div class="text-center">No data found</div>
</VAlert>
</VCard>
</template> -->
</VCol>
</VRow>
</VContainer>
</template>
<style lang="scss">
button.v-expansion-panel-title {
background-color: rgb(var(--v-theme-yellow)) !important;
color: #fff;
}
button.v-expansion-panel-title.bg-secondary {
background-color: rgb(var(--v-theme-yellow)) !important;
color: #fff;
}
button.v-expansion-panel-title {
background-color: rgb(var(--v-theme-yellow)) !important;
color: #fff;
}
button.v-expansion-panel-title.v-expansion-panel-title--active {
background-color: rgb(var(--v-theme-yellow)) !important;
color: #fff;
}
span.v-expansion-panel-title__icon {
color: #fff;
display: none !important;
}
.v-expansion-panel {
background-color: #fff;
border-radius: 10px;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
margin-bottom: 10px;
overflow: hidden;
transition: box-shadow 0.3s ease;
}
.v-expansion-panel:hover {
box-shadow: 0px 6px 16px rgba(0, 0, 0, 0.15);
}
.v-expansion-panel-title {
padding: 15px;
font-size: 13px;
font-weight: 600;
color: #333;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
transition: background-color 0.3s ease, color 0.3s ease;
}
.v-expansion-panel-title.pt-0 {
padding-top: 0;
}
// .v-expansion-panel-title:hover {
// background-color: #f9f9f9;
// color: #222;
// }
.v-expansion-panel-title .mdi {
font-size: 20px;
color: #666;
transition: transform 0.3s ease, color 0.3s ease;
}
.v-expansion-panel-title.v-expansion-panel-title--active .mdi {
transform: rotate(180deg);
color: #222;
}
.v-expansion-panel-text {
padding: 10px 15px;
font-size: 13px;
color: #555;
border-top: 1px solid #eee;
}
.v-expansion-panel-text .d-flex {
margin-bottom: 24px;
}
.v-expansion-panel-text .d-flex > div {
flex: 1;
}
.v-expansion-panel-text p {
margin-bottom: 16px;
font-size: 14px;
}
.v-expansion-panel-text h3 {
font-size: 20px;
font-weight: 600;
margin-bottom: 16px;
color: #333;
}
.bg-primary {
background-color: rgb(var(--v-theme-yellow-theme-button)) !important;
}
</style>