initial commit
This commit is contained in:
249
resources/js/pages/admin-users/AddUser.vue
Normal file
249
resources/js/pages/admin-users/AddUser.vue
Normal file
@@ -0,0 +1,249 @@
|
||||
<script setup>
|
||||
import { passwordValidator } from '@/@core/utils/validators';
|
||||
import avatar1 from '@images/avatars/avatar-1.png';
|
||||
import { PerfectScrollbar } from 'vue3-perfect-scrollbar';
|
||||
import { VForm } from 'vuetify/components/VForm';
|
||||
import { useStore } from 'vuex';
|
||||
const store = useStore()
|
||||
const props = defineProps({
|
||||
isDrawerOpen: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
const accountData = {
|
||||
avatarImg: avatar1,
|
||||
name: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
email: '',
|
||||
phone_no: '',
|
||||
password: '',
|
||||
status: '',
|
||||
role_id: ''
|
||||
}
|
||||
const accountDataLocal = ref(structuredClone(accountData))
|
||||
const refInputEl = ref()
|
||||
const ImageBase64 = ref();
|
||||
const statusList = ref([
|
||||
{ name: 'Active', abbreviation: '1' },
|
||||
{ name: 'De-Active', abbreviation: '0' },
|
||||
|
||||
]);
|
||||
const sortedStates = computed(() => {
|
||||
return states.value.slice().sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
});
|
||||
const isPasswordVisible = ref(false)
|
||||
const emit = defineEmits(['update:isDrawerOpen', 'addedMessage'])
|
||||
const formatPhoneNumber = () => {
|
||||
// Remove non-numeric characters from the input
|
||||
const numericValue = accountDataLocal.value.phone_no.replace(/\D/g, '');
|
||||
|
||||
// Apply formatting logic
|
||||
if (numericValue.length <= 10) {
|
||||
accountDataLocal.value.phone_no = numericValue.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
|
||||
} else {
|
||||
// Limit the input to a maximum of 14 characters
|
||||
const truncatedValue = numericValue.slice(0, 10);
|
||||
accountDataLocal.value.phone_no = truncatedValue.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
|
||||
}
|
||||
};
|
||||
const handleDrawerModelValueUpdate = val => {
|
||||
emit('update:isDrawerOpen', val)
|
||||
}
|
||||
const genders = ref([
|
||||
{ name: 'Male', abbreviation: 'Male' },
|
||||
{ name: 'Female', abbreviation: 'Female' },
|
||||
{ name: 'Other', abbreviation: 'Other' },
|
||||
]);
|
||||
const refVForm = ref()
|
||||
const first_name = ref()
|
||||
const last_name = ref()
|
||||
const email = ref()
|
||||
const status = ref()
|
||||
const password = ref()
|
||||
const phone_no = ref()
|
||||
const changeAvatar = file => {
|
||||
const fileReader = new FileReader()
|
||||
const { files } = file.target
|
||||
if (files && files.length) {
|
||||
fileReader.readAsDataURL(files[0])
|
||||
fileReader.onload = () => {
|
||||
if (typeof fileReader.result === 'string') {
|
||||
accountDataLocal.value.avatarImg = fileReader.result
|
||||
}
|
||||
ImageBase64.value = fileReader.result.split(',')[1];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onSubmit = async () => {
|
||||
const { valid } = await refVForm.value.validate()
|
||||
if (valid) {
|
||||
|
||||
await store.dispatch('adminUserSave', {
|
||||
name: accountDataLocal.value.first_name,
|
||||
email: accountDataLocal.value.email,
|
||||
last_name: accountDataLocal.value.last_name,
|
||||
phone_no: accountDataLocal.value.phone_no,
|
||||
password: accountDataLocal.value.password,
|
||||
role_id: accountDataLocal.value.role_id,
|
||||
profile_pic: ImageBase64.value, //ecelData,
|
||||
|
||||
})
|
||||
|
||||
if (!store.getters.getErrorMsg) {
|
||||
emit('addedMessage', 'success')
|
||||
accountDataLocal.value.email = null
|
||||
accountDataLocal.value.name = null
|
||||
accountDataLocal.value.first_name = null
|
||||
accountDataLocal.value.phone_no = null
|
||||
accountDataLocal.value.last_name = null
|
||||
accountDataLocal.value.password = null
|
||||
accountDataLocal.value.role_id = null
|
||||
ImageBase64.value = null
|
||||
accountDataLocal.value.avatarImg = avatar1
|
||||
emit('update:isDrawerOpen', false)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const resetForm = () => {
|
||||
refVForm.value?.reset()
|
||||
emit('update:isDrawerOpen', false)
|
||||
}
|
||||
const roleData = ref([]);
|
||||
const useSortedRole = () => {
|
||||
const isLoading = ref(false);
|
||||
const error = ref(null);
|
||||
|
||||
const sortedRole = computed(() => {
|
||||
const allOption = { id: '', role: 'Select Any' };
|
||||
const sortedData = roleData.value.slice().sort((a, b) => {
|
||||
return a.role.localeCompare(b.role);
|
||||
});
|
||||
return [allOption, ...sortedData];
|
||||
});
|
||||
|
||||
const fetchRoleData = async () => {
|
||||
isLoading.value = true;
|
||||
error.value = null;
|
||||
try {
|
||||
await store.dispatch('getAllRolesList');
|
||||
roleData.value = store.getters.getRolesList || [];
|
||||
console.log('Fetched Role data:', roleData.value);
|
||||
} catch (e) {
|
||||
console.error('Error fetching Role data:', e);
|
||||
error.value = 'Failed to fetch Role data';
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(fetchRoleData);
|
||||
|
||||
return { sortedRole, isLoading, error, fetchRoleData };
|
||||
};
|
||||
const { sortedRole, isLoading, error, fetchRoleData } = useSortedRole();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VNavigationDrawer :model-value="props.isDrawerOpen" temporary location="end" width="800"
|
||||
@update:model-value="handleDrawerModelValueUpdate">
|
||||
<!-- 👉 Header -->
|
||||
<AppDrawerHeaderSection title="Add User" @cancel="$emit('update:isDrawerOpen', false)" />
|
||||
<VDivider />
|
||||
|
||||
<VCard flat>
|
||||
<PerfectScrollbar :options="{ wheelPropagation: false }" class="h-100">
|
||||
<VCardText style="block-size: calc(100vh - 5rem);">
|
||||
<VForm ref="refVForm" @submit.prevent="">
|
||||
<VRow>
|
||||
|
||||
|
||||
<div class="d-flex mb-10">
|
||||
|
||||
<!-- 👉 Avatar -->
|
||||
<VAvatar rounded size="100" class="me-6" :image="accountDataLocal.avatarImg" />
|
||||
|
||||
<!-- 👉 Upload Photo -->
|
||||
<form class="d-flex flex-column justify-center gap-4">
|
||||
<div class="d-flex flex-wrap gap-4">
|
||||
<VBtn color="primary" @click="refInputEl?.click()">
|
||||
<VIcon icon="ri-upload-cloud-line" class="d-sm-none" />
|
||||
<span class="d-none d-sm-block">Upload Logo</span>
|
||||
</VBtn>
|
||||
<input ref="refInputEl" type="file" name="file" accept=".jpeg,.png,.jpg,GIF" hidden
|
||||
@input="changeAvatar">
|
||||
</div>
|
||||
<p class="text-body-1 mb-0">
|
||||
Allowed JPG, GIF or PNG. Max size of 800K
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.first_name" label="First Name" :rules="[requiredValidator]"
|
||||
placeholder="First Name" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.last_name" label="Last Name" :rules="[requiredValidator]"
|
||||
placeholder="Last Name" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.email" label="Email Address"
|
||||
:rules="[requiredValidator, emailValidator]" placeholder="johndoe@email.com" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.password" label="Password" placeholder="············"
|
||||
:type="isPasswordVisible ? 'text' : 'password'"
|
||||
:append-inner-icon="isPasswordVisible ? 'ri-eye-off-line' : 'ri-eye-line'"
|
||||
@click:append-inner="isPasswordVisible = !isPasswordVisible"
|
||||
:rules="[requiredValidator, passwordValidator]" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.phone_no" label="Phone Number" placeholder="+1 (917) 543-9876"
|
||||
:rules="[requiredPhone, validUSAPhone]" @input="formatPhoneNumber" max="14"
|
||||
pattern="^\(\d{3}\) \d{3}-\d{4}$" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VAutocomplete v-model="accountDataLocal.role_id" label="Role" placeholder="Role" density="comfortable"
|
||||
:items="sortedRole" item-title="role" item-value="id" :loading="isLoading" :error-messages="error"
|
||||
:rules="[requiredValidator]" />
|
||||
|
||||
</VCol>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<VCol cols="12">
|
||||
<div class="d-flex justify-start">
|
||||
<VBtn type="submit" color="primary" class="me-4" @click="onSubmit">
|
||||
Save
|
||||
</VBtn>
|
||||
<VBtn color="error" variant="outlined" @click="resetForm">
|
||||
Discard
|
||||
</VBtn>
|
||||
</div>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
</PerfectScrollbar>
|
||||
</VCard>
|
||||
</VNavigationDrawer>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.v-navigation-drawer__content {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
</style>
|
265
resources/js/pages/admin-users/EditUser.vue
Normal file
265
resources/js/pages/admin-users/EditUser.vue
Normal file
@@ -0,0 +1,265 @@
|
||||
<script setup>
|
||||
import avatar1 from '@images/avatars/avatar-1.png';
|
||||
import { PerfectScrollbar } from 'vue3-perfect-scrollbar';
|
||||
import { VForm } from 'vuetify/components/VForm';
|
||||
import { useStore } from 'vuex';
|
||||
const store = useStore()
|
||||
const props = defineProps({
|
||||
isDrawerOpen: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
userData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
})
|
||||
const accountData = {
|
||||
avatarImg: avatar1,
|
||||
name: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
email: '',
|
||||
phone_no: '',
|
||||
password: '',
|
||||
status: '',
|
||||
role_id: ''
|
||||
}
|
||||
const itemId = ref()
|
||||
|
||||
const accountDataLocal = ref(structuredClone(accountData))
|
||||
const refInputEl = ref()
|
||||
const ImageBase64 = ref();
|
||||
const statusList = ref([
|
||||
{ name: 'Active', abbreviation: '1' },
|
||||
{ name: 'De-Active', abbreviation: '0' },
|
||||
|
||||
]);
|
||||
const roleData = ref([]);
|
||||
const useSortedRole = () => {
|
||||
const isLoading = ref(false);
|
||||
const error = ref(null);
|
||||
|
||||
const sortedRole = computed(() => {
|
||||
const allOption = { id: '', role: 'Select Any' };
|
||||
const sortedData = roleData.value.slice().sort((a, b) => {
|
||||
return a.role.localeCompare(b.role);
|
||||
});
|
||||
return [allOption, ...sortedData];
|
||||
});
|
||||
|
||||
const fetchRoleData = async () => {
|
||||
isLoading.value = true;
|
||||
error.value = null;
|
||||
try {
|
||||
await store.dispatch('getAllRolesList');
|
||||
roleData.value = store.getters.getRolesList || [];
|
||||
console.log('Fetched Role data:', roleData.value);
|
||||
} catch (e) {
|
||||
console.error('Error fetching Role data:', e);
|
||||
error.value = 'Failed to fetch Role data';
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(fetchRoleData);
|
||||
|
||||
return { sortedRole, isLoading, error, fetchRoleData };
|
||||
};
|
||||
const { sortedRole, isLoading, error, fetchRoleData } = useSortedRole();
|
||||
const sortedStates = computed(() => {
|
||||
return states.value.slice().sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
});
|
||||
const getUser = computed(async () => {
|
||||
if (props.userData) {
|
||||
|
||||
itemId.value = props.userData.id
|
||||
accountDataLocal.value.email = props.userData.email
|
||||
accountDataLocal.value.name = props.userData.name
|
||||
accountDataLocal.value.first_name = props.userData.name
|
||||
accountDataLocal.value.phone_no = props.userData.phone_no
|
||||
accountDataLocal.value.last_name = props.userData.last_name
|
||||
accountDataLocal.value.role_id = props.userData.role_id
|
||||
|
||||
|
||||
accountDataLocal.value.avatarImg = props.userData.image_path
|
||||
}
|
||||
|
||||
});
|
||||
const isPasswordVisible = ref(false)
|
||||
const emit = defineEmits(['update:isDrawerOpen', 'addedMessage'])
|
||||
const formatPhoneNumber = () => {
|
||||
// Remove non-numeric characters from the input
|
||||
const numericValue = accountDataLocal.value.phone_no.replace(/\D/g, '');
|
||||
|
||||
// Apply formatting logic
|
||||
if (numericValue.length <= 10) {
|
||||
accountDataLocal.value.phone_no = numericValue.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
|
||||
} else {
|
||||
// Limit the input to a maximum of 14 characters
|
||||
const truncatedValue = numericValue.slice(0, 10);
|
||||
accountDataLocal.value.phone_no = truncatedValue.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
|
||||
}
|
||||
};
|
||||
const handleDrawerModelValueUpdate = val => {
|
||||
emit('update:isDrawerOpen', val)
|
||||
}
|
||||
const genders = ref([
|
||||
{ name: 'Male', abbreviation: 'Male' },
|
||||
{ name: 'Female', abbreviation: 'Female' },
|
||||
{ name: 'Other', abbreviation: 'Other' },
|
||||
]);
|
||||
const refVForm = ref()
|
||||
|
||||
const changeAvatar = file => {
|
||||
const fileReader = new FileReader()
|
||||
const { files } = file.target
|
||||
if (files && files.length) {
|
||||
fileReader.readAsDataURL(files[0])
|
||||
fileReader.onload = () => {
|
||||
if (typeof fileReader.result === 'string') {
|
||||
accountDataLocal.value.avatarImg = fileReader.result
|
||||
}
|
||||
ImageBase64.value = fileReader.result.split(',')[1];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onSubmit = async () => {
|
||||
const { valid } = await refVForm.value.validate()
|
||||
if (valid) {
|
||||
|
||||
await store.dispatch('adminUpdateUser', {
|
||||
id: itemId.value,
|
||||
name: accountDataLocal.value.first_name,
|
||||
email: accountDataLocal.value.email,
|
||||
last_name: accountDataLocal.value.last_name,
|
||||
phone_no: accountDataLocal.value.phone_no,
|
||||
role_id: accountDataLocal.value.role_id,
|
||||
password: accountDataLocal.value.password,
|
||||
profile_pic: ImageBase64.value, //ecelData,
|
||||
|
||||
})
|
||||
|
||||
if (!store.getters.getErrorMsg) {
|
||||
emit('addedMessage', 'success')
|
||||
accountDataLocal.value.email = null
|
||||
accountDataLocal.value.name = null
|
||||
accountDataLocal.value.first_name = null
|
||||
accountDataLocal.value.phone_no = null
|
||||
accountDataLocal.value.role_id = null
|
||||
accountDataLocal.value.last_name = null
|
||||
accountDataLocal.value.password = null
|
||||
ImageBase64.value = null
|
||||
accountDataLocal.value.avatarImg = avatar1
|
||||
emit('update:isDrawerOpen', false)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const resetForm = () => {
|
||||
refVForm.value?.reset()
|
||||
emit('update:isDrawerOpen', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VNavigationDrawer :model-value="props.isDrawerOpen" temporary location="end" width="800"
|
||||
@update:model-value="handleDrawerModelValueUpdate">
|
||||
<!-- 👉 Header -->
|
||||
<AppDrawerHeaderSection title="Edit User" @cancel="$emit('update:isDrawerOpen', false)" />
|
||||
<VDivider />
|
||||
|
||||
<VCard flat>
|
||||
<PerfectScrollbar :options="{ wheelPropagation: false }" class="h-100">
|
||||
<VCardText style="block-size: calc(100vh - 5rem);" v-if="getUser">
|
||||
<VForm ref="refVForm" @submit.prevent="">
|
||||
<VRow>
|
||||
|
||||
|
||||
<div class="d-flex mb-10">
|
||||
|
||||
<!-- 👉 Avatar -->
|
||||
<VAvatar rounded size="100" class="me-6" :image="accountDataLocal.avatarImg" />
|
||||
|
||||
<!-- 👉 Upload Photo -->
|
||||
<form class="d-flex flex-column justify-center gap-4">
|
||||
<div class="d-flex flex-wrap gap-4">
|
||||
<VBtn color="primary" @click="refInputEl?.click()">
|
||||
<VIcon icon="ri-upload-cloud-line" class="d-sm-none" />
|
||||
<span class="d-none d-sm-block">Upload Logo</span>
|
||||
</VBtn>
|
||||
<input ref="refInputEl" type="file" name="file" accept=".jpeg,.png,.jpg,GIF" hidden
|
||||
@input="changeAvatar">
|
||||
</div>
|
||||
<p class="text-body-1 mb-0">
|
||||
Allowed JPG, GIF or PNG. Max size of 800K
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.first_name" label="First Name" :rules="[requiredValidator]"
|
||||
placeholder="First Name" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.last_name" label="Last Name" :rules="[requiredValidator]"
|
||||
placeholder="Last Name" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.email" label="Email Address"
|
||||
:rules="[requiredValidator, emailValidator]" placeholder="johndoe@email.com" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.password" label="Password" placeholder="············"
|
||||
:type="isPasswordVisible ? 'text' : 'password'"
|
||||
:append-inner-icon="isPasswordVisible ? 'ri-eye-off-line' : 'ri-eye-line'"
|
||||
@click:append-inner="isPasswordVisible = !isPasswordVisible" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="accountDataLocal.phone_no" label="Phone Number" placeholder="+1 (917) 543-9876"
|
||||
:rules="[requiredPhone, validUSAPhone]" @input="formatPhoneNumber" max="14"
|
||||
pattern="^\(\d{3}\) \d{3}-\d{4}$" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VAutocomplete v-model="accountDataLocal.role_id" label="Role" placeholder="Role" density="comfortable"
|
||||
:items="sortedRole" item-title="role" item-value="id" :loading="isLoading" :error-messages="error"
|
||||
:rules="[requiredValidator]" />
|
||||
|
||||
</VCol>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<VCol cols="12">
|
||||
<div class="d-flex justify-start">
|
||||
<VBtn type="submit" color="primary" class="me-4" @click="onSubmit">
|
||||
Save
|
||||
</VBtn>
|
||||
<VBtn color="error" variant="outlined" @click="resetForm">
|
||||
Discard
|
||||
</VBtn>
|
||||
</div>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
</PerfectScrollbar>
|
||||
</VCard>
|
||||
</VNavigationDrawer>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.v-navigation-drawer__content {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
</style>
|
335
resources/js/pages/admin-users/admin-list.vue
Normal file
335
resources/js/pages/admin-users/admin-list.vue
Normal file
@@ -0,0 +1,335 @@
|
||||
<script setup>
|
||||
import API from '@/api';
|
||||
import { ADMIN_USER_LIST_API } from '@/constants';
|
||||
import AddUser from '@/pages/admin-users/AddUser.vue';
|
||||
import EditUser from '@/pages/admin-users/EditUser.vue';
|
||||
import debounce from 'lodash.debounce';
|
||||
import { useStore } from 'vuex';
|
||||
const isAddCustomerDrawerOpen = ref(false)
|
||||
const isEditCustomerDrawerOpen = ref(false)
|
||||
const store = useStore()
|
||||
const editDialog = ref(false)
|
||||
const addDialog = ref(false)
|
||||
const deleteDialog = ref(false)
|
||||
const search = ref('')
|
||||
const refVForm = ref(null)
|
||||
const refVFormAdd = ref(null)
|
||||
const selectDropdown = ref(false)
|
||||
const selectdataList = ref(null)
|
||||
const defaultItem = ref({
|
||||
id: -1,
|
||||
title: '',
|
||||
slug: '',
|
||||
list_one_title: '',
|
||||
list_sub_title: '',
|
||||
list_two_title: '',
|
||||
price: '',
|
||||
currency:""
|
||||
})
|
||||
const requiredImageValidator = (value) => !!value || 'Please select an image file.'
|
||||
const requiredExcelValidator = (value) => !!value || 'Please select an Excel file.'
|
||||
const imageFile = ref(null)
|
||||
const excelFile = ref(null)
|
||||
const editedItem = ref(defaultItem.value)
|
||||
const editedIndex = ref(-1)
|
||||
const medicineList = ref([])
|
||||
const isLoading = ref(false)
|
||||
const currencySign = ref('$');
|
||||
|
||||
|
||||
|
||||
|
||||
// headers
|
||||
const headers = [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: 'Name',
|
||||
key: 'name',
|
||||
},
|
||||
|
||||
{
|
||||
title: 'email',
|
||||
key: 'email',
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Phone',
|
||||
key: 'phone_no',
|
||||
},
|
||||
|
||||
{
|
||||
title: 'ACTIONS',
|
||||
key: 'actions',
|
||||
},
|
||||
]
|
||||
|
||||
const resolveStatusVariant = status => {
|
||||
if (status === 1)
|
||||
return {
|
||||
color: 'primary',
|
||||
text: 'Current',
|
||||
}
|
||||
else if (status === 2)
|
||||
return {
|
||||
color: 'success',
|
||||
text: 'Professional',
|
||||
}
|
||||
else if (status === 3)
|
||||
return {
|
||||
color: 'error',
|
||||
text: 'Rejected',
|
||||
}
|
||||
else if (status === 4)
|
||||
return {
|
||||
color: 'warning',
|
||||
text: 'Resigned',
|
||||
}
|
||||
else
|
||||
return {
|
||||
color: 'info',
|
||||
text: 'Applied',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const editItem = async (item) => {
|
||||
isEditCustomerDrawerOpen.value = true
|
||||
|
||||
await store.dispatch('singleUserEdit', {
|
||||
id: item.id,
|
||||
})
|
||||
|
||||
editedItem.value = store.getters.getSingleUser
|
||||
console.log(store.getters.getSingleUser)
|
||||
// editDialog.value = true
|
||||
}
|
||||
const addItem = item => {
|
||||
addDialog.value = true
|
||||
}
|
||||
const deleteItem = item => {
|
||||
editedIndex.value = medicineList.value.indexOf(item)
|
||||
editedItem.value = { ...item }
|
||||
deleteDialog.value = true
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const closeDelete = () => {
|
||||
deleteDialog.value = false
|
||||
editedIndex.value = -1
|
||||
editedItem.value = { ...defaultItem.value }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const deleteItemConfirm = async () => {
|
||||
|
||||
await store.dispatch('medicineDelete',{
|
||||
id: editedItem.value.id
|
||||
})
|
||||
|
||||
closeDelete()
|
||||
loadItems({ page: 1, itemsPerPage: itemsPerPage.value, sortBy: [] });
|
||||
defaultItem.value.id= null
|
||||
defaultItem.value.title= null
|
||||
defaultItem.value.slug= null
|
||||
defaultItem.value.list_one_title= null
|
||||
defaultItem.value.list_sub_title= null
|
||||
defaultItem.value.list_two_title= null
|
||||
defaultItem.value.price =null
|
||||
defaultItem.value.currency=null
|
||||
|
||||
}
|
||||
|
||||
const serverItems = ref([]);
|
||||
const loading = ref(true);
|
||||
const totalItems = ref(0);
|
||||
const itemsPerPage = ref(5);
|
||||
|
||||
const loadItems = debounce( async ( { page, itemsPerPage, sortBy }) => {
|
||||
const payload = {
|
||||
page,
|
||||
itemsPerPage,
|
||||
sortBy,
|
||||
filters:{
|
||||
},
|
||||
search:search.value,
|
||||
}
|
||||
console.log("records",page, itemsPerPage, sortBy , ADMIN_USER_LIST_API);
|
||||
loading.value = true;
|
||||
const data = await API.getDataTableRecord(ADMIN_USER_LIST_API, payload, headers);
|
||||
console.log('patientData',data);
|
||||
serverItems.value = data.items;
|
||||
totalItems.value = data.total;
|
||||
loading.value = false;
|
||||
|
||||
},500);
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
const handleParentAdded = async (msg) => {
|
||||
if (msg == 'success') {
|
||||
store.dispatch('updateIsLoading', true)
|
||||
loadItems({ page: 1, itemsPerPage: itemsPerPage.value, sortBy: [] });
|
||||
store.dispatch('updateIsLoading', false)
|
||||
}
|
||||
// You can also trigger a toast or snackbar here to show the message
|
||||
// For example, if using Vuetify:
|
||||
// showSnackbar(msg)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col cols="12" md="12">
|
||||
<VCard title="Users">
|
||||
|
||||
<VCardText >
|
||||
<VRow>
|
||||
|
||||
<VCol cols="12" md="8" class="d-flex align-center">
|
||||
<VBtn color="primary" prepend-icon="ri-add-line" @click="isAddCustomerDrawerOpen = !isAddCustomerDrawerOpen" v-if="$can('read', 'Admin Add')">
|
||||
New User
|
||||
</VBtn>
|
||||
</VCol>
|
||||
<VCol cols="12" md="4" class="d-flex justify-end">
|
||||
<VTextField
|
||||
v-model="search"
|
||||
label="Search"
|
||||
placeholder="Search ..."
|
||||
append-inner-icon="ri-search-line"
|
||||
single-line
|
||||
hide-details
|
||||
dense
|
||||
outlined
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
|
||||
<v-data-table-server
|
||||
v-model:items-per-page="itemsPerPage"
|
||||
:headers="headers"
|
||||
:items="serverItems"
|
||||
:items-length="totalItems"
|
||||
:loading="loading"
|
||||
:search="search"
|
||||
@update:options="loadItems"
|
||||
>
|
||||
<!-- full name -->
|
||||
<template #item.name="{ item }">
|
||||
<div class="d-flex align-center">
|
||||
<!-- avatar -->
|
||||
<VAvatar
|
||||
size="32"
|
||||
:color="item.image_path ? '' : 'primary'"
|
||||
:class="item.image_path ? '' : 'v-avatar-light-bg primary--text'"
|
||||
:variant="!item.image_path ? 'tonal' : undefined"
|
||||
>
|
||||
<VImg
|
||||
v-if="item.image_path"
|
||||
:src="item.image_path"
|
||||
/>
|
||||
<span
|
||||
v-else
|
||||
class="text-sm"
|
||||
>{{ avatarText(item.name) }}</span>
|
||||
</VAvatar>
|
||||
|
||||
<div class="d-flex flex-column ms-3">
|
||||
<span class="d-block font-weight-medium text-high-emphasis text-truncate">{{ item.name +' '+item.last_name }}</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- status -->
|
||||
<template #item.status="{ item }">
|
||||
<VChip
|
||||
:color="resolveStatusVariant(item.status).color"
|
||||
density="comfortable"
|
||||
>
|
||||
{{ resolveStatusVariant(item.status).text }}
|
||||
</VChip>
|
||||
</template>
|
||||
|
||||
<!-- Actions -->
|
||||
<template #item.actions="{ item }">
|
||||
<div class="d-flex gap-1">
|
||||
<IconBtn
|
||||
size="small"
|
||||
@click="editItem(item )"
|
||||
v-if="$can('read', 'Admin Edit')"
|
||||
>
|
||||
<VIcon icon="ri-pencil-line" />
|
||||
</IconBtn>
|
||||
<IconBtn
|
||||
size="small"
|
||||
@click="deleteItem(item)"
|
||||
style="display: none;"
|
||||
>
|
||||
<VIcon icon="ri-delete-bin-line" />
|
||||
</IconBtn>
|
||||
</div>
|
||||
</template>
|
||||
</v-data-table-server>
|
||||
<!-- </VDataTable> -->
|
||||
</VCard>
|
||||
</v-col>
|
||||
|
||||
<AddUser v-model:is-drawer-open="isAddCustomerDrawerOpen" @addedMessage="handleParentAdded" />
|
||||
<EditUser v-model:is-drawer-open="isEditCustomerDrawerOpen" :user-data="store.getters.getSingleUser" @addedMessage="handleParentAdded" />
|
||||
</v-row>
|
||||
|
||||
|
||||
|
||||
<!-- 👉 Delete Dialog -->
|
||||
<VDialog
|
||||
v-model="deleteDialog"
|
||||
max-width="500px"
|
||||
>
|
||||
<VCard>
|
||||
<VCardTitle>
|
||||
Are you sure you want to delete this item?
|
||||
</VCardTitle>
|
||||
|
||||
<VCardActions>
|
||||
<VSpacer />
|
||||
|
||||
<VBtn
|
||||
color="error"
|
||||
variant="outlined"
|
||||
@click="closeDelete"
|
||||
>
|
||||
Cancel
|
||||
</VBtn>
|
||||
|
||||
<VBtn
|
||||
color="success"
|
||||
variant="elevated"
|
||||
@click="deleteItemConfirm"
|
||||
>
|
||||
OK
|
||||
</VBtn>
|
||||
|
||||
<VSpacer />
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
|
||||
|
||||
|
||||
|
||||
</template>
|
||||
<style scoped>
|
||||
.custom-button {
|
||||
width: 100%;
|
||||
height: 48px; /* This value should match the height of your input fields */
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user