feat: Implement Fast Request feature with file upload and request management
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user