Merge branch 'dev' of https://git.codelfi.com/TelemedPro/hgh_admin into dev
This commit is contained in:
commit
58837c4188
@ -52,4 +52,4 @@ export const ADMIN_LAB_KIT_UPDATE_API = MAIN_DOMAIN + "/api/admin/labkit-update/
|
||||
export const ADMIN_LAB_KIT_ADD_API = MAIN_DOMAIN + "/api/admin/labkit-list-create"
|
||||
export const ADMIN_LAB_KIT_DELETE_API = MAIN_DOMAIN + "/api/admin/labkit-delete/"
|
||||
|
||||
|
||||
export const ADMIN_PATIENT_DETAIL_API = MAIN_DOMAIN + "/api/admin/patient-full-detail/"
|
||||
|
@ -91,10 +91,10 @@ const headers = [
|
||||
key: 'list_sub_title',
|
||||
},
|
||||
|
||||
{
|
||||
title: 'ACTIONS',
|
||||
key: 'actions',
|
||||
},
|
||||
// {
|
||||
// title: 'ACTIONS',
|
||||
// key: 'actions',
|
||||
// },
|
||||
]
|
||||
|
||||
const resolveStatusVariant = status => {
|
||||
@ -377,7 +377,7 @@ onMounted(() => {
|
||||
<VRow>
|
||||
|
||||
<VCol cols="12" md="8" class="d-flex align-center">
|
||||
<VBtn color="primary" prepend-icon="ri-add-line" @click="addDialog = true">
|
||||
<VBtn color="primary" prepend-icon="ri-add-line" @click="addDialog = true" style="display: none;">
|
||||
New Medicine
|
||||
</VBtn>
|
||||
</VCol>
|
||||
@ -403,18 +403,18 @@ onMounted(() => {
|
||||
class="text-no-wrap"
|
||||
>
|
||||
<!-- full name -->
|
||||
<template #item.name="{ item }">
|
||||
<template #item.title="{ item }">
|
||||
<div class="d-flex align-center">
|
||||
<!-- avatar -->
|
||||
<VAvatar
|
||||
size="32"
|
||||
:color="item.avatar ? '' : 'primary'"
|
||||
:class="item.avatar ? '' : 'v-avatar-light-bg primary--text'"
|
||||
:variant="!item.avatar ? 'tonal' : undefined"
|
||||
:color="item.image_url ? '' : 'primary'"
|
||||
:class="item.image_url ? '' : 'v-avatar-light-bg primary--text'"
|
||||
:variant="!item.image_url ? 'tonal' : undefined"
|
||||
>
|
||||
<VImg
|
||||
v-if="item.avatar"
|
||||
:src="item.avatar"
|
||||
v-if="item.image_url"
|
||||
:src="item.image_url"
|
||||
/>
|
||||
<span
|
||||
v-else
|
||||
@ -423,7 +423,7 @@ onMounted(() => {
|
||||
</VAvatar>
|
||||
|
||||
<div class="d-flex flex-column ms-3">
|
||||
<span class="d-block font-weight-medium text-high-emphasis text-truncate">{{ item.name }}</span>
|
||||
<span class="d-block font-weight-medium text-high-emphasis text-truncate">{{ item.title }}</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
108
resources/js/pages/patients/NotesPanel.vue
Normal file
108
resources/js/pages/patients/NotesPanel.vue
Normal file
@ -0,0 +1,108 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const patientId = route.params.patient_id;
|
||||
const appointmentId = route.params.id;
|
||||
const notes = ref([]);
|
||||
const props = defineProps({
|
||||
notesData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
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, '-');
|
||||
};
|
||||
|
||||
const downloadFile = (fileUrl) => {
|
||||
const link = document.createElement('a');
|
||||
link.href = fileUrl;
|
||||
link.download = 'noteFile.png';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
|
||||
<VCard title="Notes">
|
||||
<VCardText>
|
||||
<VTimeline
|
||||
side="end"
|
||||
align="start"
|
||||
line-inset="8"
|
||||
truncate-line="both"
|
||||
density="compact"
|
||||
>
|
||||
|
||||
<!-- SECTION Timeline Item: Flight -->
|
||||
|
||||
<template v-for="(p_note, index) in props.notesData.patientNotes" :key="index" v-if="props.notesData.patientNotes.length>0">
|
||||
<VTimelineItem
|
||||
dot-color="primary"
|
||||
size="x-small"
|
||||
>
|
||||
<!-- 👉 Header -->
|
||||
<div class="d-flex justify-space-between align-center gap-2 flex-wrap">
|
||||
<span class="app-timeline-title">
|
||||
{{p_note.note}}
|
||||
</span>
|
||||
|
||||
<span class="app-timeline-meta">{{ formatDateDate(p_note.created_at) }}</span>
|
||||
<!-- <span></span> -->
|
||||
</div>
|
||||
|
||||
<!-- 👉 Content -->
|
||||
<div class="app-timeline-text mb-1">
|
||||
<span>{{ p_note.telemedPro.name }}</span>
|
||||
<VIcon
|
||||
size="20"
|
||||
icon="tabler-arrow-right"
|
||||
class="mx-2 flip-in-rtl"
|
||||
/>
|
||||
<!-- <span>Heathrow Airport, London</span> -->
|
||||
</div>
|
||||
|
||||
<!-- <p class="app-timeline-meta mb-2">
|
||||
6:30 AM
|
||||
</p> -->
|
||||
|
||||
<!-- <div class="app-timeline-text d-flex align-center gap-2">
|
||||
<div>
|
||||
<VImg
|
||||
:src="pdf"
|
||||
:width="22"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span>booking-card.pdf</span>
|
||||
</div> -->
|
||||
</VTimelineItem>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<!-- !SECTION -->
|
||||
|
||||
<!-- !SECTION -->
|
||||
</VTimeline>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</template>
|
202
resources/js/pages/patients/PatienTabOverview.vue
Normal file
202
resources/js/pages/patients/PatienTabOverview.vue
Normal file
@ -0,0 +1,202 @@
|
||||
<script setup>
|
||||
import moment from 'moment';
|
||||
import { onBeforeMount, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const editDialog = ref(false);
|
||||
const deleteDialog = ref(false);
|
||||
const search = ref('');
|
||||
const appointmentId = ref('');
|
||||
const defaultItem = ref({
|
||||
id: -1,
|
||||
avatar: '',
|
||||
name: '',
|
||||
email: '',
|
||||
dob: '',
|
||||
phone_no: '',
|
||||
});
|
||||
|
||||
const editedItem = ref({ ...defaultItem.value });
|
||||
const editedIndex = ref(-1);
|
||||
const patientMeetingList = ref([]);
|
||||
const isLoading = ref(false);
|
||||
|
||||
// Status options
|
||||
const selectedOptions = [
|
||||
{ text: 'Active', value: 1 },
|
||||
{ text: 'InActive', value: 2 },
|
||||
];
|
||||
|
||||
const refVForm = ref(null);
|
||||
|
||||
// Headers
|
||||
const headers = [
|
||||
// { title: 'Appointment Id', key: 'id' },
|
||||
{ title: 'Patient', key: 'patient_name' },
|
||||
// { key: 'appointment_date', sortable: false, title: 'Date' },
|
||||
{ key: 'start_time', title: 'Start Time' },
|
||||
{ key: 'end_time', title: 'End Time' },
|
||||
{ key: 'duration', title: 'Duration' },
|
||||
{ title: 'ACTIONS', key: 'actions' },
|
||||
];
|
||||
|
||||
// Utility functions
|
||||
function changeDateFormat(dateFormat) {
|
||||
if (dateFormat) {
|
||||
const [datePart, timePart] = dateFormat.split(' ');
|
||||
const [year, month, day] = datePart.split('-');
|
||||
const formattedDate = `${parseInt(month)}-${parseInt(day)}-${year}`;
|
||||
return `${formattedDate} ${timePart}`;
|
||||
}
|
||||
return dateFormat;
|
||||
}
|
||||
|
||||
function changeFormat(dateFormat) {
|
||||
const [year, month, day] = dateFormat.split('-');
|
||||
return `${parseInt(month)}-${parseInt(day)}-${year}`;
|
||||
}
|
||||
|
||||
function totalCallDuration(start_time, end_time) {
|
||||
const startMoment = moment(start_time);
|
||||
const endMoment = moment(end_time);
|
||||
const duration = moment.duration(endMoment.diff(startMoment));
|
||||
const hours = String(duration.hours()).padStart(2, '0');
|
||||
const minutes = String(duration.minutes()).padStart(2, '0');
|
||||
const seconds = String(duration.seconds()).padStart(2, '0');
|
||||
|
||||
if (hours === '00' && minutes === '00') {
|
||||
return `00:00:${seconds}`;
|
||||
} else if (hours === '00') {
|
||||
return `00:${minutes}:${seconds}`;
|
||||
} else {
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch and process the patient meeting list
|
||||
const getPatientMeetingList = async () => {
|
||||
store.dispatch('updateIsLoading', true);
|
||||
await store.dispatch('patientMeetingList', { id: route.params.id });
|
||||
store.dispatch('updateIsLoading', false);
|
||||
|
||||
let list = store.getters.getPatientMeetingList;
|
||||
patientMeetingList.value = list.map(history => ({
|
||||
...history,
|
||||
appointment_date: changeFormat(history.appointment_date),
|
||||
start_time: changeDateFormat(history.start_time),
|
||||
end_time: changeDateFormat(history.end_time),
|
||||
duration: totalCallDuration(history.start_time, history.end_time),
|
||||
}));
|
||||
console.log(list);
|
||||
};
|
||||
|
||||
// Lifecycle hooks
|
||||
onBeforeMount(() => {});
|
||||
onMounted(async () => {
|
||||
await getPatientMeetingList();
|
||||
|
||||
});
|
||||
onUnmounted(() => {});
|
||||
const historyDetail = (item, value) => {
|
||||
console.log('item',item.id ,value)
|
||||
if(value == 'notes')
|
||||
router.push('/admin/patient/meeting/notes/' + route.params.id + '/' + item.id);
|
||||
if(value == 'prescription')
|
||||
router.push('/admin/patient/meeting/prescription/' + route.params.id + '/' + item.id);
|
||||
}
|
||||
const menusVariant = [
|
||||
'primary'
|
||||
];
|
||||
const options = [
|
||||
{
|
||||
title: 'Notes',
|
||||
key: 'notes',
|
||||
},
|
||||
{
|
||||
title: 'Prescription',
|
||||
key: 'prescription',
|
||||
},
|
||||
|
||||
]
|
||||
const breadcrums = [
|
||||
{
|
||||
title: 'Patient',
|
||||
disabled: false,
|
||||
to: '/admin/patients',
|
||||
},
|
||||
{
|
||||
title: 'Meetings',
|
||||
disabled: false,
|
||||
}
|
||||
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" md="12">
|
||||
<v-card title="Meetings">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12" offset-md="8" md="4">
|
||||
<v-text-field
|
||||
v-model="search"
|
||||
label="Search"
|
||||
placeholder="Search ..."
|
||||
append-inner-icon="ri-search-line"
|
||||
single-line
|
||||
hide-details
|
||||
dense
|
||||
outlined
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="patientMeetingList"
|
||||
:search="search"
|
||||
:items-per-page="5"
|
||||
class="text-no-wrap"
|
||||
>
|
||||
<template #item.id="{ item }">{{ item.id }}</template>
|
||||
<template #item.duration="{ item }">{{ item.duration }}</template>
|
||||
<!-- Actions -->
|
||||
<template #item.actions="{ item }">
|
||||
<div class="demo-space-x">
|
||||
<VMenu
|
||||
v-for="menu in menusVariant"
|
||||
:key="menu"
|
||||
>
|
||||
<template #activator="{ props }">
|
||||
|
||||
<i class="ri-more-2-line cursor-pointer" style="font-size: 32px;" v-bind="props"></i>
|
||||
|
||||
</template>
|
||||
|
||||
<v-list>
|
||||
<v-list-item
|
||||
v-for="opt in options"
|
||||
:key="opt.value"
|
||||
@click="historyDetail(item, opt.key)"
|
||||
>
|
||||
{{ opt.title }}
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</VMenu>
|
||||
</div>
|
||||
<!-- <div class="d-flex gap-1">
|
||||
<VBtn class="text-capitalize text-white" @click="historyDetail(item)"> Detail
|
||||
</VBtn>
|
||||
</div> -->
|
||||
</template>
|
||||
</v-data-table>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
361
resources/js/pages/patients/PatientBioPanel.vue
Normal file
361
resources/js/pages/patients/PatientBioPanel.vue
Normal file
@ -0,0 +1,361 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
userData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const standardPlan = {
|
||||
plan: 'Standard',
|
||||
price: 99,
|
||||
benefits: [
|
||||
'10 Users',
|
||||
'Up to 10GB storage',
|
||||
'Basic Support',
|
||||
],
|
||||
}
|
||||
|
||||
const isUserInfoEditDialogVisible = ref(false)
|
||||
const isUpgradePlanDialogVisible = ref(false)
|
||||
|
||||
const resolveUserStatusVariant = stat => {
|
||||
if (stat === 'pending')
|
||||
return 'warning'
|
||||
if (stat === 'active')
|
||||
return 'success'
|
||||
if (stat === 'inactive')
|
||||
return 'secondary'
|
||||
|
||||
return 'primary'
|
||||
}
|
||||
|
||||
const resolveUserRoleVariant = role => {
|
||||
if (role === 'subscriber')
|
||||
return {
|
||||
color: 'primary',
|
||||
icon: 'ri-user-line',
|
||||
}
|
||||
if (role === 'author')
|
||||
return {
|
||||
color: 'warning',
|
||||
icon: 'ri-settings-2-line',
|
||||
}
|
||||
if (role === 'maintainer')
|
||||
return {
|
||||
color: 'success',
|
||||
icon: 'ri-database-2-line',
|
||||
}
|
||||
if (role === 'editor')
|
||||
return {
|
||||
color: 'info',
|
||||
icon: 'ri-pencil-line',
|
||||
}
|
||||
if (role === 'admin')
|
||||
return {
|
||||
color: 'error',
|
||||
icon: 'ri-server-line',
|
||||
}
|
||||
|
||||
return {
|
||||
color: 'primary',
|
||||
icon: 'ri-user-line',
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow>
|
||||
<!-- SECTION User Details -->
|
||||
<VCol cols="12">
|
||||
<VCard v-if="props.userData">
|
||||
<VCardText class="text-center pt-12 pb-6">
|
||||
<!-- 👉 Avatar -->
|
||||
<VAvatar
|
||||
rounded
|
||||
:size="120"
|
||||
:color="!props.userData.patient.avatar ? 'primary' : undefined"
|
||||
:variant="!props.userData.patient.avatar ? 'tonal' : undefined"
|
||||
>
|
||||
<VImg
|
||||
v-if="props.userData.patient.avatar"
|
||||
:src="props.userData.patient.avatar"
|
||||
/>
|
||||
<span
|
||||
v-else
|
||||
class="text-5xl font-weight-medium"
|
||||
>
|
||||
{{ avatarText(props.userData.patient.first_name) }}
|
||||
</span>
|
||||
</VAvatar>
|
||||
|
||||
<!-- 👉 User fullName -->
|
||||
<h5 class="text-h5 mt-4">
|
||||
{{ props.userData.patient.first_name }} {{ props.userData.patient.last_name }}
|
||||
</h5>
|
||||
|
||||
<!-- 👉 Role chip -->
|
||||
<VChip
|
||||
:color="resolveUserRoleVariant('Patient').color"
|
||||
size="small"
|
||||
class="text-capitalize mt-4"
|
||||
>
|
||||
Patient
|
||||
</VChip>
|
||||
</VCardText>
|
||||
|
||||
|
||||
|
||||
<!-- 👉 Details -->
|
||||
<VCardText class="pb-6">
|
||||
<h5 class="text-h5">
|
||||
Details
|
||||
</h5>
|
||||
|
||||
<VDivider class="my-4" />
|
||||
|
||||
<!-- 👉 User Details list -->
|
||||
<VList class="card-list">
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">
|
||||
Email:
|
||||
</span>
|
||||
<span class="text-body-1">{{ props.userData.patient.email }}</span>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">
|
||||
Address:
|
||||
</span>
|
||||
<span class="text-body-1">{{ props.userData.patient.address }}</span>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">
|
||||
City:
|
||||
</span>
|
||||
<span class="text-body-1">{{ props.userData.patient.city }}</span>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">
|
||||
State:
|
||||
</span>
|
||||
<span class="text-body-1">{{ props.userData.patient.state }}</span>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">
|
||||
Zip:
|
||||
</span>
|
||||
<span class="text-body-1">{{ props.userData.patient.zip_code }}</span>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">
|
||||
Status:
|
||||
</span>
|
||||
<VChip
|
||||
size="small"
|
||||
:color="resolveUserStatusVariant('Active')"
|
||||
class="text-capitalize"
|
||||
>
|
||||
Active
|
||||
</VChip>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">Role: </span>
|
||||
<span class="text-capitalize text-body-1">Patient</span>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
|
||||
|
||||
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">
|
||||
Contact:
|
||||
</span>
|
||||
<span class="text-body-1">{{ props.userData.patient.phone_no }}</span>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
|
||||
|
||||
<VListItem>
|
||||
<VListItemTitle class="text-sm">
|
||||
<span class="font-weight-medium">
|
||||
Country:
|
||||
</span>
|
||||
<span class="text-body-1">{{ props.userData.patient.country }}</span>
|
||||
</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardText>
|
||||
|
||||
<!-- 👉 Edit and Suspend button -->
|
||||
<VCardText class="d-flex justify-center">
|
||||
<VBtn
|
||||
variant="elevated"
|
||||
class="me-4"
|
||||
@click="isUserInfoEditDialogVisible = true"
|
||||
>
|
||||
Edit
|
||||
</VBtn>
|
||||
<VBtn
|
||||
variant="outlined"
|
||||
color="error"
|
||||
>
|
||||
Suspend
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
<!-- !SECTION -->
|
||||
|
||||
<!-- SECTION Current Plan -->
|
||||
<VCol cols="12" v-if="props.userData.plans[0]">
|
||||
<VCard
|
||||
flat
|
||||
class="current-plan"
|
||||
|
||||
>
|
||||
<VCardText class="d-flex">
|
||||
<!-- 👉 Standard Chip -->
|
||||
<VChip
|
||||
color="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ props.userData.plans[0].title }}
|
||||
</VChip>
|
||||
|
||||
<VSpacer />
|
||||
|
||||
<!-- 👉 Current Price -->
|
||||
<div class="d-flex align-center">
|
||||
<sup class="text-primary text-lg font-weight-medium"> {{ props.userData.plans[0].currency }}</sup>
|
||||
<h1 class="text-h1 text-primary">
|
||||
{{ props.userData.plans[0].price }}
|
||||
</h1>
|
||||
<sub class="mt-3"><h6 class="text-h6 font-weight-regular">month</h6></sub>
|
||||
</div>
|
||||
</VCardText>
|
||||
|
||||
<VCardText>
|
||||
<!-- 👉 Price Benefits -->
|
||||
<VList class="card-list">
|
||||
<VListItem
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<VIcon
|
||||
size="10"
|
||||
color="medium-emphasis"
|
||||
class="me-2"
|
||||
icon="ri-circle-fill"
|
||||
/>
|
||||
<div class="text-medium-emphasis">
|
||||
{{ props.userData.plans[0].list_one_title }}
|
||||
</div>
|
||||
</div>
|
||||
</VListItem>
|
||||
<VListItem
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<VIcon
|
||||
size="10"
|
||||
color="medium-emphasis"
|
||||
class="me-2"
|
||||
icon="ri-circle-fill"
|
||||
/>
|
||||
<div class="text-medium-emphasis">
|
||||
{{ props.userData.plans[0].list_sub_title }}
|
||||
</div>
|
||||
</div>
|
||||
</VListItem>
|
||||
|
||||
<VListItem
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<VIcon
|
||||
size="10"
|
||||
color="medium-emphasis"
|
||||
class="me-2"
|
||||
icon="ri-circle-fill"
|
||||
/>
|
||||
<div class="text-medium-emphasis">
|
||||
{{ props.userData.plans[0].list_two_title }}
|
||||
</div>
|
||||
</div>
|
||||
</VListItem>
|
||||
</VList>
|
||||
|
||||
<!-- 👉 Days -->
|
||||
<div class="my-6">
|
||||
<div class="d-flex mt-3 mb-2">
|
||||
<h6 class="text-h6 font-weight-medium">
|
||||
Days
|
||||
</h6>
|
||||
<VSpacer />
|
||||
<h6 class="text-h6 font-weight-medium">
|
||||
26 of 30 Days
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Progress -->
|
||||
<VProgressLinear
|
||||
rounded
|
||||
:model-value="86"
|
||||
height="8"
|
||||
color="primary"
|
||||
/>
|
||||
|
||||
<p class="text-sm mt-1">
|
||||
4 days remaining
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 👉 Upgrade Plan -->
|
||||
<VBtn
|
||||
block
|
||||
@click="isUpgradePlanDialogVisible = true"
|
||||
>
|
||||
Upgrade Plan
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
<!-- !SECTION -->
|
||||
</VRow>
|
||||
|
||||
<!-- 👉 Edit user info dialog -->
|
||||
<UserInfoEditDialog
|
||||
v-model:isDialogVisible="isUserInfoEditDialogVisible"
|
||||
:user-data="props.userData"
|
||||
/>
|
||||
|
||||
<!-- 👉 Upgrade plan dialog -->
|
||||
<UserUpgradePlanDialog v-model:isDialogVisible="isUpgradePlanDialogVisible" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-list {
|
||||
--v-card-list-gap: .5rem;
|
||||
}
|
||||
|
||||
.current-plan {
|
||||
border: 2px solid rgb(var(--v-theme-primary));
|
||||
}
|
||||
|
||||
.text-capitalize {
|
||||
text-transform: capitalize !important;
|
||||
}
|
||||
</style>
|
352
resources/js/pages/patients/PrescriptionPanel.vue
Normal file
352
resources/js/pages/patients/PrescriptionPanel.vue
Normal file
@ -0,0 +1,352 @@
|
||||
<script setup>
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
const store = useStore();
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const itemsPrescriptions = ref([]);
|
||||
const patientId = route.params.patient_id;
|
||||
const props = defineProps({
|
||||
prescriptionData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
const prescription = computed(async () => {
|
||||
console.log('computed=====')
|
||||
await getprescriptionList()
|
||||
|
||||
});
|
||||
|
||||
const getprescriptionList = async () => {
|
||||
|
||||
let prescriptions = props.prescriptionData.prescriptionData
|
||||
console.log("BeforeOverviewItem", prescriptions);
|
||||
// itemsPrescriptions.value = store.getters.getPrescriptionList
|
||||
for (let data of prescriptions) {
|
||||
let dataObject = {}
|
||||
dataObject.name = data.prescription.name
|
||||
dataObject.brand = data.prescription.brand
|
||||
dataObject.from = data.prescription.from
|
||||
dataObject.direction_quantity = data.prescription.direction_quantity
|
||||
dataObject.dosage = data.prescription.dosage
|
||||
dataObject.quantity = data.prescription.quantity
|
||||
dataObject.refill_quantity = data.prescription.refill_quantity
|
||||
dataObject.actions = ''
|
||||
dataObject.id = data.prescription.id
|
||||
dataObject.comments = data.comments
|
||||
dataObject.direction_one = data.direction_one
|
||||
dataObject.direction_two= data.direction_two
|
||||
dataObject.status = data.status
|
||||
|
||||
dataObject.date = formatDateDate(data.created_at)
|
||||
|
||||
itemsPrescriptions.value.push(dataObject)
|
||||
}
|
||||
console.log(itemsPrescriptions.value)
|
||||
itemsPrescriptions.value.sort((a, b) => {
|
||||
return b.id - a.id;
|
||||
});
|
||||
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, '-');
|
||||
};
|
||||
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 'success';
|
||||
case 'returned':
|
||||
return 'red';
|
||||
case 'results':
|
||||
return 'blue';
|
||||
default:
|
||||
return 'grey'; // Use Vuetify's grey color for any other status
|
||||
}
|
||||
};
|
||||
const resolveStatusVariant = status => {
|
||||
if (status === 1)
|
||||
return {
|
||||
color: 'primary',
|
||||
text: 'Current',
|
||||
}
|
||||
else if (status === 2)
|
||||
return {
|
||||
color: 'success',
|
||||
text: 'Professional',
|
||||
}
|
||||
else if (status === 3)
|
||||
return {
|
||||
color: 'error',
|
||||
text: 'Rejected',
|
||||
}
|
||||
else if (status === 4)
|
||||
return {
|
||||
color: 'warning',
|
||||
text: 'Resigned',
|
||||
}
|
||||
else
|
||||
return {
|
||||
color: 'info',
|
||||
text: 'Applied',
|
||||
}
|
||||
}
|
||||
const headers = [
|
||||
|
||||
{
|
||||
title: 'Name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: 'Date',
|
||||
key: 'date',
|
||||
},
|
||||
{
|
||||
title: 'Status',
|
||||
key: 'status',
|
||||
},
|
||||
]
|
||||
const prescriptionIndex = ref([]);
|
||||
const prescriptionItem = ref(-1)
|
||||
const prescriptionDialog = ref(false)
|
||||
const selectedItem = ref(null);
|
||||
const showDetail = item => {
|
||||
// console.log("id",item);
|
||||
prescriptionIndex.value = item
|
||||
selectedItem.value = item;
|
||||
// console.log("index",prescriptionIndex.value);
|
||||
// prescriptionItem.value = { ...item }
|
||||
prescriptionDialog.value = true
|
||||
}
|
||||
const close = () => {
|
||||
prescriptionDialog.value = false
|
||||
prescriptionIndex.value = -1
|
||||
prescriptionItem.value = { ...defaultItem.value }
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" md="12" v-if="itemsPrescriptions">
|
||||
<v-card title="Prescriptions" v-if="prescription">
|
||||
<VCardText >
|
||||
|
||||
</VCardText>
|
||||
<VDataTable
|
||||
:headers="headers"
|
||||
:items="itemsPrescriptions"
|
||||
:items-per-page="5"
|
||||
class="text-no-wrap"
|
||||
>
|
||||
|
||||
<!-- full name -->
|
||||
<!-- status -->
|
||||
<template #item.status="{ item }">
|
||||
<VChip
|
||||
:color="getStatusColor(item.status)"
|
||||
density="comfortable"
|
||||
>
|
||||
{{ getStatusColor(item.status) }}
|
||||
</VChip>
|
||||
</template>
|
||||
|
||||
<!-- Actions -->
|
||||
<template #item.name="{ item }">
|
||||
<router-link
|
||||
:to="{ name: 'admin-patient-profile', params: { id: item.id } }"
|
||||
class="text-high-emphasis "
|
||||
@click.prevent=showDetail(item)
|
||||
>
|
||||
{{ item.name }}
|
||||
</router-link>
|
||||
|
||||
</template>
|
||||
</VDataTable>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDialog
|
||||
v-model="prescriptionDialog"
|
||||
max-width="600px"
|
||||
>
|
||||
<VCard :title=prescriptionIndex.name>
|
||||
<DialogCloseBtn
|
||||
variant="text"
|
||||
size="default"
|
||||
@click="[prescriptionDialog = false,selectedItem = '']"
|
||||
/>
|
||||
<VCardText>
|
||||
<v-row class='mt-0'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Brand:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p>{{ prescriptionIndex.brand }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>From:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p>{{ prescriptionIndex.from }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Dosage:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p>{{ prescriptionIndex.dosage }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Quantity:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p>{{ prescriptionIndex.quantity }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Direction Quantity:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="8" sm="6">
|
||||
<p>{{ prescriptionIndex.direction_quantity }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Direction One:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="8" sm="6">
|
||||
<p>{{ prescriptionIndex.direction_one }} </p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Direction Two:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="8" sm="6">
|
||||
<p>{{ prescriptionIndex.direction_two }} </p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Refill Quantity:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="8" sm="6">
|
||||
<p>{{ prescriptionIndex.refill_quantity }}</p>
|
||||
</v-col>
|
||||
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Status:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="8" sm="6">
|
||||
<p v-if="prescriptionIndex.status == null" class="text-warning">Pending</p>
|
||||
<p v-else>{{ prescriptionIndex.status }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<VDivider></VDivider>
|
||||
<v-row class='mt-1 pb-0'>
|
||||
<v-col cols="12" md="4" sm="6">
|
||||
<p class='heading mb-0 text-right'><b>Comments:</b></p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="8" sm="8">
|
||||
<p>{{ prescriptionIndex.comments }} </p>
|
||||
</v-col>
|
||||
|
||||
</v-row>
|
||||
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
button.v-expansion-panel-title {
|
||||
background-color: #003152 !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
button.v-expansion-panel-title.bg-secondary {
|
||||
background-color: #003152 !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
button.v-expansion-panel-title {
|
||||
background-color: #003152 !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
span.v-expansion-panel-title__icon {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
// button.v-expansion-panel-title.bg-secondary {
|
||||
// background-color: rgba(var(--v-theme-primary), var(--v-activated-opacity)) !important;
|
||||
// }
|
||||
|
||||
// button.v-expansion-panel-title {
|
||||
// background-color: rgba(var(--v-theme-primary), var(--v-activated-opacity)) !important;
|
||||
// }
|
||||
|
||||
// button.v-expansion-panel-title.v-expansion-panel-title--active {
|
||||
// background-color: rgba(var(--v-theme-primary), var(--v-activated-opacity)) !important;
|
||||
// }
|
||||
|
||||
.v-expansion-panel {
|
||||
overflow: hidden;
|
||||
border-radius: 16px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 10%);
|
||||
margin-block-end: 10px;
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.details {
|
||||
position: relative;
|
||||
box-sizing: content-box;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 1em;
|
||||
background-color: #696cff;
|
||||
block-size: 0.85em;
|
||||
box-shadow: 0 0 3px rgba(67, 89, 113, 80%);
|
||||
color: #fff;
|
||||
content: "+";
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
font-weight: 500;
|
||||
inline-size: 0.85em;
|
||||
inset-block-start: 50%;
|
||||
inset-block-start: 0.7em;
|
||||
inset-inline-start: 50%;
|
||||
line-height: 0.9em;
|
||||
text-align: center;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
</style>
|
286
resources/js/pages/patients/UserTabOverview.vue
Normal file
286
resources/js/pages/patients/UserTabOverview.vue
Normal file
@ -0,0 +1,286 @@
|
||||
<script setup>
|
||||
import { useTheme } from 'vuetify'
|
||||
import UserInvoiceTable from './UserInvoiceTable.vue'
|
||||
import pdf from '@images/icons/project-icons/pdf.png'
|
||||
import avatar2 from '@images/avatars/avatar-2.png'
|
||||
import avatar3 from '@images/avatars/avatar-3.png'
|
||||
import avatar4 from '@images/avatars/avatar-4.png'
|
||||
import avatar5 from '@images/avatars/avatar-5.png'
|
||||
import figma from '@images/icons/project-icons/figma.png'
|
||||
import html5 from '@images/icons/project-icons/html5.png'
|
||||
import python from '@images/icons/project-icons/python.png'
|
||||
import react from '@images/icons/project-icons/react.png'
|
||||
import sketch from '@images/icons/project-icons/sketch.png'
|
||||
import vue from '@images/icons/project-icons/vue.png'
|
||||
import xamarin from '@images/icons/project-icons/xamarin.png'
|
||||
|
||||
const projectTableHeaders = [
|
||||
{
|
||||
title: 'PROJECT',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: 'TOTAL TASK',
|
||||
key: 'totalTask',
|
||||
},
|
||||
{
|
||||
title: 'PROGRESS',
|
||||
key: 'progress',
|
||||
},
|
||||
{
|
||||
title: 'HOURS',
|
||||
key: 'hours',
|
||||
},
|
||||
]
|
||||
|
||||
const { name } = useTheme()
|
||||
|
||||
const projects = [
|
||||
{
|
||||
logo: react,
|
||||
name: 'BGC eCommerce App',
|
||||
project: 'React Project',
|
||||
totalTask: '122/240',
|
||||
progress: 78,
|
||||
hours: '18:42',
|
||||
},
|
||||
{
|
||||
logo: figma,
|
||||
name: 'Falcon Logo Design',
|
||||
project: 'Figma Project',
|
||||
totalTask: '09/56',
|
||||
progress: 18,
|
||||
hours: '20:42',
|
||||
},
|
||||
{
|
||||
logo: vue,
|
||||
name: 'Dashboard Design',
|
||||
project: 'Vuejs Project',
|
||||
totalTask: '290/320',
|
||||
progress: 62,
|
||||
hours: '120:87',
|
||||
},
|
||||
{
|
||||
logo: xamarin,
|
||||
name: 'Foodista mobile app',
|
||||
project: 'Xamarin Project',
|
||||
totalTask: '290/320',
|
||||
progress: 8,
|
||||
hours: '120:87',
|
||||
},
|
||||
{
|
||||
logo: python,
|
||||
name: 'Dojo Email App',
|
||||
project: 'Python Project',
|
||||
totalTask: '120/186',
|
||||
progress: 49,
|
||||
hours: '230:10',
|
||||
},
|
||||
{
|
||||
logo: sketch,
|
||||
name: 'Blockchain Website',
|
||||
project: 'Sketch Project',
|
||||
totalTask: '99/109',
|
||||
progress: 92,
|
||||
hours: '342:41',
|
||||
},
|
||||
{
|
||||
logo: html5,
|
||||
name: 'Hoffman Website',
|
||||
project: 'HTML Project',
|
||||
totalTask: '98/110',
|
||||
progress: 88,
|
||||
hours: '12:45',
|
||||
},
|
||||
]
|
||||
|
||||
const resolveUserProgressVariant = progress => {
|
||||
if (progress <= 25)
|
||||
return 'error'
|
||||
if (progress > 25 && progress <= 50)
|
||||
return 'warning'
|
||||
if (progress > 50 && progress <= 75)
|
||||
return 'primary'
|
||||
if (progress > 75 && progress <= 100)
|
||||
return 'success'
|
||||
|
||||
return 'secondary'
|
||||
}
|
||||
|
||||
const search = ref('')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<VCard title="Project List">
|
||||
<template #append>
|
||||
<VTextField
|
||||
v-model="search"
|
||||
placeholder="Search Project"
|
||||
density="compact"
|
||||
style="inline-size: 10rem;"
|
||||
/>
|
||||
</template>
|
||||
<!-- 👉 User Project List Table -->
|
||||
|
||||
<!-- SECTION Datatable -->
|
||||
<VDataTable
|
||||
:search="search"
|
||||
:headers="projectTableHeaders"
|
||||
:items="projects"
|
||||
item-value="name"
|
||||
class="text-no-wrap rounded-0"
|
||||
>
|
||||
<!-- projects -->
|
||||
<template #item.name="{ item }">
|
||||
<div class="d-flex align-center">
|
||||
<VAvatar
|
||||
:size="34"
|
||||
class="me-3"
|
||||
:image="item.logo"
|
||||
/>
|
||||
<div>
|
||||
<h6 class="text-h6 mb-0">
|
||||
{{ item.name }}
|
||||
</h6>
|
||||
<p class="text-sm text-medium-emphasis mb-0">
|
||||
{{ item.project }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- total task -->
|
||||
<template #item.totalTask="{ item }">
|
||||
<div class="text-high-emphasis">
|
||||
{{ item.totalTask }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Progress -->
|
||||
<template #item.progress="{ item }">
|
||||
<div class="text-high-emphasis">
|
||||
{{ item.progress }}%
|
||||
</div>
|
||||
<VProgressLinear
|
||||
:height="6"
|
||||
:model-value="item.progress"
|
||||
rounded
|
||||
:color="resolveUserProgressVariant(item.progress)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- remove footer -->
|
||||
<!-- TODO refactor this after vuetify community gives answer -->
|
||||
<template #bottom />
|
||||
</VDataTable>
|
||||
<!-- !SECTION -->
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="12">
|
||||
<!-- 👉 Activity timeline -->
|
||||
<VCard title="User Activity Timeline">
|
||||
<VCardText>
|
||||
<VTimeline
|
||||
density="compact"
|
||||
align="start"
|
||||
truncate-line="both"
|
||||
:line-inset="8"
|
||||
class="v-timeline-density-compact"
|
||||
>
|
||||
<VTimelineItem
|
||||
dot-color="error"
|
||||
size="x-small"
|
||||
>
|
||||
<div class="d-flex justify-space-between align-center flex-wrap gap-2 mb-3">
|
||||
<span class="app-timeline-title">
|
||||
12 Invoices have been paid
|
||||
</span>
|
||||
<span class="app-timeline-meta">12 min ago</span>
|
||||
</div>
|
||||
|
||||
<p class="app-timeline-text mb-2">
|
||||
Invoices have been paid to the company
|
||||
</p>
|
||||
<div class="d-inline-flex align-center timeline-chip">
|
||||
<img
|
||||
:src="pdf"
|
||||
height="20"
|
||||
class="me-2"
|
||||
alt="img"
|
||||
>
|
||||
|
||||
<span class="app-timeline-text font-weight-medium">
|
||||
invoice.pdf
|
||||
</span>
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
|
||||
<VTimelineItem
|
||||
dot-color="primary"
|
||||
size="x-small"
|
||||
>
|
||||
<div class="d-flex justify-space-between align-center flex-wrap gap-2 mb-3">
|
||||
<span class="app-timeline-title">
|
||||
Client Meeting
|
||||
</span>
|
||||
<span class="app-timeline-meta">45 min ago</span>
|
||||
</div>
|
||||
|
||||
<p class="app-timeline-text mb-2">
|
||||
React Project meeting with john @10:15am
|
||||
</p>
|
||||
|
||||
<div class="d-flex align-center mt-3">
|
||||
<VAvatar
|
||||
size="32"
|
||||
class="me-2"
|
||||
:image="avatar2"
|
||||
/>
|
||||
<div>
|
||||
<p class="text-sm font-weight-medium mb-0">
|
||||
Lester McCarthy (Client)
|
||||
</p>
|
||||
<span class="text-sm">CEO of Kelly Group</span>
|
||||
</div>
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
|
||||
<VTimelineItem
|
||||
dot-color="info"
|
||||
size="x-small"
|
||||
>
|
||||
<div class="d-flex justify-space-between align-center flex-wrap gap-2 mb-3">
|
||||
<span class="app-timeline-title">
|
||||
Create a new project for client
|
||||
</span>
|
||||
<span class="app-timeline-meta">2 day ago</span>
|
||||
</div>
|
||||
|
||||
<p class="app-timeline-text mb-2">
|
||||
6 team members in a project
|
||||
</p>
|
||||
|
||||
<div class="v-avatar-group">
|
||||
<VAvatar
|
||||
v-for="avatar in [avatar2, avatar3, avatar4, avatar5]"
|
||||
:key="avatar"
|
||||
:image="avatar"
|
||||
/>
|
||||
<VAvatar :color="name === 'light' ? '#F0EFF0' : '#3F3B59'">
|
||||
<span class="text-high-emphasis">+3</span>
|
||||
</VAvatar>
|
||||
</div>
|
||||
</VTimelineItem>
|
||||
</VTimeline>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="12">
|
||||
<UserInvoiceTable />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</template>
|
114
resources/js/pages/patients/patient-profile.vue
Normal file
114
resources/js/pages/patients/patient-profile.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<script setup>
|
||||
import NotesPanel from '@/pages/patients/NotesPanel.vue'
|
||||
import PatienTabOverview from '@/pages/patients/PatienTabOverview.vue'
|
||||
import PatientBioPanel from '@/pages/patients/PatientBioPanel.vue'
|
||||
import PrescriptionPanel from '@/pages/patients/PrescriptionPanel.vue'
|
||||
|
||||
import UserTabNotifications from '@/views/apps/user/view/UserTabNotifications.vue'
|
||||
import { useStore } from 'vuex'
|
||||
const patientDtail = ref(null);
|
||||
|
||||
const store = useStore();
|
||||
const route = useRoute('apps-user-view-id')
|
||||
const userTab = ref(null)
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
icon: 'ri-group-line',
|
||||
title: 'Overview',
|
||||
},
|
||||
{
|
||||
icon: 'ri-lock-2-line',
|
||||
title: 'Notes',
|
||||
},
|
||||
{
|
||||
icon: 'ri-bookmark-line',
|
||||
title: 'Prescriptions',
|
||||
},
|
||||
// {
|
||||
// icon: 'ri-notification-4-line',
|
||||
// title: 'Notifications',
|
||||
// },
|
||||
// {
|
||||
// icon: 'ri-link-m',
|
||||
// title: 'Connections',
|
||||
// },
|
||||
]
|
||||
const getPatientDeatail = async () => {
|
||||
store.dispatch('updateIsLoading', true);
|
||||
await store.dispatch('patientDetial', { id: route.params.id });
|
||||
store.dispatch('updateIsLoading', false);
|
||||
|
||||
let list = store.getters.getPatientDetail;
|
||||
patientDtail.value=list
|
||||
console.log(list.patient);
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getPatientDeatail();
|
||||
|
||||
});
|
||||
//const { data: userData } = await useApi(`/apps/users/${ route.params.id }`)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow v-if="patientDtail">
|
||||
<VCol
|
||||
cols="12"
|
||||
md="5"
|
||||
lg="4"
|
||||
>
|
||||
<PatientBioPanel :user-data="patientDtail" />
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="7"
|
||||
lg="8"
|
||||
>
|
||||
<VTabs
|
||||
v-model="userTab"
|
||||
class="v-tabs-pill"
|
||||
>
|
||||
<VTab
|
||||
v-for="tab in tabs"
|
||||
:key="tab.icon"
|
||||
>
|
||||
<VIcon
|
||||
start
|
||||
:icon="tab.icon"
|
||||
/>
|
||||
<span>{{ tab.title }}</span>
|
||||
</VTab>
|
||||
</VTabs>
|
||||
|
||||
<VWindow
|
||||
v-model="userTab"
|
||||
class="mt-6 disable-tab-transition"
|
||||
:touch="false"
|
||||
>
|
||||
<VWindowItem>
|
||||
<PatienTabOverview :notes-data="patientDtail"/>
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem>
|
||||
<NotesPanel :notes-data="patientDtail"/>
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem>
|
||||
<PrescriptionPanel :prescription-data="patientDtail"/>
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem>
|
||||
<UserTabNotifications />
|
||||
</VWindowItem>
|
||||
|
||||
|
||||
</VWindow>
|
||||
</VCol>
|
||||
</VRow>
|
||||
<VCard v-else>
|
||||
<VCardTitle class="text-center">
|
||||
No User Found
|
||||
</VCardTitle>
|
||||
</VCard>
|
||||
</template>
|
@ -119,17 +119,17 @@ const headers = [
|
||||
key: 'phone_no',
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Lab Kit',
|
||||
key: 'labkit',
|
||||
},
|
||||
// {
|
||||
// title: 'Lab Kit',
|
||||
// key: 'labkit',
|
||||
// },
|
||||
|
||||
|
||||
|
||||
{
|
||||
title: 'ACTIONS',
|
||||
key: 'actions',
|
||||
},
|
||||
// {
|
||||
// title: 'ACTIONS',
|
||||
// key: 'actions',
|
||||
// },
|
||||
]
|
||||
|
||||
const resolveStatusVariant = status => {
|
||||
@ -448,7 +448,12 @@ const onStateChange = async(newvalue)=> {
|
||||
</VAvatar>
|
||||
|
||||
<div class="d-flex flex-column ms-3">
|
||||
<router-link
|
||||
:to="{ name: 'admin-patient-profile', params: { id: item.id } }"
|
||||
class="text-high-emphasis "
|
||||
>
|
||||
<span class="d-block font-weight-medium text-high-emphasis text-truncate">{{ item.name }}</span>
|
||||
</router-link>
|
||||
<small>{{ item.post }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
101
resources/js/pages/providers/provider-profile.vue
Normal file
101
resources/js/pages/providers/provider-profile.vue
Normal file
@ -0,0 +1,101 @@
|
||||
<script setup>
|
||||
import UserBioPanel from '@/views/apps/user/view/UserBioPanel.vue'
|
||||
import UserTabBillingsPlans from '@/views/apps/user/view/UserTabBillingsPlans.vue'
|
||||
import UserTabConnections from '@/views/apps/user/view/UserTabConnections.vue'
|
||||
import UserTabNotifications from '@/views/apps/user/view/UserTabNotifications.vue'
|
||||
import UserTabOverview from '@/views/apps/user/view/UserTabOverview.vue'
|
||||
import UserTabSecurity from '@/views/apps/user/view/UserTabSecurity.vue'
|
||||
|
||||
const route = useRoute('apps-user-view-id')
|
||||
const userTab = ref(null)
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
icon: 'ri-group-line',
|
||||
title: 'Overview',
|
||||
},
|
||||
{
|
||||
icon: 'ri-lock-2-line',
|
||||
title: 'Security',
|
||||
},
|
||||
{
|
||||
icon: 'ri-bookmark-line',
|
||||
title: 'Billing & Plan',
|
||||
},
|
||||
{
|
||||
icon: 'ri-notification-4-line',
|
||||
title: 'Notifications',
|
||||
},
|
||||
{
|
||||
icon: 'ri-link-m',
|
||||
title: 'Connections',
|
||||
},
|
||||
]
|
||||
|
||||
const { data: userData } = await useApi(`/apps/users/${ route.params.id }`)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VRow v-if="userData">
|
||||
<VCol
|
||||
cols="12"
|
||||
md="5"
|
||||
lg="4"
|
||||
>
|
||||
<UserBioPanel :user-data="userData" />
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="7"
|
||||
lg="8"
|
||||
>
|
||||
<VTabs
|
||||
v-model="userTab"
|
||||
class="v-tabs-pill"
|
||||
>
|
||||
<VTab
|
||||
v-for="tab in tabs"
|
||||
:key="tab.icon"
|
||||
>
|
||||
<VIcon
|
||||
start
|
||||
:icon="tab.icon"
|
||||
/>
|
||||
<span>{{ tab.title }}</span>
|
||||
</VTab>
|
||||
</VTabs>
|
||||
|
||||
<VWindow
|
||||
v-model="userTab"
|
||||
class="mt-6 disable-tab-transition"
|
||||
:touch="false"
|
||||
>
|
||||
<VWindowItem>
|
||||
<UserTabOverview />
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem>
|
||||
<UserTabSecurity />
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem>
|
||||
<UserTabBillingsPlans />
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem>
|
||||
<UserTabNotifications />
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem>
|
||||
<UserTabConnections />
|
||||
</VWindowItem>
|
||||
</VWindow>
|
||||
</VCol>
|
||||
</VRow>
|
||||
<VCard v-else>
|
||||
<VCardTitle class="text-center">
|
||||
No User Found
|
||||
</VCardTitle>
|
||||
</VCard>
|
||||
</template>
|
@ -74,10 +74,10 @@ const headers = [
|
||||
key: 'phone_no',
|
||||
},
|
||||
|
||||
{
|
||||
title: 'ACTIONS',
|
||||
key: 'actions',
|
||||
},
|
||||
// {
|
||||
// title: 'ACTIONS',
|
||||
// key: 'actions',
|
||||
// },
|
||||
]
|
||||
|
||||
const resolveStatusVariant = status => {
|
||||
@ -253,12 +253,14 @@ onMounted(() => {
|
||||
<IconBtn
|
||||
size="small"
|
||||
@click="editItem(item)"
|
||||
style="display: none;"
|
||||
>
|
||||
<VIcon icon="ri-pencil-line" />
|
||||
</IconBtn>
|
||||
<IconBtn
|
||||
size="small"
|
||||
@click="deleteItem(item)"
|
||||
style="display: none;"
|
||||
>
|
||||
<VIcon icon="ri-delete-bin-line" />
|
||||
</IconBtn>
|
||||
|
@ -112,6 +112,11 @@ export const routes = [
|
||||
path: '/admin/site-setting',
|
||||
name: 'admin-site-setting',
|
||||
component: () => import('@/views/pages/account-settings/WebsiteSettings.vue'),
|
||||
},
|
||||
{
|
||||
path: '/admin/patients/patient-profile/:id',
|
||||
name: 'admin-patient-profile',
|
||||
component: () => import('@/pages/patients/patient-profile.vue'),
|
||||
},
|
||||
{
|
||||
path: '/apps/email/filter/:filter',
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
ADMIN_LAB_KIT_LIST_API,
|
||||
ADMIN_LAB_KIT_UPDATE_API,
|
||||
ADMIN_LOGIN_DETAIL,
|
||||
ADMIN_PATIENT_DETAIL_API,
|
||||
ADMIN_UPDATE_PASSWORD,
|
||||
ADMIN_UPDATE_SITE_SETTING,
|
||||
APPOINTMENT_DETAILS_API,
|
||||
@ -61,12 +62,13 @@ export default createStore({
|
||||
showMessage: null,
|
||||
timeout: null,
|
||||
checkLoginExpire: false,
|
||||
labKitList:[]
|
||||
labKitList: [],
|
||||
patientDetail:null
|
||||
},
|
||||
mutations: {
|
||||
setLoading(state, payload) {
|
||||
console.log('payload');
|
||||
state.isLoading = payload
|
||||
state.isLoading = payload
|
||||
},
|
||||
setCheckLoginExpire(state, payload) {
|
||||
console.log('payload');
|
||||
@ -95,6 +97,10 @@ export default createStore({
|
||||
},
|
||||
setSubcriptions(state, payload) {
|
||||
state.subcriptions = payload
|
||||
},
|
||||
setPatientDetail(state, payload) {
|
||||
console.log('payload');
|
||||
state.patientDetail = payload
|
||||
},
|
||||
setPtientList(state, payload) {
|
||||
state.patientList = payload
|
||||
@ -960,6 +966,24 @@ export default createStore({
|
||||
console.error('Error:', error);
|
||||
});
|
||||
},
|
||||
async patientDetial({ commit }, payload) {
|
||||
commit('setLoading', true)
|
||||
|
||||
await axios.post(ADMIN_PATIENT_DETAIL_API+payload.id, {}, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${localStorage.getItem('admin_access_token')}`,
|
||||
}
|
||||
}) .then(response => {
|
||||
commit('setLoading', false)
|
||||
console.log('Response:', response.data);
|
||||
commit('setPatientDetail',response.data)
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
commit('setLoading', false)
|
||||
console.error('Error:', error);
|
||||
});
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
getIsLoading(state){
|
||||
@ -1031,5 +1055,8 @@ export default createStore({
|
||||
getLabKitList(state) {
|
||||
return state.labKitList
|
||||
},
|
||||
getPatientDetail(state) {
|
||||
return state.patientDetail
|
||||
},
|
||||
}
|
||||
})
|
||||
|
7
typed-router.d.ts
vendored
7
typed-router.d.ts
vendored
@ -156,9 +156,16 @@ declare module 'vue-router/auto/routes' {
|
||||
'pages-user-profile-tab': RouteRecordInfo<'pages-user-profile-tab', '/pages/user-profile/:tab', { tab: ParamValue<true> }, { tab: ParamValue<false> }>,
|
||||
'patients-meeting-details': RouteRecordInfo<'patients-meeting-details', '/patients/meeting-details', Record<never, never>, Record<never, never>>,
|
||||
'patients-meetings': RouteRecordInfo<'patients-meetings', '/patients/meetings', Record<never, never>, Record<never, never>>,
|
||||
'patients-notes-panel': RouteRecordInfo<'patients-notes-panel', '/patients/NotesPanel', Record<never, never>, Record<never, never>>,
|
||||
'patients-patient-profile': RouteRecordInfo<'patients-patient-profile', '/patients/patient-profile', Record<never, never>, Record<never, never>>,
|
||||
'patients-patien-tab-overview': RouteRecordInfo<'patients-patien-tab-overview', '/patients/PatienTabOverview', Record<never, never>, Record<never, never>>,
|
||||
'patients-patient-bio-panel': RouteRecordInfo<'patients-patient-bio-panel', '/patients/PatientBioPanel', Record<never, never>, Record<never, never>>,
|
||||
'patients-patients': RouteRecordInfo<'patients-patients', '/patients/patients', Record<never, never>, Record<never, never>>,
|
||||
'patients-prescription-panel': RouteRecordInfo<'patients-prescription-panel', '/patients/PrescriptionPanel', Record<never, never>, Record<never, never>>,
|
||||
'patients-user-tab-overview': RouteRecordInfo<'patients-user-tab-overview', '/patients/UserTabOverview', Record<never, never>, Record<never, never>>,
|
||||
'providers-meeting-details': RouteRecordInfo<'providers-meeting-details', '/providers/meeting-details', Record<never, never>, Record<never, never>>,
|
||||
'providers-meetings': RouteRecordInfo<'providers-meetings', '/providers/meetings', Record<never, never>, Record<never, never>>,
|
||||
'providers-provider-profile': RouteRecordInfo<'providers-provider-profile', '/providers/provider-profile', Record<never, never>, Record<never, never>>,
|
||||
'providers-providers': RouteRecordInfo<'providers-providers', '/providers/providers', Record<never, never>, Record<never, never>>,
|
||||
'register': RouteRecordInfo<'register', '/register', Record<never, never>, Record<never, never>>,
|
||||
'tables-data-table': RouteRecordInfo<'tables-data-table', '/tables/data-table', Record<never, never>, Record<never, never>>,
|
||||
|
Loading…
Reference in New Issue
Block a user