feat: Implement Fast Request feature with file upload and request management
This commit is contained in:
@@ -1,11 +1,42 @@
|
||||
<script setup>
|
||||
import ClientLayout from '../../../layouts/ClientLayout.vue'
|
||||
import ClientLayout from '../../../layouts/ClientLayout.vue';
|
||||
import TableGeneric from '../../../components/ui/TableGeneric.vue';
|
||||
import UiCard from '../../../components/ui/UiCard.vue';
|
||||
import EyeSvg from '../../../components/svg/eye.svg';
|
||||
import { Link } from '@inertiajs/inertia-vue3';
|
||||
import { caseColumns } from '../../../data/casesTableColumns';
|
||||
|
||||
defineProps({
|
||||
cases: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ClientLayout>
|
||||
<h1 class="text-2xl font-bold">
|
||||
Cases
|
||||
</h1>
|
||||
<UiCard title="لیست کیسها" variant="default">
|
||||
<TableGeneric
|
||||
class="bg-white !rounded-2xl"
|
||||
:data="cases.data"
|
||||
customStyle="!text-[11px] !font-normal"
|
||||
:searchable="false"
|
||||
:columns="caseColumns"
|
||||
:selectable="false"
|
||||
:pagination="cases.meta"
|
||||
:model-value="[]"
|
||||
>
|
||||
<template #column-actions="{ data }">
|
||||
<div class="flex items-center justify-end">
|
||||
<Link :href="`/dashboard/cases/${data.id}`"
|
||||
class="text-primary-500 bg-complement-100 flex items-center justify-end p-1.5 rounded-md"
|
||||
>
|
||||
<EyeSvg class="w-4 h-4 text-primary-500" />
|
||||
</Link>
|
||||
</div>
|
||||
</template>
|
||||
</TableGeneric>
|
||||
</UiCard>
|
||||
</ClientLayout>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,8 @@ import { ref } from 'vue';
|
||||
import { Link } from '@inertiajs/inertia-vue3';
|
||||
import FastRequestModal from '../../components/dashboard/FastRequestModal.vue';
|
||||
import { useFastRequestStore } from '../../store/FastRequest';
|
||||
import { modalities } from '../../data/fastRequestOptions';
|
||||
import { caseColumns } from '../../data/casesTableColumns';
|
||||
const fastRequestStore = useFastRequestStore();
|
||||
|
||||
const fastRequestModalVisible = ref(false);
|
||||
@@ -24,90 +26,12 @@ defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
cases: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const data = ref([
|
||||
{
|
||||
id: 1,
|
||||
file_number: '1234567890',
|
||||
status: 'مشاهده نشد',
|
||||
request_type: 'CT',
|
||||
requester: 'محراب اسماعیلنیا',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'اتمام فرصت رسیدگی'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
file_number: '1234567891',
|
||||
status: 'مشاهده نشد',
|
||||
request_type: 'CT',
|
||||
requester: 'رضا گلیان',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: '۵۳ دقیقه'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
file_number: '1234567892',
|
||||
status: 'مشاهده نشد',
|
||||
request_type: 'MRI',
|
||||
requester: 'دکتر مریم مهدیپور',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۳۲ ساعت'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
file_number: '1234567893',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'دکتر مریم مهدیپور',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۲۴ ساعت'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
file_number: '1234567894',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'نام شخص و یا پزشک',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۵ ساعت'
|
||||
}
|
||||
])
|
||||
|
||||
const columns = ref([
|
||||
{
|
||||
title: 'شماره پرونده',
|
||||
key: 'file_number'
|
||||
},
|
||||
{
|
||||
title: 'وضعیت',
|
||||
key: 'status'
|
||||
},
|
||||
{
|
||||
title: 'نوع درخواست',
|
||||
key: 'request_type'
|
||||
},
|
||||
{
|
||||
title: 'درخواستکننده',
|
||||
key: 'requester'
|
||||
},
|
||||
{
|
||||
title: 'تاریخ ثبت',
|
||||
key: 'registration_date'
|
||||
},
|
||||
{
|
||||
title: 'فرصت رسیدگی',
|
||||
key: 'processing_deadline'
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
key: 'actions',
|
||||
width: 80,
|
||||
style: 'grid grid-cols-1',
|
||||
slot: true,
|
||||
}
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -116,27 +40,31 @@ const columns = ref([
|
||||
<UiCard title="ثبت آنی درخواست جدید" variant="default" class="mt-4">
|
||||
<p class="w-full flex items-center justify-start font-[400] text-[11px]">فقط چند قدم ساده برای ثبت درخواست کافیه.</p>
|
||||
<div class="w-full h-[179px] grid grid-cols-5 gap-3 justify-start pt-[10px]">
|
||||
<RequestCard title="CT Scan" icon="ct-scan" severity="primary" @click="openFastRequestModal('ct-scan')"/>
|
||||
<RequestCard title="MRI" icon="mri" severity="primary" @click="openFastRequestModal('mri')"/>
|
||||
<RequestCard title="سونوگرافی" icon="sonography" severity="primary" @click="openFastRequestModal('sonography')"/>
|
||||
<RequestCard title="اکوکاردیوگرافی" icon="echo" severity="primary" @click="openFastRequestModal('echo')"/>
|
||||
<RequestCard title="رادیولوژی" icon="radiology" severity="primary" @click="openFastRequestModal('radiology')"/>
|
||||
<RequestCard
|
||||
v-for="modality in modalities"
|
||||
:key="modality.code"
|
||||
:value="modality.code"
|
||||
:title="modality.title"
|
||||
:icon="modality.icon"
|
||||
severity="primary"
|
||||
@click="openFastRequestModal(modality.code)"
|
||||
/>
|
||||
</div>
|
||||
</UiCard>
|
||||
<UiCard title="آخرین کیسهای در انتظار بررسی" variant="default" class="mt-4">
|
||||
<TableGeneric
|
||||
class="bg-white !rounded-2xl"
|
||||
:data="data"
|
||||
:data="cases.data"
|
||||
customStyle="!text-[11px] !font-normal"
|
||||
:searchable="false"
|
||||
:columns="columns"
|
||||
:columns="caseColumns"
|
||||
:selectable="false"
|
||||
:pagination="null"
|
||||
:model-value="[]"
|
||||
>
|
||||
<template #column-actions="{ data }" class="">
|
||||
<div class="flex items-center justify-end">
|
||||
<Link to="/dashboard/doctor/cases/1"
|
||||
<Link :href="`/dashboard/cases/${data.id}`"
|
||||
class="text-primary-500 bg-complement-100 flex items-center justify-end p-1.5 rounded-md"
|
||||
>
|
||||
<EyeSvg class="w-4 h-4 text-primary-500" />
|
||||
|
||||
@@ -4,157 +4,17 @@ import UiCard from '../../../components/ui/UiCard.vue'
|
||||
import TableGeneric from '../../../components/ui/TableGeneric.vue'
|
||||
import EyeSvg from '../../../components/svg/eye.svg'
|
||||
import { Link } from '@inertiajs/inertia-vue3'
|
||||
import { ref } from 'vue'
|
||||
import { useDocumentStore } from '../../../store/Document'
|
||||
import { caseColumns } from '../../../data/casesTableColumns'
|
||||
|
||||
const documentStore = useDocumentStore();
|
||||
|
||||
const selectedItems = ref([])
|
||||
|
||||
const data = ref([
|
||||
{
|
||||
id: 1,
|
||||
file_number: '1234567890',
|
||||
status: 'مشاهده نشد',
|
||||
request_type: 'CT',
|
||||
requester: 'محراب اسماعیلنیا',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'اتمام فرصت رسیدگی'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
file_number: '1234567891',
|
||||
status: 'مشاهده نشد',
|
||||
request_type: 'CT',
|
||||
requester: 'رضا گلیان',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: '۵۳ دقیقه'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
file_number: '1234567892',
|
||||
status: 'مشاهده نشد',
|
||||
request_type: 'MRI',
|
||||
requester: 'دکتر مریم مهدیپور',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۳۲ ساعت'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
file_number: '1234567893',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'دکتر مریم مهدیپور',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۲۴ ساعت'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
file_number: '1234567894',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'نام شخص و یا پزشک',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۵ ساعت'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
file_number: '1234567893',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'دکتر مریم مهدیپور',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۲۴ ساعت'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
file_number: '1234567894',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'نام شخص و یا پزشک',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۵ ساعت'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
file_number: '1234567893',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'دکتر مریم مهدیپور',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۲۴ ساعت'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
file_number: '1234567894',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'نام شخص و یا پزشک',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۵ ساعت'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
file_number: '1234567894',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'نام شخص و یا پزشک',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۵ ساعت'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
file_number: '1234567893',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'دکتر مریم مهدیپور',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۲۴ ساعت'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
file_number: '1234567894',
|
||||
status: 'در انتظار ثبت گزارش',
|
||||
request_type: 'MRI',
|
||||
requester: 'نام شخص و یا پزشک',
|
||||
registration_date: '۱۴۰۴/۰۳/۰۲ ۱۴:۱۸',
|
||||
processing_deadline: 'کمتر از ۵ ساعت'
|
||||
defineProps({
|
||||
documents: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
])
|
||||
|
||||
const columns = ref([
|
||||
{
|
||||
title: 'شماره پرونده',
|
||||
key: 'file_number'
|
||||
},
|
||||
{
|
||||
title: 'وضعیت',
|
||||
key: 'status'
|
||||
},
|
||||
{
|
||||
title: 'نوع درخواست',
|
||||
key: 'request_type'
|
||||
},
|
||||
{
|
||||
title: 'درخواستکننده',
|
||||
key: 'requester'
|
||||
},
|
||||
{
|
||||
title: 'تاریخ ثبت',
|
||||
key: 'registration_date'
|
||||
},
|
||||
{
|
||||
title: 'فرصت رسیدگی',
|
||||
key: 'processing_deadline'
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
key: 'actions',
|
||||
width: 80,
|
||||
style: 'grid grid-cols-1',
|
||||
slot: true,
|
||||
},
|
||||
])
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -162,13 +22,13 @@ const columns = ref([
|
||||
<UiCard title="کیسهای در انتظار بررسی" variant="default" class="">
|
||||
<TableGeneric
|
||||
class="bg-white !rounded-2xl"
|
||||
:data="data"
|
||||
:data="documents.data"
|
||||
customStyle="!text-[11px] !font-normal"
|
||||
:searchable="false"
|
||||
:columns="columns"
|
||||
:columns="caseColumns"
|
||||
:selectable="false"
|
||||
:pagination="null"
|
||||
:model-value="selectedItems"
|
||||
:pagination="documents.meta"
|
||||
:model-value="[]"
|
||||
>
|
||||
<template #column-actions="{ data }" class="">
|
||||
<div class="flex items-center justify-end">
|
||||
|
||||
@@ -1,108 +1,96 @@
|
||||
<script setup>
|
||||
import UiButton from '../../components/ui/UiButton.vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import Dialog from 'primevue/dialog';
|
||||
import ProgressBar from 'primevue/progressbar';
|
||||
import RequestType from './fastRequest/RequestType.vue';
|
||||
import RequestCase from './fastRequest/RequestCase.vue';
|
||||
import RequestDetails from './fastRequest/RequestDetails.vue';
|
||||
import RequestDoctor from './fastRequest/RequestDoctor.vue';
|
||||
import RequestReview from './fastRequest/RequestReview.vue';
|
||||
import UiButton from '../../components/ui/UiButton.vue';
|
||||
import { computed, watch } from 'vue';
|
||||
import Dialog from 'primevue/dialog';
|
||||
import ProgressBar from 'primevue/progressbar';
|
||||
import { toast } from 'vue3-toastify';
|
||||
import RequestType from './fastRequest/RequestType.vue';
|
||||
import RequestCase from './fastRequest/RequestCase.vue';
|
||||
import RequestDetails from './fastRequest/RequestDetails.vue';
|
||||
import RequestDoctor from './fastRequest/RequestDoctor.vue';
|
||||
import RequestReview from './fastRequest/RequestReview.vue';
|
||||
import { useFastRequestStore } from '../../store/FastRequest';
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
const visible = defineModel('visible');
|
||||
const fastRequestStore = useFastRequestStore();
|
||||
|
||||
const step = ref(1);
|
||||
const stepRef = ref(null);
|
||||
const steps = [
|
||||
{ label: 'نوع درخواست', component: RequestType },
|
||||
{ label: 'انتخاب کیس', component: RequestCase },
|
||||
{ label: 'جزئیات درخواست', component: RequestDetails },
|
||||
{ label: 'انتخاب پزشک', component: RequestDoctor },
|
||||
{ label: 'مرور نهایی', component: RequestReview },
|
||||
];
|
||||
|
||||
const steps = ref({
|
||||
1: RequestType,
|
||||
2: RequestCase,
|
||||
3: RequestDetails,
|
||||
4: RequestDoctor,
|
||||
5: RequestReview,
|
||||
});
|
||||
const currentStepComponent = computed(() => {
|
||||
return steps[fastRequestStore.step - 1]?.component || RequestType;
|
||||
});
|
||||
|
||||
const currentStepComponent = computed(() => {
|
||||
return steps.value[step.value] || RequestType
|
||||
});
|
||||
|
||||
const handleNext = () => {
|
||||
step.value++;
|
||||
const isLastStep = computed(() => fastRequestStore.step === steps.length);
|
||||
|
||||
watch(visible, (isVisible) => {
|
||||
if (isVisible) {
|
||||
fastRequestStore.fetchCreateData();
|
||||
} else {
|
||||
fastRequestStore.reset();
|
||||
}
|
||||
});
|
||||
|
||||
const handleNext = async () => {
|
||||
if (!fastRequestStore.canProceed) {
|
||||
toast.error('لطفا اطلاعات این مرحله را کامل کنید.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isLastStep.value) {
|
||||
fastRequestStore.nextStep();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const document = await fastRequestStore.submit();
|
||||
toast.success(`درخواست شما با شماره پرونده ${document.code} با موفقیت ثبت شد.`);
|
||||
visible.value = false;
|
||||
} catch (error) {
|
||||
toast.error(error.response?.data?.message || 'خطا در ثبت درخواست. لطفا دوباره تلاش کنید.');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<Dialog :modal="true" :closable="true" :dismissableMask="true" :maximizable="false" :style="{ width: '688px' , minHeight: '376px' }" :pt="{header : '!bg-client-primaryBlue'}">
|
||||
<Dialog v-model:visible="visible" :modal="true" :closable="true" :dismissableMask="true" :maximizable="false" :style="{ width: '688px' , minHeight: '376px' }" class="fast-request-dialog" :pt="{header : '!bg-client-primaryBlue'}">
|
||||
<template #header>
|
||||
<div class="w-full flex items-center justify-start">
|
||||
<h2 class="text-[14px] font-[700] text-[#576989]">ثبت آنی درخواست</h2>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-[56px] flex items-center justify-between border-b border-[#EBEBEB] pb-3">
|
||||
<div class="w-auto h-[40px] grid grid-cols-1 items-center justify-center gap-1">
|
||||
<div class="w-full h-[20px] flex items-center justify-center ">
|
||||
<span class="w-[20px] h-[20px] bg-[#576989] rounded-full text-white flex items-center justify-center text-[10px] font-[600]">1</span>
|
||||
<template v-for="(item, index) in steps" :key="item.label">
|
||||
<ProgressBar v-if="index > 0" :value="fastRequestStore.step > index ? 100 : 0" :showValue="false" mode="determinate"></ProgressBar>
|
||||
<div class="w-auto h-[40px] grid grid-cols-1 items-center justify-center gap-1">
|
||||
<div class="w-full h-[20px] flex items-center justify-center">
|
||||
<span
|
||||
class="w-[20px] h-[20px] rounded-full text-white flex items-center justify-center text-[10px] font-[600]"
|
||||
:class="fastRequestStore.step >= index + 1 ? 'bg-[#576989]' : 'bg-[#C1D0E8]'"
|
||||
>{{ index + 1 }}</span>
|
||||
</div>
|
||||
<span class="text-[10px] font-[600]" :class="fastRequestStore.step >= index + 1 ? 'text-[#576989]' : 'text-[#7188AD]'">{{ item.label }}</span>
|
||||
</div>
|
||||
<span class="text-[10px] font-[600] text-[#7188AD]">نوع درخواست</span>
|
||||
</div>
|
||||
<ProgressBar :value="value1" :showValue="false" mode="determinate"></ProgressBar>
|
||||
<div class="w-auto h-[40px] grid grid-cols-1 items-center justify-center gap-1">
|
||||
<div class="w-full h-[20px] flex items-center justify-center ">
|
||||
<span class="w-[20px] h-[20px] bg-[#576989] rounded-full text-white flex items-center justify-center text-[10px] font-[600]">2</span>
|
||||
</div>
|
||||
<span class="text-[10px] font-[600] text-[#7188AD]">انتخاب کیس</span>
|
||||
</div>
|
||||
<ProgressBar :value="value2" :showValue="false" mode="determinate"></ProgressBar>
|
||||
<div class="w-auto h-[40px] grid grid-cols-1 items-center justify-center gap-1">
|
||||
<div class="w-full h-[20px] flex items-center justify-center ">
|
||||
<span class="w-[20px] h-[20px] bg-[#576989] rounded-full text-white flex items-center justify-center text-[10px] font-[600]">3</span>
|
||||
</div>
|
||||
<span class="text-[10px] font-[600] text-[#7188AD]">جزئیات درخواست</span>
|
||||
</div>
|
||||
<ProgressBar :value="value3" :showValue="false" mode="determinate"></ProgressBar>
|
||||
<div class="w-auto h-[40px] grid grid-cols-1 items-center justify-center gap-1">
|
||||
<div class="w-full h-[20px] flex items-center justify-center ">
|
||||
<span class="w-[20px] h-[20px] bg-[#576989] rounded-full text-white flex items-center justify-center text-[10px] font-[600]">4</span>
|
||||
</div>
|
||||
<span class="text-[10px] font-[600] text-[#7188AD]">انتخاب پزشک</span>
|
||||
</div>
|
||||
<ProgressBar :value="value4" :showValue="false" mode="determinate"></ProgressBar>
|
||||
<div class="w-auto h-[40px] grid grid-cols-1 items-center justify-center gap-1">
|
||||
<div class="w-full h-[20px] flex items-center justify-center ">
|
||||
<span class="w-[20px] h-[20px] bg-[#576989] rounded-full text-white flex items-center justify-center text-[10px] font-[600]">5</span>
|
||||
</div>
|
||||
<span class="text-[10px] font-[600] text-[#7188AD]">مرور نهایی</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<component :is="currentStepComponent" ref="stepRef" @validated="onValidated"/>
|
||||
<component :is="currentStepComponent" />
|
||||
|
||||
<div class="w-full pt-3 flex items-center justify-end border-t border-[#EBEBEB]">
|
||||
<ui-button label="تایید و مرحله بعد" severity="success" size="small" @click="handleNext" />
|
||||
<div class="w-full pt-3 flex items-center justify-between border-t border-[#EBEBEB]">
|
||||
<ui-button v-if="fastRequestStore.step > 1" label="مرحله قبل" severity="secondary" size="small" @click="fastRequestStore.prevStep" />
|
||||
<span v-else></span>
|
||||
<ui-button
|
||||
:label="isLastStep ? 'ثبت نهایی درخواست' : 'تایید و مرحله بعد'"
|
||||
severity="success"
|
||||
size="small"
|
||||
:loading="fastRequestStore.submitting"
|
||||
:disabled="fastRequestStore.submitting"
|
||||
@click="handleNext"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.p-progressbar) {
|
||||
min-width: 60px !important;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
:deep(.p-progressbar-value) {
|
||||
background: #576989 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -2,46 +2,36 @@
|
||||
import Dialog from 'primevue/dialog';
|
||||
import UiButton from '../../ui/UiButton.vue';
|
||||
import TableGeneric from '../../ui/TableGeneric.vue';
|
||||
import { ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import CaseNumber from './CaseNumber.vue';
|
||||
import { useFastRequestStore } from '../../../store/FastRequest';
|
||||
|
||||
const visible = defineModel('visible');
|
||||
const fastRequestStore = useFastRequestStore();
|
||||
|
||||
const isChooseCaseNumber = ref(false);
|
||||
const selectedPetId = ref(null);
|
||||
|
||||
const showChooseCaseNumber = () => {
|
||||
isChooseCaseNumber.value = true;
|
||||
}
|
||||
const data = ref([
|
||||
{
|
||||
id: 1,
|
||||
case_number: '1234567890',
|
||||
case_name: 'مایلو',
|
||||
case_type: 'سگ',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
case_number: '1234567891',
|
||||
case_name: 'تدی',
|
||||
case_type: 'گربه',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
case_number: '1234567892',
|
||||
case_name: 'پونی',
|
||||
case_type: 'خرگوش',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
case_number: '1234567893',
|
||||
case_name: 'روبیک',
|
||||
case_type: 'همستر',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
case_number: '1234567894',
|
||||
case_name: 'کولا',
|
||||
case_type: 'خوکچه هندی',
|
||||
}
|
||||
]);
|
||||
|
||||
const data = computed(() => fastRequestStore.pets.map((pet) => ({
|
||||
id: pet.id,
|
||||
case_number: pet.id,
|
||||
case_name: pet.name,
|
||||
case_type: pet.breed ? `${pet.type} (${pet.breed})` : pet.type,
|
||||
})));
|
||||
|
||||
const selectPet = (petId) => {
|
||||
selectedPetId.value = petId;
|
||||
}
|
||||
|
||||
const confirmSelection = () => {
|
||||
if (!selectedPetId.value) return;
|
||||
fastRequestStore.selectArchivePet(selectedPetId.value);
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
const columns = ref([
|
||||
{
|
||||
@@ -65,9 +55,9 @@ const columns = ref([
|
||||
}
|
||||
]);
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<Dialog :modal="true" :closable="true" :dismissableMask="true" :maximizable="false" :style="{ width: '554px' , minHeight: '326px' }">
|
||||
<Dialog v-model:visible="visible" :modal="true" :closable="true" :dismissableMask="true" :maximizable="false" :style="{ width: '554px' , minHeight: '326px' }" class="fast-request-dialog">
|
||||
<template #header>
|
||||
<h3>انتخاب کیس از آرشیو</h3>
|
||||
</template>
|
||||
@@ -76,7 +66,9 @@ const columns = ref([
|
||||
<p>در صورتیکه شماره مرجع یک کیس را در اختیار داشته باشید میتوانید درخواست را برای کیس مربوطه نیز ثبت کنید.</p>
|
||||
</div>
|
||||
<div class="h-[180px] overflow-y-scroll">
|
||||
<p v-if="!data.length" class="w-full py-8 text-center text-[11px] font-[400] text-[#7188AD]">کیسی در آرشیو شما ثبت نشده است.</p>
|
||||
<TableGeneric
|
||||
v-else
|
||||
class="bg-white !rounded-2xl"
|
||||
:data="data"
|
||||
customStyle="!text-[11px] !font-normal"
|
||||
@@ -88,25 +80,20 @@ const columns = ref([
|
||||
>
|
||||
<template #column-actions="{ data }">
|
||||
<div class="flex items-center justify-end">
|
||||
<UiButton severity="secondary" size="small">
|
||||
<template #icon>
|
||||
|
||||
</template>
|
||||
</UiButton>
|
||||
<UiButton
|
||||
:severity="selectedPetId === data.id ? 'success' : 'secondary'"
|
||||
size="small"
|
||||
:label="selectedPetId === data.id ? 'انتخاب شد' : 'انتخاب'"
|
||||
@click="selectPet(data.id)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</TableGeneric>
|
||||
</div>
|
||||
<div class="w-full pt-3 flex items-center justify-end gap-2 border-t border-[#EBEBEB]">
|
||||
<ui-button label="افزودن از طریق شناسه کیس" severity="secondary" @click="showChooseCaseNumber"/>
|
||||
<ui-button label="تایید و انتخاب" severity="success" size="small" @click="handleNext" />
|
||||
<ui-button label="تایید و انتخاب" severity="success" size="small" :disabled="!selectedPetId" @click="confirmSelection" />
|
||||
</div>
|
||||
<case-number v-model:visible="isChooseCaseNumber"></case-number>
|
||||
<case-number v-model:visible="isChooseCaseNumber" @selected="visible = false"></case-number>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,45 +1,43 @@
|
||||
<script setup>
|
||||
import Dialog from 'primevue/dialog';
|
||||
import InputText from 'primevue/inputtext';
|
||||
import UiButton from '../../ui/UiButton.vue';
|
||||
import { ref } from 'vue';
|
||||
import { useFastRequestStore } from '../../../store/FastRequest';
|
||||
|
||||
const visible = defineModel('visible');
|
||||
const emit = defineEmits(['selected']);
|
||||
const fastRequestStore = useFastRequestStore();
|
||||
|
||||
const caseNumber = ref(null);
|
||||
|
||||
const confirmCaseNumber = () => {
|
||||
if (!caseNumber.value) return;
|
||||
fastRequestStore.selectArchivePet(Number(caseNumber.value));
|
||||
caseNumber.value = null;
|
||||
visible.value = false;
|
||||
emit('selected');
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<Dialog :modal="true" :closable="true" :dismissableMask="true" :maximizable="false" :style="{ width: '408px' , minHeight: '210px' }">
|
||||
<Dialog v-model:visible="visible" :modal="true" :closable="true" :dismissableMask="true" :maximizable="false" :style="{ width: '408px' , minHeight: '210px' }" class="fast-request-dialog">
|
||||
<template #header>
|
||||
<h3>افزودن کیس از طریق شناسه مرجع</h3>
|
||||
</template>
|
||||
<div class="w-full py-2 flex flex-col items-start justify-center border-t border-[#EBEBEB] text-[11px] font-[600]">
|
||||
<p>لطفا شناسه کیس که از پزشک و یا سرپرست کیس دریافت کردهاید را وارد نمایید.</p>
|
||||
</div>
|
||||
<Form ref="formRef" v-slot="$form" class="p-4 grid grid-cols-1 !w-full">
|
||||
<FormField v-slot="$field" name="name" initialValue="" class="flex flex-col">
|
||||
<InputText
|
||||
type="text"
|
||||
placeholder="شناسه کیس"
|
||||
size="large"/>
|
||||
</FormField>
|
||||
</Form>
|
||||
<form class="p-4 grid grid-cols-1 w-full" @submit.prevent="confirmCaseNumber">
|
||||
<InputText
|
||||
v-model="caseNumber"
|
||||
type="number"
|
||||
placeholder="شناسه کیس"
|
||||
size="large"
|
||||
/>
|
||||
</form>
|
||||
<div class="w-full pt-3 flex items-center justify-end gap-2 border-t border-[#EBEBEB]">
|
||||
<ui-button label="تایید و افزودن" severity="success" size="small"/>
|
||||
<ui-button label="تایید و افزودن" severity="success" size="small" :disabled="!caseNumber" @click="confirmCaseNumber"/>
|
||||
</div>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.p-inputtext::placeholder) {
|
||||
color: #6E91C9;
|
||||
}
|
||||
|
||||
:deep(.p-inputtext) {
|
||||
border: 1px solid #DEE3EB !important;
|
||||
border-radius: 8px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import FileUpload from 'primevue/fileupload';
|
||||
import Badge from 'primevue/badge';
|
||||
import { formatFileSize } from '../../../utils/fileUtils';
|
||||
|
||||
const files = defineModel({ type: Array, default: () => [] });
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const fileUpload = ref(null);
|
||||
|
||||
const openFileDialog = () => {
|
||||
fileUpload.value.choose();
|
||||
}
|
||||
|
||||
const onSelectedFiles = (event) => {
|
||||
files.value = event.files;
|
||||
}
|
||||
|
||||
const onRemoveFile = (removeFileCallback, index) => {
|
||||
removeFileCallback(index);
|
||||
files.value = fileUpload.value.files;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FileUpload
|
||||
ref="fileUpload"
|
||||
class="w-full !border-dashed !border-[#C1D0E8] !min-h-[100px] flex items-center justify-center"
|
||||
name="files[]"
|
||||
:customUpload="true"
|
||||
:showUploadButton="false"
|
||||
:showCancelButton="false"
|
||||
:showChooseButton="false"
|
||||
:multiple="true"
|
||||
accept="image/*"
|
||||
:maxFileSize="10485760"
|
||||
@select="onSelectedFiles"
|
||||
>
|
||||
<template #content="{ files: selectedFiles, removeFileCallback }">
|
||||
<div v-if="selectedFiles.length > 0" class="flex flex-wrap gap-4 pt-4">
|
||||
<div v-for="(file, index) of selectedFiles" :key="file.name + file.type + file.size" class="relative w-[5rem] h-[5rem] rounded-lg border border-gray-200 flex flex-col items-center overflow-hidden">
|
||||
<img role="presentation" :alt="file.name" :src="file.objectURL" class="absolute top-0 left-0 w-full h-full object-cover"/>
|
||||
<div class="absolute bottom-0 left-0 w-full flex flex-col items-center gap-1 bg-white/80 p-1">
|
||||
<span class="w-full text-[10px] font-[400] text-center text-ellipsis whitespace-nowrap overflow-hidden">{{ file.name }}</span>
|
||||
<span class="text-[9px]">{{ formatFileSize(file.size) }}</span>
|
||||
</div>
|
||||
<button type="button" class="absolute top-1 left-1 w-4 h-4 flex items-center justify-center rounded-full bg-white text-[#7A1419] text-[10px] cursor-pointer" @click.stop="onRemoveFile(removeFileCallback, index)">✕</button>
|
||||
</div>
|
||||
<button type="button" class="w-[5rem] h-[5rem] rounded-lg border border-dashed border-[#C1D0E8] text-[11px] text-[#365891] cursor-pointer" @click="openFileDialog">افزودن</button>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="w-full flex items-center justify-center flex-col cursor-pointer" @click="openFileDialog">
|
||||
<p class="text-[11px] font-[600] text-[#365891]">{{ title }}</p>
|
||||
<p class="mt-1 mb-0 text-[11px] font-[400] text-[#365891]">
|
||||
جهت آپلود تصویر کلیک کنید و یا فایل خود را کشیده و در این قسمت رها (Drag and Drop) کنید.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</FileUpload>
|
||||
</template>
|
||||
@@ -1,172 +1,86 @@
|
||||
<script setup>
|
||||
import Select from 'primevue/select';
|
||||
import InputText from 'primevue/inputtext';
|
||||
import { ref } from 'vue';
|
||||
import ArchiveCase from './ArchiveCase.vue';
|
||||
import UiInput from '../../ui/UiInput.vue';
|
||||
import { useFastRequestStore } from '../../../store/FastRequest';
|
||||
import { petTypes, petGenders, neuteredOptions } from '../../../data/fastRequestOptions';
|
||||
|
||||
const fastRequestStore = useFastRequestStore();
|
||||
|
||||
const isChooseArchive = ref(false);
|
||||
|
||||
const showChooseArchive = () => {
|
||||
isChooseArchive.value = true;
|
||||
}
|
||||
const genders = ref([
|
||||
{ name: 'نر', code: 'male' },
|
||||
{ name: 'ماده', code: 'female' }
|
||||
]);
|
||||
|
||||
const types = ref([
|
||||
{ name: 'سگ', code: 'dog' },
|
||||
{ name: 'گربه', code: 'cat' },
|
||||
{ name: 'پرنده', code: 'bird' },
|
||||
{ name: 'خرگوش', code: 'rabbit' },
|
||||
{ name: 'همستر', code: 'hamster' },
|
||||
{ name: 'خوکچه هندی', code: 'guinea_pig' },
|
||||
{ name: 'لاک پشت', code: 'turtle' },
|
||||
{ name: 'مار', code: 'snake' },
|
||||
{ name: 'مارمولک', code: 'lizard' },
|
||||
]);
|
||||
|
||||
const neuteredStatus = ref([
|
||||
{ name: 'عقیم سازی شده', code: 'neutered' },
|
||||
{ name: 'عقیم سازی نشده', code: 'not_neutered' }
|
||||
]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full space-y-2 py-6">
|
||||
<div class="w-full h-[12px] flex items-center justify-between">
|
||||
<p class="flex h-full items-center justify-start text-[11px] font-[600] text-[#3E4C63]">مشخصات کیس(حیوان) مورد نظر را وارد نمایید.</p>
|
||||
<button @click="showChooseArchive" class="flex h-full items-center justify-end text-[11px] font-[400] text-[#7A1419] cursor-pointer">انتخاب از آرشیو</button>
|
||||
<button type="button" @click="showChooseArchive" class="flex h-full items-center justify-end text-[11px] font-[400] text-[#7A1419] cursor-pointer">انتخاب از آرشیو</button>
|
||||
</div>
|
||||
<p class="flex items-center justify-start text-[11px] font-[600] text-[#576989]">
|
||||
در صورتی که قبلا این کیس در پلتفرم رادیکال ثبت شده، برای بررسی سوابق قبلی از دکمه «انتخاب از آرشیو» استفاده نمایید.
|
||||
</p>
|
||||
<Form ref="formRef" v-slot="$form" class="p-4 grid grid-cols-2 gap-4 !w-full">
|
||||
<FormField v-slot="$field" name="name" initialValue="" class="flex flex-col">
|
||||
<!-- <InputText
|
||||
<div v-if="fastRequestStore.requestCase.petId" class="w-full flex items-center justify-between border border-[#DEE3EB] rounded-[8px] p-3">
|
||||
<p class="text-[11px] font-[600] text-[#3E4C63]">
|
||||
کیس انتخابشده از آرشیو:
|
||||
<span v-if="fastRequestStore.selectedPet" class="text-[#7A1419]">{{ fastRequestStore.selectedPet.name }} ({{ fastRequestStore.selectedPet.type }})</span>
|
||||
<span v-else class="text-[#7A1419]">شناسه {{ fastRequestStore.requestCase.petId }}</span>
|
||||
</p>
|
||||
<button type="button" @click="fastRequestStore.clearArchivePet" class="text-[11px] font-[400] text-[#7A1419] cursor-pointer">حذف و ثبت کیس جدید</button>
|
||||
</div>
|
||||
<form v-else class="p-4 grid grid-cols-2 gap-4 w-full">
|
||||
<InputText
|
||||
v-model="fastRequestStore.requestCase.name"
|
||||
type="text"
|
||||
placeholder="نام"
|
||||
size="large"/> -->
|
||||
<UiInput
|
||||
type="text"
|
||||
size="large"
|
||||
prefixStart="نام"
|
||||
direction="ltr"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" name="type" initialValue="" class="flex flex-col">
|
||||
<Select
|
||||
:options="types"
|
||||
size="large"
|
||||
/>
|
||||
<Select
|
||||
v-model="fastRequestStore.requestCase.type"
|
||||
:options="petTypes"
|
||||
optionLabel="name"
|
||||
optionValue="code"
|
||||
placeholder="نوع"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" name="breed" initialValue="" class="flex flex-col">
|
||||
<InputText
|
||||
type="text"
|
||||
placeholder="نژاد"
|
||||
size="large"/>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" name="gender" initialValue="" class="flex flex-col">
|
||||
<Select :options="genders" optionLabel="name" optionValue="code" placeholder="جنسیت" size="small"/>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" name="age" initialValue="" class="flex flex-col">
|
||||
<InputText
|
||||
type="text"
|
||||
placeholder="سن"
|
||||
size="large"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" name="birthday" initialValue="" class="flex flex-col">
|
||||
<InputText
|
||||
type="text"
|
||||
placeholder="وزن"
|
||||
size="large"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" name="sterilized" initialValue="" class="flex flex-col">
|
||||
<Select
|
||||
:options="neuteredStatus"
|
||||
/>
|
||||
<InputText
|
||||
v-model="fastRequestStore.requestCase.breed"
|
||||
type="text"
|
||||
placeholder="نژاد"
|
||||
size="large"
|
||||
/>
|
||||
<Select
|
||||
v-model="fastRequestStore.requestCase.gender"
|
||||
:options="petGenders"
|
||||
optionLabel="name"
|
||||
optionValue="code"
|
||||
placeholder="جنسیت"
|
||||
size="small"
|
||||
/>
|
||||
<InputText
|
||||
v-model="fastRequestStore.requestCase.age"
|
||||
type="number"
|
||||
placeholder="سن (سال)"
|
||||
size="large"
|
||||
/>
|
||||
<InputText
|
||||
v-model="fastRequestStore.requestCase.weight"
|
||||
type="number"
|
||||
placeholder="وزن (کیلوگرم)"
|
||||
size="large"
|
||||
/>
|
||||
<Select
|
||||
v-model="fastRequestStore.requestCase.sterilized"
|
||||
:options="neuteredOptions"
|
||||
optionLabel="name"
|
||||
optionValue="code"
|
||||
placeholder="وضعیت عقیم سازی"
|
||||
size="small"
|
||||
/>
|
||||
</FormField>
|
||||
</Form>
|
||||
/>
|
||||
</form>
|
||||
<archive-case v-model:visible="isChooseArchive"></archive-case>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.p-select) {
|
||||
border: 1px solid #DEE3EB !important;
|
||||
border-radius: 8px !important;
|
||||
height: 37px !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
:deep(.p-select-label) {
|
||||
padding: 0 12px;
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.p-select-label.p-placeholder) {
|
||||
color: #6E91C9 !important;
|
||||
font-size: 11px !important;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
|
||||
:deep(.p-inputtext) {
|
||||
font-size: 11px !important;
|
||||
font-weight: 400 !important;
|
||||
border: 1px solid #DEE3EB !important;
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
:deep(.p-inputtext::placeholder) {
|
||||
color: #6E91C9;
|
||||
}
|
||||
|
||||
:deep(.vpd-main) {
|
||||
border: 1px solid #DEE3EB !important;
|
||||
border-radius: 8px !important;
|
||||
overflow: hidden !important;
|
||||
height: 45px !important;
|
||||
|
||||
}
|
||||
:deep(.vpd-input-group) {
|
||||
border: 0 !important;
|
||||
font-size: 16px !important;
|
||||
border-radius: 8px !important;
|
||||
border: 0 !important;
|
||||
font-weight: 400 !important;
|
||||
height: 45px !important;
|
||||
}
|
||||
:deep(.vpd-input-group .vpd-placeholder) {
|
||||
font-size: 13px !important;
|
||||
font-weight: 400 !important;
|
||||
color: #3E4C63 !important;
|
||||
}
|
||||
:deep(.vpd-input-group input) {
|
||||
border: 0 !important;
|
||||
}
|
||||
:deep(.vpd-icon-btn) {
|
||||
background: #576989 !important;
|
||||
}
|
||||
:deep(.vpd-content) {
|
||||
border-radius: 12px !important;
|
||||
overflow: hidden !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
:deep(.vpd-wrapper) {
|
||||
background-color: rgba(0,0,0,.1) !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,256 +1,37 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { usePrimeVue } from 'primevue/config';
|
||||
import { useToast } from "primevue/usetoast";
|
||||
|
||||
const $primevue = usePrimeVue();
|
||||
const toast = useToast();
|
||||
|
||||
const totalSize = ref(0);
|
||||
const totalSizePercent = ref(0);
|
||||
const files = ref([]);
|
||||
|
||||
const fileUpload = ref(null)
|
||||
|
||||
const openFileDialog = () => {
|
||||
fileUpload.value.choose()
|
||||
}
|
||||
|
||||
const onRemoveTemplatingFile = (file, removeFileCallback, index) => {
|
||||
removeFileCallback(index);
|
||||
totalSize.value -= parseInt(formatSize(file.size));
|
||||
totalSizePercent.value = totalSize.value / 10;
|
||||
};
|
||||
|
||||
const onClearTemplatingUpload = (clear) => {
|
||||
clear();
|
||||
totalSize.value = 0;
|
||||
totalSizePercent.value = 0;
|
||||
};
|
||||
|
||||
const onSelectedFiles = (event) => {
|
||||
files.value = event.files;
|
||||
files.value.forEach((file) => {
|
||||
totalSize.value += parseInt(formatSize(file.size));
|
||||
});
|
||||
};
|
||||
|
||||
const uploadEvent = (callback) => {
|
||||
totalSizePercent.value = totalSize.value / 10;
|
||||
callback();
|
||||
};
|
||||
|
||||
const onTemplatedUpload = () => {
|
||||
toast.add({ severity: "info", summary: "Success", detail: "File Uploaded", life: 3000 });
|
||||
};
|
||||
|
||||
const formatSize = (bytes) => {
|
||||
const k = 1024;
|
||||
const dm = 3;
|
||||
const sizes = $primevue.config.locale.fileSizeTypes;
|
||||
|
||||
if (bytes === 0) {
|
||||
return `0 ${sizes[0]}`;
|
||||
}
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));
|
||||
|
||||
return `${formattedSize} ${sizes[i]}`;
|
||||
};
|
||||
import Select from 'primevue/select';
|
||||
import Textarea from 'primevue/textarea';
|
||||
import FileUploadBox from './FileUploadBox.vue';
|
||||
import { useFastRequestStore } from '../../../store/FastRequest';
|
||||
import { priorities, modalityTitle } from '../../../data/fastRequestOptions';
|
||||
|
||||
const fastRequestStore = useFastRequestStore();
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<p class="text-[11px] font-[400] text-[#3E4C63] py-3">جزئیات درخواست و اطلاعات مورد نیاز را با دقت و حوصله وار نمایید.</p>
|
||||
<p class="text-[11px] font-[400] text-[#3E4C63] py-3">جزئیات درخواست و اطلاعات مورد نیاز را با دقت و حوصله وارد نمایید.</p>
|
||||
<div class="w-full grid grid-cols-2 gap-2 items-center justify-between">
|
||||
<Select
|
||||
:options="types"
|
||||
optionLabel="name"
|
||||
optionValue="code"
|
||||
placeholder="نوع درخواست"
|
||||
/>
|
||||
<span class="text-[11px] font-[400] text-[#7188AD]">زمان تخمینی ثبت گزارش: ۷۲ ساعت</span>
|
||||
<Select
|
||||
v-model="fastRequestStore.requestDetails.priority"
|
||||
:options="priorities"
|
||||
optionLabel="name"
|
||||
optionValue="code"
|
||||
placeholder="اولویت درخواست"
|
||||
/>
|
||||
<span class="text-[11px] font-[400] text-[#7188AD]">زمان تخمینی ثبت گزارش: ۷۲ ساعت</span>
|
||||
</div>
|
||||
<div class="w-full h-[118px] mt-3">
|
||||
<Textarea
|
||||
v-model="value1"
|
||||
size="small"
|
||||
placeholder="شرح درخواست و توضیحات"
|
||||
rows="3"
|
||||
class="w-full h-full" />
|
||||
|
||||
v-model="fastRequestStore.requestDetails.note"
|
||||
size="small"
|
||||
placeholder="شرح درخواست و توضیحات"
|
||||
rows="3"
|
||||
class="w-full h-full" />
|
||||
</div>
|
||||
<div class="w-full grid grid-cols-2 gap-2 items-center justify-between my-4">
|
||||
<FileUpload class="w-full !border-dashed !border-[#C1D0E8] !min-h-[100px] flex items-center justify-center" ref="fileUpload" name="files[]" :customUpload="true" :showUploadButton="false" :showCancelButton="false" :showChooseButton="false" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles">
|
||||
<template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }">
|
||||
<div class="flex flex-col gap-8 pt-4">
|
||||
<div v-if="files.length > 0">
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="relative w-[5rem] h-[5rem] rounded-lg border border-gray-200 bg-amber-100 flex flex-col items-center gap-4 overflow-hidden">
|
||||
<div class="w-full h-full absolute top-0 left-0">
|
||||
<img role="presentation" :alt="file.name" :src="file.objectURL" class="w-full h-full object-cover"/>
|
||||
</div>
|
||||
<div class="w-full h-full flex flex-col items-center justify-center gap-2 absolute bottom-0 left-0">
|
||||
<span class="w-full px-2 text-xs font-[400] text-ellipsis whitespace-nowrap overflow-hidden">{{ file.name }}</span>
|
||||
<div>{{ formatSize(file.size) }}</div>
|
||||
<Badge value="Pending" severity="warn" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="uploadedFiles.length > 0">
|
||||
<h5>Completed</h5>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
|
||||
<div>
|
||||
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
|
||||
</div>
|
||||
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
|
||||
<div>{{ formatSize(file.size) }}</div>
|
||||
<Badge value="Completed" class="mt-4" severity="success" />
|
||||
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" variant="outlined" rounded severity="danger" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="w-full flex items-center justify-center flex-col cursor-pointer" @click="openFileDialog">
|
||||
<Button
|
||||
icon="pi pi-images"
|
||||
rounded
|
||||
variant="outlined"
|
||||
severity="secondary"
|
||||
class="!hidden"
|
||||
@click.stop="openFileDialog"/>
|
||||
<p class="text-[11px] font-[600] text-[#365891]">سوابق پزشکی قبلی (اختیاری)</p>
|
||||
<p class="mt-1 mb-0 text-[11px] font-[400] text-[#365891]">
|
||||
جهت آپلود تصویر کلیک کنید و یا فایل خود کشیده و در این قسمت رها (Drag and Drup) کنید.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</FileUpload>
|
||||
<FileUpload class="w-full !border-dashed !border-[#C1D0E8] !min-h-[100px] flex items-center justify-center" ref="fileUpload" name="files[]" :customUpload="true" :showUploadButton="false" :showCancelButton="false" :showChooseButton="false" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles">
|
||||
<template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }">
|
||||
<div class="flex flex-col gap-8 pt-4">
|
||||
<div v-if="files.length > 0">
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="relative w-[5rem] h-[5rem] rounded-lg border border-gray-200 bg-amber-100 flex flex-col items-center gap-4 overflow-hidden">
|
||||
<div class="w-full h-full absolute top-0 left-0">
|
||||
<img role="presentation" :alt="file.name" :src="file.objectURL" class="w-full h-full object-cover"/>
|
||||
</div>
|
||||
<div class="w-full h-full flex flex-col items-center justify-center gap-2 absolute bottom-0 left-0">
|
||||
<span class="w-full px-2 text-xs font-[400] text-ellipsis whitespace-nowrap overflow-hidden">{{ file.name }}</span>
|
||||
<div>{{ formatSize(file.size) }}</div>
|
||||
<Badge value="Pending" severity="warn" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="uploadedFiles.length > 0">
|
||||
<h5>Completed</h5>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
|
||||
<div>
|
||||
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
|
||||
</div>
|
||||
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
|
||||
<div>{{ formatSize(file.size) }}</div>
|
||||
<Badge value="Completed" class="mt-4" severity="success" />
|
||||
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" variant="outlined" rounded severity="danger" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="w-full flex items-center justify-center flex-col cursor-pointer" @click="openFileDialog">
|
||||
<Button
|
||||
icon="pi pi-images"
|
||||
rounded
|
||||
variant="outlined"
|
||||
severity="secondary"
|
||||
class="!hidden"
|
||||
@click.stop="openFileDialog"/>
|
||||
<p class="text-[11px] font-[600] text-[#365891]">فایل «CT Scan»</p>
|
||||
<p class="mt-1 mb-0 text-[11px] font-[400] text-[#365891]">
|
||||
جهت آپلود تصویر کلیک کنید و یا فایل خود کشیده و در این قسمت رها (Drag and Drup) کنید.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</FileUpload>
|
||||
<div class="w-full grid grid-cols-2 gap-2 items-start justify-between my-4">
|
||||
<FileUploadBox v-model="fastRequestStore.historyFiles" title="سوابق پزشکی قبلی (اختیاری)" />
|
||||
<FileUploadBox v-model="fastRequestStore.scanFiles" :title="`فایل «${modalityTitle(fastRequestStore.requestType)}»`" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.p-select) {
|
||||
border: 1px solid #DEE3EB !important;
|
||||
border-radius: 8px !important;
|
||||
height: 37px !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
:deep(.p-select-label) {
|
||||
padding: 0 12px;
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.p-select-label.p-placeholder) {
|
||||
color: #6E91C9 !important;
|
||||
font-size: 11px !important;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
:deep(.p-textarea) {
|
||||
border: 1px solid #DEE3EB !important;
|
||||
border-radius: 8px !important;
|
||||
height: 100% !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
:deep(.p-textarea::placeholder) {
|
||||
color: #6E91C9 !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
.p-fileupload-content {
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
|
||||
:deep(.p-fileupload-choose-button) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:deep(.p-fileupload-header) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:deep(.p-fileupload) {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
:deep(.p-fileupload-advanced) {
|
||||
border: none !important;
|
||||
border: 2px solid #C1D0E8 !important;
|
||||
border-style: dashed !important;
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,29 +1,35 @@
|
||||
<script setup>
|
||||
|
||||
import { useFastRequestStore } from '../../../store/FastRequest';
|
||||
|
||||
const fastRequestStore = useFastRequestStore();
|
||||
|
||||
const selectDoctor = (doctorId) => {
|
||||
fastRequestStore.doctorId = doctorId;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="w-full h-full grid grid-cols-3 gap-2 items-center justify-between py-4">
|
||||
<div class="w-full bg-white h-[134px] flex flex-col items-center justify-center border-[2px] border-[#576989] rounded-[12px]">
|
||||
<button
|
||||
type="button"
|
||||
@click="selectDoctor(null)"
|
||||
class="w-full bg-white h-[134px] flex flex-col items-center justify-center rounded-[12px] cursor-pointer"
|
||||
:class="fastRequestStore.doctorId === null ? 'border-[2px] border-[#576989]' : 'border-[1px] border-[#DEE3EB]'"
|
||||
>
|
||||
<h3 class="text-[13px] font-[600] text-[#576989]">انتخاب خودکار</h3>
|
||||
<p class="w-[190px] text-center text-[11px] font-[600] text-[#3E4C63]">انتخاب در دسترس ترین پزشک جهت بررسی سریع درخواست شما</p>
|
||||
</div>
|
||||
<div class="w-full bg-white h-[134px] flex flex-col items-center justify-center border-[1px] border-[#DEE3EB] rounded-[12px]">
|
||||
<img src="/public/images/profile_default.png" alt="doctor" class="w-[65px] h-[65px] rounded-[50px] object-contain ">
|
||||
<h3 class="text-[13px] font-[600] text-[#576989]">دکتر حسین حسینی</h3>
|
||||
<p class="text-center text-[11px] font-[600] text-[#7188AD]">متخصص جراحی پوست و مو</p>
|
||||
</div>
|
||||
<div class="w-full bg-white h-[134px] flex flex-col items-center justify-center border-[1px] border-[#DEE3EB] rounded-[12px]">
|
||||
<img src="/public/images/profile_default.png" alt="doctor" class="w-[65px] h-[65px] rounded-[50px] object-contain ">
|
||||
<h3 class="text-[13px] font-[600] text-[#576989]">دکتر امین حسینی</h3>
|
||||
<p class="text-center text-[11px] font-[600] text-[#7188AD]">متخصص و رادیولوژیست</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
v-for="doctor in fastRequestStore.doctors"
|
||||
:key="doctor.id"
|
||||
type="button"
|
||||
@click="selectDoctor(doctor.id)"
|
||||
class="w-full bg-white h-[134px] flex flex-col items-center justify-center rounded-[12px] cursor-pointer"
|
||||
:class="fastRequestStore.doctorId === doctor.id ? 'border-[2px] border-[#576989]' : 'border-[1px] border-[#DEE3EB]'"
|
||||
>
|
||||
<img :src="doctor.profile_url || '/images/profile_default.png'" :alt="doctor.fullname" class="w-[65px] h-[65px] rounded-full object-cover">
|
||||
<h3 class="text-[13px] font-[600] text-[#576989]">{{ doctor.fullname }}</h3>
|
||||
<p class="text-center text-[11px] font-[600] text-[#7188AD]">{{ doctor.specialty }}</p>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
<script setup>
|
||||
|
||||
import { computed } from 'vue';
|
||||
import { useFastRequestStore } from '../../../store/FastRequest';
|
||||
import { modalityTitle, priorityTitle } from '../../../data/fastRequestOptions';
|
||||
|
||||
const fastRequestStore = useFastRequestStore();
|
||||
|
||||
const caseName = computed(() => fastRequestStore.selectedPet?.name || fastRequestStore.requestCase.name || 'کیس جدید');
|
||||
const caseNumber = computed(() => fastRequestStore.requestCase.petId || 'جدید');
|
||||
const doctorName = computed(() => fastRequestStore.selectedDoctor?.fullname || 'اولین پزشک در دسترس');
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="w-full h-full flex flex-col items-start justify-between gap-8 py-8">
|
||||
<p class="text-[13px] font-[400] text-[#3E4C63]">
|
||||
شما در حال تکمیل فرایند ثبت درخواست
|
||||
<span class="font-[600] text-[#7A1419]">((CT Scan))</span>
|
||||
شما در حال تکمیل فرایند ثبت درخواست
|
||||
<span class="font-[600] text-[#7A1419]">(({{ modalityTitle(fastRequestStore.requestType) }}))</span>
|
||||
با اولویت
|
||||
<span class="font-[600] text-[#7A1419]">((اورژانسی))</span> برای کیس <span class="font-[600] text-[#7A1419]">((مایلو))</span> با شماره کیس <span class="font-[600] text-[#7A1419]">((۱۲۳۴۵۶))</span> میباشید. درخواست شما در ابتدا توسط کارشناسان ما بررسی و در صورت تایید به <span class="font-[600] text-[#7A1419]">((اولین پزشک در دسترس))</span> جهت بررسی و گزارش نویسی ارجاع خواهد شد.
|
||||
<span class="font-[600] text-[#7A1419]">(({{ priorityTitle(fastRequestStore.requestDetails.priority) }}))</span> برای کیس <span class="font-[600] text-[#7A1419]">(({{ caseName }}))</span> با شماره کیس <span class="font-[600] text-[#7A1419]">(({{ caseNumber }}))</span> میباشید. درخواست شما در ابتدا توسط کارشناسان ما بررسی و در صورت تایید به <span class="font-[600] text-[#7A1419]">(({{ doctorName }}))</span> جهت بررسی و گزارش نویسی ارجاع خواهد شد.
|
||||
</p>
|
||||
<p class="text-[13px] font-[400] text-[#3E4C63]">
|
||||
وضعیت و مراحل پرونده از طریق <span class="font-[600] text-[#7A1419]">((پیامک))</span> به شما اطلاعرسانی خواهد شد.
|
||||
@@ -17,9 +24,3 @@
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
<script setup>
|
||||
import RequestCard from '../../../components/dashboard/RequestCard.vue';
|
||||
|
||||
import RequestCard from '../../../components/dashboard/RequestCard.vue';
|
||||
import { modalities } from '../../../data/fastRequestOptions';
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="w-full space-y-3 py-6">
|
||||
<p class="h-[17px] flex items-center justify-start text-[11px] font-[600] text-[#3E4C63]">نوع درخواست خود را مشخص کنید</p>
|
||||
<div class="w-full h-[133px] grid grid-cols-5 gap-3 justify-start">
|
||||
<RequestCard value="ct-scan" title="CT Scan" icon="ct-scan" severity="primary" :selectable="true"/>
|
||||
<RequestCard value="mri" title="MRI" icon="mri" severity="primary" :selectable="true"/>
|
||||
<RequestCard value="sonography" title="سونوگرافی" icon="sonography" severity="primary" :selectable="true"/>
|
||||
<RequestCard value="echo" title="اکوکاردیوگرافی" icon="echo" severity="primary" :selectable="true"/>
|
||||
<RequestCard value="radiology" title="رادیولوژی" icon="radiology" severity="primary" :selectable="true"/>
|
||||
<RequestCard
|
||||
v-for="modality in modalities"
|
||||
:key="modality.code"
|
||||
:value="modality.code"
|
||||
:title="modality.title"
|
||||
:icon="modality.icon"
|
||||
severity="primary"
|
||||
:selectable="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { modalityTitle } from './fastRequestOptions'
|
||||
import { convertEnglishToPersian } from '../utils/numberUtils'
|
||||
|
||||
export const caseColumns = [
|
||||
{
|
||||
title: 'شماره پرونده',
|
||||
key: 'code'
|
||||
},
|
||||
{
|
||||
title: 'وضعیت',
|
||||
key: 'status'
|
||||
},
|
||||
{
|
||||
title: 'نوع درخواست',
|
||||
key: 'modality',
|
||||
render: (row) => modalityTitle(row.modality)
|
||||
},
|
||||
{
|
||||
title: 'درخواستکننده',
|
||||
key: 'requester'
|
||||
},
|
||||
{
|
||||
title: 'تاریخ ثبت',
|
||||
key: 'submitted_at',
|
||||
render: (row) => row.submitted_at ? convertEnglishToPersian(row.submitted_at) : '-'
|
||||
},
|
||||
{
|
||||
title: 'فرصت رسیدگی',
|
||||
key: 'processing_deadline',
|
||||
render: (row) => row.processing_deadline ? convertEnglishToPersian(row.processing_deadline) : '-'
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
key: 'actions',
|
||||
width: 80,
|
||||
style: 'grid grid-cols-1',
|
||||
slot: true,
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
export const modalities = [
|
||||
{ code: 'ct-scan', title: 'CT Scan', icon: 'ct-scan' },
|
||||
{ code: 'mri', title: 'MRI', icon: 'mri' },
|
||||
{ code: 'sonography', title: 'سونوگرافی', icon: 'sonography' },
|
||||
{ code: 'echo', title: 'اکوکاردیوگرافی', icon: 'echo' },
|
||||
{ code: 'radiology', title: 'رادیولوژی', icon: 'radiology' },
|
||||
]
|
||||
|
||||
export const petTypes = [
|
||||
{ name: 'سگ', code: 'Dog' },
|
||||
{ name: 'گربه', code: 'Cat' },
|
||||
{ name: 'پرنده', code: 'Bird' },
|
||||
{ name: 'ماهی', code: 'Fish' },
|
||||
{ name: 'خرگوش', code: 'Rabbit' },
|
||||
{ name: 'همستر', code: 'Hamster' },
|
||||
{ name: 'خوکچه هندی', code: 'GuineaPig' },
|
||||
{ name: 'لاک پشت', code: 'Turtle' },
|
||||
{ name: 'مار', code: 'Snake' },
|
||||
{ name: 'مارمولک', code: 'Lizard' },
|
||||
{ name: 'سایر', code: 'Other' },
|
||||
]
|
||||
|
||||
export const petGenders = [
|
||||
{ name: 'نر', code: 'Male' },
|
||||
{ name: 'ماده', code: 'Female' },
|
||||
]
|
||||
|
||||
export const neuteredOptions = [
|
||||
{ name: 'عقیم سازی شده', code: true },
|
||||
{ name: 'عقیم سازی نشده', code: false },
|
||||
]
|
||||
|
||||
export const priorities = [
|
||||
{ name: 'عادی', code: 'Medium' },
|
||||
{ name: 'اورژانسی', code: 'High' },
|
||||
]
|
||||
|
||||
export const modalityTitle = (code) => {
|
||||
return modalities.find((modality) => modality.code === code)?.title || code
|
||||
}
|
||||
|
||||
export const priorityTitle = (code) => {
|
||||
return priorities.find((priority) => priority.code === code)?.name || code
|
||||
}
|
||||
@@ -1,22 +1,104 @@
|
||||
import { step } from '@primeuix/themes/aura/stepper'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
const emptyCase = () => ({
|
||||
petId: null,
|
||||
name: null,
|
||||
type: null,
|
||||
gender: null,
|
||||
breed: null,
|
||||
age: null,
|
||||
weight: null,
|
||||
sterilized: null,
|
||||
})
|
||||
|
||||
export const useFastRequestStore = defineStore('FastRequestStore', {
|
||||
state: () => ({
|
||||
endpoints: {
|
||||
create: '/dashboard/fast-requests/create',
|
||||
store: '/dashboard/fast-requests',
|
||||
},
|
||||
step: 1,
|
||||
requestType: null,
|
||||
requestCase: {
|
||||
name: null,
|
||||
species: null,
|
||||
gender: null,
|
||||
age: null,
|
||||
weight: null,
|
||||
neutered: null,
|
||||
requestCase: emptyCase(),
|
||||
requestDetails: {
|
||||
priority: null,
|
||||
note: null,
|
||||
},
|
||||
requestDetails: null,
|
||||
requestDoctor: null,
|
||||
requestReview: null,
|
||||
historyFiles: [],
|
||||
scanFiles: [],
|
||||
doctorId: null,
|
||||
pets: [],
|
||||
doctors: [],
|
||||
submitting: false,
|
||||
submittedDocument: null,
|
||||
}),
|
||||
getters: {
|
||||
selectedPet: (state) => state.pets.find((pet) => pet.id === state.requestCase.petId) || null,
|
||||
selectedDoctor: (state) => state.doctors.find((doctor) => doctor.id === state.doctorId) || null,
|
||||
canProceed: (state) => {
|
||||
switch (state.step) {
|
||||
case 1:
|
||||
return !!state.requestType
|
||||
case 2:
|
||||
return !!state.requestCase.petId || (!!state.requestCase.name && !!state.requestCase.type)
|
||||
case 3:
|
||||
return !!state.requestDetails.priority
|
||||
default:
|
||||
return true
|
||||
}
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async fetchCreateData() {
|
||||
const { data } = await window.axios.get(this.endpoints.create)
|
||||
this.pets = data.pets
|
||||
this.doctors = data.doctors
|
||||
},
|
||||
selectArchivePet(petId) {
|
||||
this.requestCase = emptyCase()
|
||||
this.requestCase.petId = petId
|
||||
},
|
||||
clearArchivePet() {
|
||||
this.requestCase.petId = null
|
||||
},
|
||||
nextStep() {
|
||||
if (this.step < 5) this.step++
|
||||
},
|
||||
prevStep() {
|
||||
if (this.step > 1) this.step--
|
||||
},
|
||||
async submit() {
|
||||
this.submitting = true
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('modality', this.requestType)
|
||||
formData.append('priority', this.requestDetails.priority)
|
||||
if (this.requestDetails.note) formData.append('note', this.requestDetails.note)
|
||||
|
||||
}
|
||||
if (this.requestCase.petId) {
|
||||
formData.append('pet_id', this.requestCase.petId)
|
||||
} else {
|
||||
Object.entries(this.requestCase).forEach(([key, value]) => {
|
||||
if (key !== 'petId' && value !== null && value !== '') {
|
||||
formData.append(`pet[${key}]`, key === 'sterilized' ? (value ? 1 : 0) : value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (this.doctorId) formData.append('doctor_id', this.doctorId)
|
||||
|
||||
this.historyFiles.forEach((file) => formData.append('history_files[]', file))
|
||||
this.scanFiles.forEach((file) => formData.append('scan_files[]', file))
|
||||
|
||||
const { data } = await window.axios.post(this.endpoints.store, formData)
|
||||
this.submittedDocument = data.document
|
||||
return data.document
|
||||
} finally {
|
||||
this.submitting = false
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.$reset()
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
const sizes = ['B', 'KB', 'MB', 'GB']
|
||||
|
||||
export const formatFileSize = (bytes) => {
|
||||
if (!bytes) {
|
||||
return `0 ${sizes[0]}`
|
||||
}
|
||||
|
||||
const k = 1024
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(1))
|
||||
|
||||
return `${formattedSize} ${sizes[i]}`
|
||||
}
|
||||
Reference in New Issue
Block a user