complete Complete User Request Submission section RAD-1
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import {useToast} from "primevue";
|
||||
import Master from "../../../layouts/master.vue";
|
||||
import {useGlobalStore} from "../../../store/Global.js";
|
||||
|
||||
const src = ref(null);
|
||||
const file = ref({});
|
||||
const loading = ref(false);
|
||||
const isUpload = ref(false);
|
||||
const loadingUpload = ref(false);
|
||||
|
||||
const toast = useToast();
|
||||
const globalStore = useGlobalStore();
|
||||
const user_form = ref({
|
||||
name: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
user_form.value = {
|
||||
name: globalStore.current_user?.name ?? '',
|
||||
first_name: globalStore.current_user?.first_name ?? '',
|
||||
last_name: globalStore.current_user?.last_name ?? '',
|
||||
};
|
||||
})
|
||||
const errors = ref([]);
|
||||
const onFileSelect = (event) => {
|
||||
isUpload.value = false;
|
||||
file.value = event.files[0];
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = async (e) => {
|
||||
src.value = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(file.value);
|
||||
}
|
||||
|
||||
const onRemoveTemplatingFile = () => {
|
||||
src.value = null;
|
||||
file.value = {};
|
||||
};
|
||||
|
||||
const onFormSubmit = () => {
|
||||
loading.value = true;
|
||||
axios.post(`/admin/setting-profile/update-data/${globalStore.current_user.id}` , user_form.value ).then(res => {
|
||||
toast.add({ severity: 'success', summary: 'اطلاعات شما با موفقیت ثبت شد.', life: 3000 });
|
||||
errors.value = [];
|
||||
loading.value = false;
|
||||
globalStore.current_user.name = res.data.name;
|
||||
globalStore.current_user.first_name = res.data.first_name;
|
||||
globalStore.current_user.last_name = res.data.last_name;
|
||||
}).catch(error => {
|
||||
errors.value = error.response.data.errors;
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const uploadProfile = () => {
|
||||
loadingUpload.value = true;
|
||||
const form = new FormData();
|
||||
form.append('file' , file.value );
|
||||
axios.post('/admin/setting-profile/update-avatar' , form ).then(res => {
|
||||
toast.add({ severity: 'success', summary: 'پروفایل شما با موفقیت آپلود شد', life: 3000 });
|
||||
isUpload.value = true;
|
||||
loadingUpload.value = false;
|
||||
globalStore.current_user.profile_url = res.data.profile_url ?? '';
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<master>
|
||||
<section class="grid grid-cols-[1fr] pb-10 gap-4 px-10 max-lg:px-4">
|
||||
<div class="!w-1/2 max-lg:!w-full !m-auto grid grid-cols-a text-client-Fontcolor justify-center text-center">
|
||||
<i class="fi fi-rr-user-pen flex text-5xl m-auto"></i>
|
||||
<h4 class="font-extrabold text-2xl mt-4">ویرایش اطلاعات</h4>
|
||||
<p class="leading-6 text-sm font-light mt-2">برای تغییر آواتار خود، تصویر مورد نظر را از دستگاه خود انتخاب کرده و بارگذاری کنید. پس از بارگذاری، آواتار جدید شما بهطور خودکار در پروفایل بهروز میشود.</p>
|
||||
</div>
|
||||
<div class="card grid grid-cols-1 !w-[30rem] max-lg:!w-full !m-auto justify-center">
|
||||
<div class="card flex flex-col items-center gap-6 !mb-8">
|
||||
<FileUpload mode="basic" @select="onFileSelect" customUpload auto severity="secondary" chooseLabel="انتخاب آواتار" class="p-button-outlined flex flex-row-reverse !text-xs !text-white !bg-client-primary" />
|
||||
<img v-if="!src && globalStore.current_user.profile_url" :src="globalStore.current_user.profile_url" alt="Image" class="shadow-md rounded-xl w-auto max-h-28 object-contain" />
|
||||
<img v-if="src" :src="src" alt="Image" class="shadow-md rounded-xl w-auto max-h-28 object-contain" :style="!isUpload ? {filter: 'grayscale(100%)' } : {}" />
|
||||
<div v-if="!isUpload" class="grid grid-cols-2a gap-2 -mt-3 items-center justify-center">
|
||||
<Button v-if="src" icon="fi fi-rr-trash" :pt="{icon: 'flex'}" @click="onRemoveTemplatingFile()" outlined severity="danger" />
|
||||
<Button v-if="src" icon="fi fi-rr-cloud-upload" :pt="{icon: 'flex text-sm'}" label=" آپلود آواتار"
|
||||
class="!text-xs flex flex-row-reverse !py-3 !font-light"
|
||||
@click="uploadProfile()" :loading="loadingUpload" outlined severity="secondary" />
|
||||
</div>
|
||||
</div>
|
||||
<Fieldset legend="ویرایش حساب شما" pt:legend="!text-sm !rounded-lg !border-[1px] !border-gray-200"
|
||||
pt:root:class="!border-[1px] !rounded-xl"
|
||||
pt:content:class="grid grid-cols-1 !p-6 !pt-4 flex justify-center">
|
||||
<Form @submit="onFormSubmit" class="grid grid-cols-1 gap-4 w-full !border-0 !text-sm">
|
||||
<FormField v-slot="$field" name="name" initialValue="" class="flex flex-col gap-1">
|
||||
<label>نام کاربری</label>
|
||||
<InputText type="text" :class="[
|
||||
'placeholder:!text-sm !text-sm',
|
||||
errors?.name && !errors.name ? 'p-invalid' : ''
|
||||
]" v-model="user_form.name" placeholder="نام کاربری را وارد کنید" />
|
||||
<Message v-if="errors?.name"
|
||||
severity="error" size="small" variant="simple">{{ errors?.name[0] }}</Message>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" name="first_name" initialValue="" class="flex flex-col gap-1">
|
||||
<label>نام کوچک</label>
|
||||
<InputText type="text" :class="[
|
||||
'placeholder:!text-sm !text-sm',
|
||||
errors?.first_name && !errors.first_name ? 'p-invalid' : ''
|
||||
]" v-model="user_form.first_name" placeholder="نام کوچک خود را وارد کنید" />
|
||||
<Message v-if="errors?.first_name"
|
||||
severity="error" size="small" variant="simple">{{ errors?.first_name[0] }}</Message>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" name="last_name" initialValue="" class="flex flex-col gap-1">
|
||||
<label>نام خانوادگی</label>
|
||||
<InputText type="text" :class="[
|
||||
'placeholder:!text-sm !text-sm',
|
||||
errors?.last_name && !errors.last_name ? 'p-invalid' : ''
|
||||
]" v-model="user_form.last_name" placeholder="نام کوچک خود را وارد کنید" />
|
||||
<Message v-if="errors?.last_name"
|
||||
severity="error" size="small" variant="simple">{{ errors?.last_name[0] }}</Message>
|
||||
</FormField>
|
||||
<FormField v-slot="$field" asChild name="email" :initialValue="globalStore.current_user.email">
|
||||
<section class="flex flex-col gap-2">
|
||||
<InputText type="email" class="flex pt-2 !text-sm !font-light" disabled id="email" fluid />
|
||||
</section>
|
||||
</FormField>
|
||||
<Button type="submit" :loading="loading" severity="secondary" label="ذخیره اطلاعات" />
|
||||
</Form>
|
||||
</Fieldset>
|
||||
</div>
|
||||
</section>
|
||||
</master>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
<script setup lang="ts">
|
||||
import {reactive, ref} from "vue";
|
||||
import axios from "axios";
|
||||
import {useToast} from "primevue/usetoast";
|
||||
import Master from "../../../layouts/master.vue";
|
||||
|
||||
interface PasswordInterface {
|
||||
password: string,
|
||||
newPassword: string,
|
||||
newPassword_confirmation: string,
|
||||
}
|
||||
|
||||
|
||||
const toast = useToast();
|
||||
const loader = ref<boolean>(false);
|
||||
const errors = ref<any>([]);
|
||||
const ChangePasswordForm = reactive<PasswordInterface>({
|
||||
password : '',
|
||||
newPassword : '',
|
||||
newPassword_confirmation : '',
|
||||
});
|
||||
|
||||
|
||||
const ChangePasswordHandler = () => {
|
||||
loader.value = true;
|
||||
axios.post('/admin/setting-profile/change-password' , ChangePasswordForm).then(res => {
|
||||
if (res.status == 200){
|
||||
toast.add({severity : 'success' , summary : res.data.message});
|
||||
ChangePasswordForm.password = '';
|
||||
ChangePasswordForm.newPassword = '';
|
||||
ChangePasswordForm.newPassword_confirmation = '';
|
||||
}
|
||||
loader.value = false;
|
||||
errors.value = [];
|
||||
}).catch(error => {
|
||||
errors.value = error.response.data.errors ?? [];
|
||||
if (error.status == 401 && error.response.data.message){
|
||||
toast.add({severity : 'error' , summary : error.response.data.message})
|
||||
}
|
||||
loader.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<master>
|
||||
<Panel toggleable class="w-full !rounded-2xl bg-client-gray/10">
|
||||
<template #header>
|
||||
<div class="flex items-center gap-2">
|
||||
<i class="fi fi-rr-lock"></i>
|
||||
<span class="font-semibold text-sm">تغییر کلمه عبور</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="grid grid-cols-1 gap-4 content-start">
|
||||
<p class="mb-4 leading-7 text-sm !font-extralight">برای افزایش امنیت حساب کاربری خود، توصیه میشود که کلمه عبور خود را به طور دورهای تغییر دهید. برای این کار، ابتدا کلمه عبور فعلی خود را وارد کنید، سپس کلمه عبور جدید را وارد کرده و آن را دوباره تایید کنید. توجه داشته باشید که کلمه عبور جدید باید حداقل 8 کاراکتر باشد و شامل ترکیبی از حروف، اعداد و نمادها باشد.</p>
|
||||
<div class="m-auto">
|
||||
<FloatLabel variant="on" class=" m-auto">
|
||||
<Password id="password" type="password" :feedback="false"
|
||||
appendTo="self" toggleMask
|
||||
v-model="ChangePasswordForm.password"
|
||||
class="placeholder:!font-light !text-sm !bg-white h-12 !border-gray-500/20 !text-client-Fontcolor"/>
|
||||
<label for="on_label" class="!text-client-Fontcolor !bg-white !text-sm font-light">کلمه عبور فعلی</label>
|
||||
</FloatLabel>
|
||||
<Message
|
||||
v-if="errors.password"
|
||||
class="h-7 mt-1 !text-xs px-1"
|
||||
variant="simple"
|
||||
severity="error" size="small">{{errors.password[0]}}</Message>
|
||||
</div>
|
||||
<div class="m-auto">
|
||||
<FloatLabel variant="on" class="m-auto">
|
||||
<Password id="password" type="password" :feedback="false"
|
||||
appendTo="self" toggleMask
|
||||
v-model="ChangePasswordForm.newPassword"
|
||||
class="placeholder:!font-light !text-sm !bg-white h-12 !border-gray-500/20 !text-client-Fontcolor"/>
|
||||
<label for="on_label" class="!text-client-Fontcolor !bg-white !text-sm font-light"> کلمه عبور جدید</label>
|
||||
</FloatLabel>
|
||||
<Message
|
||||
v-if="errors.newPassword"
|
||||
class="h-7 mt-1 !text-xs px-1"
|
||||
variant="simple"
|
||||
severity="error" size="small">{{errors.newPassword[0]}}</Message>
|
||||
</div>
|
||||
<div class="m-auto">
|
||||
<FloatLabel variant="on" class="m-auto">
|
||||
<Password id="password" type="password" :feedback="false"
|
||||
appendTo="self" toggleMask
|
||||
v-model="ChangePasswordForm.newPassword_confirmation"
|
||||
class="placeholder:!font-light !text-sm !bg-white h-12 !border-gray-500/20 !text-client-Fontcolor"/>
|
||||
<label for="on_label" class="!text-client-Fontcolor !bg-white !text-sm font-light">تکرار کلمه عبور جدید</label>
|
||||
</FloatLabel>
|
||||
<Message
|
||||
class="h-7 mt-1 !text-xs px-1"
|
||||
variant="simple"
|
||||
severity="error" size="small"></Message>
|
||||
</div>
|
||||
<Button @click="ChangePasswordHandler" :loading="loader" label=" تغییر کلمه عبور" severity="secondary"
|
||||
class="m-auto flex flex-row-reverse items-center !font-normal" />
|
||||
</div>
|
||||
</Panel>
|
||||
</master>
|
||||
</template>
|
||||
@@ -0,0 +1,149 @@
|
||||
<script setup>
|
||||
import Master from "../../../layouts/master.vue";
|
||||
import { ref, onMounted } from 'vue';
|
||||
import TableGeneric from "../../../components/TableGeneric.vue";
|
||||
import { useConfirm } from 'primevue/useconfirm';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import { useSessionStore } from "../../../store/Session.js";
|
||||
|
||||
const toast = useToast();
|
||||
const confirm = useConfirm();
|
||||
|
||||
const props = defineProps({
|
||||
sessions: {
|
||||
type: Object,
|
||||
default: () => ({ data: [], meta: {} })
|
||||
}
|
||||
});
|
||||
|
||||
const sessionStore = useSessionStore();
|
||||
const selectedItems = ref([]);
|
||||
|
||||
const columns = ref(sessionStore.columns);
|
||||
|
||||
onMounted(() => {
|
||||
sessionStore.setSessions(props.sessions || []);
|
||||
});
|
||||
|
||||
const onSelectionChange = (selection) => {
|
||||
selectedItems.value = selection;
|
||||
sessionStore.setSelectedSessions(selection);
|
||||
};
|
||||
|
||||
const showDeleteConfirm = (data) => {
|
||||
confirm.require({
|
||||
group: 'deleteTemplate',
|
||||
header: 'مطمعن هستید؟',
|
||||
message: 'اگر به عملیات اطمینان دارید، تأیید کنید.',
|
||||
icon: 'fi fi-rr-info',
|
||||
rejectProps: {
|
||||
label: 'انصراف',
|
||||
icon: 'fi fi-rr-ban',
|
||||
outlined: true,
|
||||
size: 'small',
|
||||
class: '!text-xs !flex pt-1 !item-center',
|
||||
iconClass: '!flex !text-xs',
|
||||
},
|
||||
acceptProps: {
|
||||
label: 'حذف',
|
||||
icon: 'fi fi-rr-check',
|
||||
size: 'small',
|
||||
class: '!text-xs !flex pt-1 !item-center',
|
||||
iconClass: '!flex !text-xs',
|
||||
},
|
||||
accept: () => {
|
||||
sessionStore.deleteSession(data.id)
|
||||
.then((response) => {
|
||||
toast.add({ severity: 'success', summary: response.data.message });
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.add({ severity: 'error', summary: error.response.data.message });
|
||||
});
|
||||
},
|
||||
reject: () => {
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const confirmDeleteSelected = (ids) => {
|
||||
confirm.require({
|
||||
group: 'deleteTemplate',
|
||||
header: 'مطمعن هستید؟',
|
||||
message: 'اگر به عملیات اطمینان دارید، تأیید کنید.',
|
||||
icon: 'fi fi-rr-info',
|
||||
rejectProps: {
|
||||
label: 'انصراف',
|
||||
icon: 'fi fi-rr-ban',
|
||||
outlined: true,
|
||||
size: 'small',
|
||||
class: '!text-xs !flex pt-1 !item-center',
|
||||
iconClass: '!flex !text-xs',
|
||||
},
|
||||
acceptProps: {
|
||||
label: 'حذف',
|
||||
icon: 'fi fi-rr-check',
|
||||
size: 'small',
|
||||
class: '!text-xs !flex pt-1 !item-center',
|
||||
iconClass: '!flex !text-xs',
|
||||
},
|
||||
accept: () => {
|
||||
sessionStore.bulkDeleteSessions(ids);
|
||||
},
|
||||
reject: () => {
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<master>
|
||||
<div class="mb-4 grid grid-cols-2a justify-between items-center bg-white border-[1px] border-client-gray/20 py-4 px-4 rounded-2xl">
|
||||
<h2 class="font-bold text-client-Fontcolor">{{ sessionStore.indexPageTitle }}</h2>
|
||||
</div>
|
||||
<div class="card border-[1px] border-client-gray/20 bg-white rounded-2xl">
|
||||
<TableGeneric
|
||||
:data="sessionStore.sessions"
|
||||
:columns="columns"
|
||||
:selectable="true"
|
||||
:pagination="false"
|
||||
:searchable="true"
|
||||
v-model="selectedItems"
|
||||
@selection-change="onSelectionChange"
|
||||
>
|
||||
<template #bulk-action="{ selection }">
|
||||
<Button
|
||||
label="حذف همه نشست ها"
|
||||
size="small"
|
||||
:pt="{icon : 'flex'}"
|
||||
icon="fi fi-rr-trash"
|
||||
severity="danger"
|
||||
class="!text-xs !flex"
|
||||
outlined
|
||||
:loading="sessionStore.bulkLoader"
|
||||
@click="() => confirmDeleteSelected(selection.map(item => item.id))"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #column-actions="{ data }">
|
||||
<div class="grid grid-cols-1a">
|
||||
<Button
|
||||
type="button"
|
||||
class="!w-8 !h-8"
|
||||
variant="outlined"
|
||||
severity="danger"
|
||||
icon="fi fi-rr-trash"
|
||||
:pt="{icon : '!mt-2 !text-xs'}"
|
||||
:loading="sessionStore.loader"
|
||||
@click="showDeleteConfirm(data)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</TableGeneric>
|
||||
</div>
|
||||
</master>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user