Staff Module Update

This commit is contained in:
Leonard Biano
2024-05-14 11:23:57 +08:00
parent 4ccf8e9970
commit 25838d06ea
19 changed files with 911 additions and 62 deletions

View File

@@ -97,7 +97,7 @@ class StaffAdminController extends Controller
$roles = Role::where('id', '>', 1)->get();
}
$departments = Department::where('status', 1)->orderBy('name')->get();
$badges = JobRequestBadge::orderByRaw('-`order` DESC')->get();
$badges = JobRequestBadge::where('active', 1)->orderByRaw('-`order` DESC')->get();
return response()->json([
'staffs' => StaffResource::collection($staffs)->response()->getData(),
@@ -193,7 +193,7 @@ class StaffAdminController extends Controller
$user->phone = $request->phone;
$user->role_id = $request->role_id;
$user->parent_id = $request->parent_id;
$user->password = $request->password != null ? bcrypt($request->password) : $user->password;
$user->is_active = filter_var($request->is_active, FILTER_VALIDATE_BOOLEAN);
$user->date_of_birth = Carbon::parse($request->date_of_birth)->format('Y-m-d');
$user->created_at = Carbon::parse($request->created_at)->format('Y-m-d');
@@ -206,7 +206,6 @@ class StaffAdminController extends Controller
}
$staff->department_id = $request->department_id;
$staff->badges = $request->badges != null ? array_map('intval', $request->badges) : null;
$staff->bank_name = $request->bank_name;
$staff->bank_branch_name = $request->branch_name;
$staff->bank_account_name = $request->account_name;
@@ -259,6 +258,59 @@ class StaffAdminController extends Controller
}
}
public function updateBadges($id, Request $request)
{
try {
$request->validate([
'badges' => 'nullable|array'
]);
$user = User::findOrFail($id);
if($user){
$staff = $user->staff;
$staff->badges = $request->badges;
$staff->save();
return response()->json([
'staff' => $staff,
'message' => 'Staff Badges Updated Successfully'
]);
}
} catch(Exception $e){
return response()->json([
'message' => $e->getMessage()
], 500);
}
}
public function updatePassword($id, Request $request)
{
try {
$request->validate([
'password' => 'required|min:8|confirmed',
'password_confirmation' => 'required',
]);
$user = User::findOrFail($id);
if($user){
$user->password = bcrypt($request->password);
$user->save();
return response()->json([
'message' => 'Staff Password Updated Successfully'
]);
}
} catch(Exception $e){
return response()->json([
'message' => $e->getMessage()
], 500);
}
}
public function uplines(Request $request)
{

View File

@@ -23,10 +23,7 @@ class CreateStaffRequest extends FormRequest
"phone" => "nullable|unique:users,phone",
"username" => "required|unique:users,username",
"email" => "required|email|unique:users,email",
'password' => 'required|min:8|confirmed',
'password_confirmation' => 'required',
'is_active' => 'required',
'badges' => 'nullable|array',
"role_id" => "required|exists:roles,id",
"department_id" => "required|exists:departments,id",
"date_of_birth" => "required|date",

View File

@@ -23,9 +23,7 @@ class UpdateStaffRequest extends FormRequest
"phone" => "nullable|unique:users,phone,".$request->user_id,
"username" => ['required', Rule::unique('users','username')->ignore($request->user_id,'id')],
"email" => ['required', 'email', Rule::unique('users','email')->ignore($request->user_id,'id')],
"password" => "nullable|min:8",
'is_active' => 'required',
'badges' => 'nullable|array',
"role_id" => "required",
"date_of_birth" => "required|date",
"address" => "nullable|max:200",

0
Modules/Staff/Public/css/primeicons.css Normal file → Executable file
View File

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
{
"/js/staff.js": "/js/staff.js?id=3fdb072f7603d2943cfd7d01f9fb143f",
"/js/staff.js": "/js/staff.js?id=774f6ff8a640945a367944d8f5b7463f",
"/css/staff.css": "/css/staff.css?id=2b8d2ada24eb27a8b7917da64616e20b",
"/css/primeicons.css": "/css/primeicons.css?id=0f5507c54bcec97f5c297bf7fce402ec",
"/css/fonts/primeicons.eot": "/css/fonts/primeicons.eot?id=5447280781a6f00cb73c4f0ffd5db7db",

View File

@@ -52,6 +52,7 @@ import TriStateCheckbox from 'primevue/tristatecheckbox';
import TabView from 'primevue/tabview';
import TabPanel from 'primevue/tabpanel';
import InputSwitch from 'primevue/inputswitch';
import Listbox from 'primevue/listbox';
@@ -107,5 +108,6 @@ app.component('DataView', DataView);
app.component('DataViewLayoutOptions', DataViewLayoutOptions);
app.component('ProgressSpinner', ProgressSpinner);
app.component('InputSwitch', InputSwitch);
app.component('Listbox', Listbox);
app.mount('#staffs');

View File

@@ -0,0 +1,109 @@
<template>
<Dialog v-if="visible" :visible="true" @update:visible="close" :style="{ width: '30vw'}" :breakpoints="{ '1199px': '30vw', '991px': '75vw' , '760px': '95vw' }" header="Update Badges" modal class="p-fluid" :baseZIndex="99999">
<div class="row position-relative">
<div class="col-12">
<Listbox v-model="form.badges" :options="badgeOptions" optionLabel="name" optionValue="id" multiple filter class="w-full" >
<template #option="slotProps">
<div class="flex align-items-center">
<img :alt="slotProps.option.name" :src="slotProps.option.image_url" style="width: 35px" />
<div class="ml-2">{{ slotProps.option.name }}</div>
</div>
</template>
</Listbox>
</div>
<div v-if="loading" class="position-absolute w-100 h-100 d-flex justify-content-center align-items-center">
<ProgressSpinner></ProgressSpinner>
</div>
</div>
<template #footer>
<div class="flex gap-2 justify-content-end">
<Button label="Cancel" class="p-button-sm" @click="close"></Button>
<Button label="Save" class="p-button-sm" :disabled="loading" :loading="loading" @click="save"></Button>
</div>
</template>
</Dialog>
<Toast />
</template>
<script setup>
import axios from 'axios'
import { defineEmits, defineProps, onMounted, ref } from 'vue'
import { useToast } from 'primevue/usetoast';
const props = defineProps({
badgeOptions: {
type: Array,
required: true,
}
});
const emit = defineEmits(['success'])
const toast = useToast();
const visible = ref(false);
const loading = ref(false);
const staff = ref(null);
const form = ref({
badges: []
});
const errors = ref({});
const show = (options) => {
staff.value = null;
if (options) {
form.value.badges = options.staff.badges;
staff.value = options.staff;
}
visible.value = true;
};
const save = () => {
loading.value = true;
errors.value = {};
axios.post(`/admin/staffs/update/${staff.value.user_id}/badges`, form.value).then(response => {
loading.value = false;
toast.add({ severity: 'success', summary: 'Success', detail: response.data.message, life: 3000 });
emit('success')
close();
}).catch(error => {
const { response } = error;
const { status, data } = response;
if (status == 422) {
errors.value = data.errors;
toast.add({ severity: 'warn', summary: 'Warning', detail: 'Some data is missing.', life: 3000 });
}
else {
toast.add({ severity: 'error', summary: 'Error', detail: 'Unknown error occured. Please try again.', life: 3000 });
}
loading.value = false;
});
};
const close = () => {
visible.value = false;
};
const hasError = (name) => {
if (errors.value[name]) {
return true;
}
return false;
};
const getError = (name) => {
return errors.value[name][0];
};
defineExpose({
show
});
</script>

View File

@@ -0,0 +1,315 @@
<template>
<Dialog v-if="visible" :visible="true" @update:visible="close" :style="{ width: '50vw' }" :header="header" modal :baseZIndex="99999">
<div class="row position-relative">
<div class="col-md-12">
<div class="row">
<div class="col-6">
<div class="py-1 flex flex-column justify-content-center align-items-center">
<div id='profile-upload' :style="{backgroundImage: 'url(' + preview + ')'}">
<div class="hvr-profile-img">
<input type="file" name="avatar" class="upload" title="Dimensions 200 X 200" accept="image/*" @change="previewImage" :error="errors?.photo ? errors.photo[0] : null">
</div>
<i class="fa fa-camera"></i>
</div>
<div class="label mt-2">Profile Photo</div>
</div>
</div>
<div class="col-6">
<div class="py-1 flex flex-column justify-content-center align-items-center">
<div id='profile-upload' class="ott" :style="{backgroundImage: 'url(' + previewOtt + ')'}">
<div class="hvr-profile-img">
<input type="file" name="ott_photo" class="upload" accept="image/*" @change="previewOttImage" :error="errors?.ott_photo ? errors.ott_photo[0] : null">
</div>
<i class="fa fa-camera"></i>
</div>
<div class="label mt-2">OTT Photo</div>
</div>
</div>
<div class="col-12">
<div class="main-title d-flex">
<h3 class="mb-0">Personal Details</h3>
</div>
</div>
<div class="col-6">
<div class="label">First Name</div>
<InputText v-model="data.first_name" class="w-100" :invalid="errors?.first_name"></InputText>
<small v-if="errors?.first_name" class="text-danger">{{ errors.first_name[0] }}</small>
</div>
<div class="col-6">
<div class="label">Last Name</div>
<InputText v-model="data.last_name" class="w-100" :invalid="errors?.last_name"></InputText>
<small v-if="errors?.last_name" class="text-danger">{{ errors.last_name[0] }}</small>
</div>
<div class="col-6">
<div class="label">Username</div>
<InputText v-model="data.username" class="w-100" :invalid="errors?.username"></InputText>
<small v-if="errors?.username" class="text-danger">{{ errors.username[0] }}</small>
</div>
<div class="col-6">
<div class="label">Email</div>
<InputText v-model="data.email" type="email" autocomplete="off" class="w-100" :invalid="errors?.email"></InputText>
<small v-if="errors?.email" class="text-danger">{{ errors.email[0] }}</small>
</div>
<div class="col-6">
<div class="label">Date of Birth</div>
<Calendar v-model="data.date_of_birth" dateFormat="yy-mm-dd" class="w-100" :invalid="errors?.date_of_birth"/>
<small v-if="errors?.date_of_birth" class="text-danger">{{ errors.date_of_birth[0] }}</small>
</div>
<div class="col-6">
<div class="label">Phone</div>
<InputText v-model="data.phone" class="w-100" :invalid="errors?.phone"></InputText>
<small v-if="errors?.phone" class="text-danger">{{ errors.phone[0] }}</small>
</div>
<div class="col-6">
<div class="label">Role</div>
<Dropdown v-model="data.role_id" filter showClear :options="roleOptions" optionValue="id" optionLabel="name" placeholder="Select Role" class="w-100" :invalid="errors?.role_id"/>
<small v-if="errors?.role_id" class="text-danger">{{ errors.role_id[0] }}</small>
</div>
<div class="col-6">
<div class="label">Department</div>
<Dropdown v-model="data.department_id" filter showClear :options="departmentOptions" optionValue="id" optionLabel="name" placeholder="Select Department" class="w-100" :invalid="errors?.department_id"/>
<small v-if="errors?.department_id" class="text-danger">{{ errors.department_id[0] }}</small>
</div>
<div class="col-6">
<div class="label">Upline (Team Lead) </div>
<Dropdown v-model="data.parent_id" filter showClear :options="uplineOptions" optionValue="user.id" optionLabel="user.name" placeholder="Select Upline" class="w-full">
<template #option="{ option }">
<div class="flex items-center gap-2">
<Avatar v-if="option.user.avatar" :image="`https://wticreatorstudio.com/public/${option.user.avatar}`" shape="circle"></Avatar>
<Avatar v-else shape="circle"></Avatar>
<div>
<div>{{ option.user.name }} - <b>{{option.user.role.name}}</b></div>
<div class="text-xs opacity-50">Email: {{ option.user.email }}</div>
</div>
</div>
</template>
</Dropdown>
<small v-if="errors?.parent_id" class="text-danger">{{ errors.parent_id[0] }}</small>
</div>
<div class="col-6">
<div class="label">Date of Joining</div>
<Calendar v-model="data.created_at" dateFormat="yy-mm-dd" class="w-100" :invalid="errors?.created_at"/>
<small v-if="errors?.created_at" class="text-danger">{{ errors.created_at[0] }}</small>
</div>
<div class="col-12">
<div class="label">Address</div>
<Text-Area v-model="data.address" rows="3" cols="10" class="w-100"/>
</div>
<div class="col-6">
<div class="label">Status</div>
<SelectButton v-model="data.is_active" :options="statusOptions" optionLabel="label" optionValue="value" class="w-full" />
</div>
</div>
</div>
<div class="col-md-12">
<div class="row">
<div class="col-12">
<div class="main-title d-flex">
<h3 class="mb-0">Bank Details</h3>
</div>
</div>
<div class="col-6">
<div class="label">Bank Name</div>
<InputText v-model="data.bank_name" class="w-100" :invalid="errors?.bank_name"></InputText>
<small v-if="errors?.bank_name" class="text-danger">{{ errors.bank_name[0] }}</small>
</div>
<div class="col-6">
<div class="label">Branch Name</div>
<InputText v-model="data.branch_name" class="w-100" :invalid="errors?.branch_name"></InputText>
<small v-if="errors?.branch_name" class="text-danger">{{ errors.branch_name[0] }}</small>
</div>
<div class="col-6">
<div class="label">Account Name</div>
<InputText v-model="data.account_name" class="w-100" :invalid="errors?.account_number"></InputText>
<small v-if="errors?.account_name" class="text-danger">{{ errors.account_name[0] }}</small>
</div>
<div class="col-6">
<div class="label">Account Number</div>
<InputText v-model="data.account_number" class="w-100" :invalid="errors?.account_number"></InputText>
<small v-if="errors?.account_number" class="text-danger">{{ errors.account_number[0] }}</small>
</div>
</div>
</div>
<div v-if="loading" class="position-absolute w-100 h-100 d-flex justify-content-center align-items-center">
<ProgressSpinner></ProgressSpinner>
</div>
</div>
<template #footer>
<div class="flex gap-2 justify-content-end">
<button class="primary-btn semi_large1 fix-gr-bg" @click="close">Cancel</button>
<button class="primary-btn semi_large1 fix-gr-bg" :disabled="loading ? true : false" @click="save">
<i class="ti-check"></i>
<span>{{ mode == 'add' ? 'Save' : 'Update' }}</span>
</button>
</div>
</template>
</Dialog>
<Toast />
</template>
<script setup>
import axios from 'axios'
import { defineEmits, defineProps, ref } from 'vue'
import { useToast } from 'primevue/usetoast';
const toast = useToast();
const emit = defineEmits(['success'])
const props = defineProps({
roleOptions: {
type: Array,
required: true,
},
departmentOptions: {
type: Array,
required: true,
},
uplineOptions: {
type: Array,
required: true,
}
});
const visible = ref(false);
const loading = ref(false);
const header = ref(null);
const mode = ref('add');
const preview = ref(null);
const previewOtt = ref(null);
const data = ref({});
const statusOptions = ref([
{ label: 'Active', value: true},
{ label: 'Inactive', value: false},
]);
const staff = ref(null);
const errors = ref({});
const show = (options) => {
data.value = {};
data.value.is_active = true;
staff.value = null;
errors.value = {};
mode.value = options.mode;
preview.value = '/public/frontend/default/img/avatar.jpg';
previewOtt.value = '/public/frontend/default/img/avatar.jpg';
if (options) {
header.value = options.title;
if(options.mode == 'edit'){
data.value = options.data;
data.value.date_of_birth = new Date(options.data.date_of_birth);
data.value.created_at = new Date(options.data.created_at);
if(options.data.avatar != null){
preview.value = options.data.avatar;
data.value.photo = null;
}
if(options.data.ott_photo != null){
previewOtt.value = options.data.ott_photo;
data.value.ott_photo = null;
}
staff.value = options.staff;
}
}
visible.value = true;
};
const save = () => {
loading.value = true;
errors.value = {};
if (mode.value == 'edit') {
axios.post(`/admin/staffs/update/${staff.value}`, data.value, { headers: {
"Content-Type": "multipart/form-data"
}}).then(response => {
loading.value = false;
toast.add({ severity: 'success', summary: 'Success', detail: response.data.message, life: 3000 });
emit('success')
close();
}).catch(error => {
const { response } = error;
const { status, data } = response;
if (status == 422) {
errors.value = data.errors;
toast.add({ severity: 'warn', summary: 'Warning', detail: 'Some data is missing.', life: 3000 });
}
else {
toast.add({ severity: 'error', summary: 'Error', detail: 'Unknown error occured. Please try again.', life: 3000 });
}
loading.value = false;
});
} else {
axios.post('/admin/staffs/store', data.value, { headers: {
"Content-Type": "multipart/form-data"
}}).then(response => {
loading.value = false;
toast.add({ severity: 'success', summary: 'Success', detail: response.data.message, life: 3000 });
emit('success')
close();
}).catch(error => {
const { response } = error;
const { status, data } = response;
if (status == 422) {
errors.value = data.errors;
toast.add({ severity: 'warn', summary: 'Warning', detail: 'Some data is missing.', life: 3000 });
}
else {
toast.add({ severity: 'error', summary: 'Error', detail: 'Unknown error occured. Please try again.', life: 3000 });
}
loading.value = false;
});
}
};
const close = () => {
visible.value = false;
};
const previewImage = (event) => {
var input = event.target;
if (input.files) {
var reader = new FileReader();
reader.onload = (e) => {
preview.value = e.target.result;
}
data.value.photo = input.files[0];
console.log(data.value.photo)
reader.readAsDataURL(input.files[0]);
}
};
const previewOttImage = (event) => {
var input = event.target;
if (input.files) {
var reader = new FileReader();
reader.onload = (e) => {
previewOtt.value = e.target.result;
}
data.value.ott_photo = input.files[0];
reader.readAsDataURL(input.files[0]);
}
};
defineExpose({
show
});
</script>

View File

@@ -0,0 +1,98 @@
<template>
<Dialog v-if="visible" :visible="true" @update:visible="close" :style="{ width: '30vw'}" :breakpoints="{ '1199px': '30vw', '991px': '75vw' , '760px': '95vw' }" header="Change Password" modal class="p-fluid" :baseZIndex="99999">
<div class="row position-relative">
<div class="col-12">
<div class="label">New Password</div>
<InputText v-model="form.password" type="password" autocomplete="off" class="w-100" :invalid="errors?.password"></InputText>
<small v-if="errors?.password" class="text-danger">{{ errors.password[0] }}</small>
</div>
<div class="col-12">
<div class="label">Confirm New Password</div>
<InputText v-model="form.password_confirmation" type="password" autocomplete="off" class="w-100" :invalid="errors?.password_confirmation"></InputText>
<small v-if="errors?.password_confirmation" class="text-danger">{{ errors.password_confirmation[0] }}</small>
</div>
<div v-if="loading" class="position-absolute w-100 h-100 d-flex justify-content-center align-items-center">
<ProgressSpinner></ProgressSpinner>
</div>
</div>
<template #footer>
<div class="flex gap-2 justify-content-end">
<Button label="Cancel" class="p-button-sm" @click="close"></Button>
<Button label="Save" class="p-button-sm" :disabled="loading" :loading="loading" @click="save"></Button>
</div>
</template>
</Dialog>
<Toast />
</template>
<script setup>
import axios from 'axios'
import { defineEmits, defineProps, onMounted, ref } from 'vue'
import { useToast } from 'primevue/usetoast';
const toast = useToast();
const visible = ref(false);
const loading = ref(false);
const staff = ref(null);
const form = ref({});
const errors = ref({});
const show = (options) => {
staff.value = null;
if (options) {
staff.value = options.staff;
}
visible.value = true;
};
const save = () => {
loading.value = true;
errors.value = {};
axios.post(`/admin/staffs/update/${staff.value}/password`, form.value).then(response => {
loading.value = false;
toast.add({ severity: 'success', summary: 'Success', detail: response.data.message, life: 3000 });
close();
}).catch(error => {
const { response } = error;
const { status, data } = response;
if (status == 422) {
errors.value = data.errors;
toast.add({ severity: 'warn', summary: 'Warning', detail: 'Some data is missing.', life: 3000 });
}
else {
toast.add({ severity: 'error', summary: 'Error', detail: 'Unknown error occured. Please try again.', life: 3000 });
}
loading.value = false;
});
};
const close = () => {
visible.value = false;
};
const hasError = (name) => {
if (errors.value[name]) {
return true;
}
return false;
};
const getError = (name) => {
return errors.value[name][0];
};
defineExpose({
show
});
</script>

View File

@@ -26,7 +26,13 @@
<TabView>
<TabPanel header="Profile">
<Profile :staff="staff" :roles="roles" :badges="badges" :departments="departments" :uplines="uplines" @update="handleUpdate"></Profile>
<Profile :staff="staff" :roles="roles" :departments="departments" :uplines="uplines"></Profile>
</TabPanel>
<TabPanel header="Badges">
<Badge :staff="staff" :badges="badges" @update="handleUpdate"></Badge>
</TabPanel>
<TabPanel header="Password">
<Password :user_id="staff.user.id"></Password>
</TabPanel>
<TabPanel v-if="checkPermission('job_board.creator.index')" header="Jobs">
<Jobs :staff_id="staff.user.id"></Jobs>
@@ -61,6 +67,8 @@
import Referrals from './details/Referrals.vue';
import Contact from './details/Contact.vue';
import Video from './details/Video.vue';
import Badge from './details/Badge.vue';
import Password from './details/Password.vue';
const toast = useToast();
const props = defineProps({

View File

@@ -150,7 +150,6 @@
<div class="flex justify-center align-items-center gap-2">
<SelectButton v-model="filterModel.value" :options="[{ label: 'Active', status: 1 }, { label: 'Inactive', status: 0 }]" optionValue="status" optionLabel="label" aria-labelledby="basic" class="w-full"/>
</div>
</template>
</Column>
@@ -167,6 +166,8 @@
<div class="d-flex gap-10 justify-content-center">
<Button v-show="checkPermission('staffs.view')" @click="handleViewStaff(slotProps.data.id)" icon="pi pi-info-circle" v-tooltip.top="'Details'" rounded severity="info" />
<Button v-show="checkPermission('staffs.edit')" @click="handleEditStaff(slotProps.data)" icon="pi pi-pencil" v-tooltip.top="'Edit'" rounded />
<Button v-show="checkPermission('staffs.edit')" @click="handleEditBadges(slotProps.data)" icon="pi pi-star" v-tooltip.top="'Update Badges'" severity="success" rounded />
<Button v-show="checkPermission('staffs.edit')" @click="handleEditPassword(slotProps.data)" icon="pi pi-lock" v-tooltip.top="'Change Password'" severity="danger" rounded />
</div>
</template>
</Column>
@@ -178,7 +179,9 @@
</Card>
<Toast />
<StaffDialog ref="staffDialogRef" @success="handleSuccess" :roleOptions="roleOptions" :departmentOptions="departmentOptions" :uplineOptions="uplineOptions" :badgeOptions="badgeOptions"/>
<DetailsDialog ref="staffDialogRef" @success="handleSuccess" :roleOptions="roleOptions" :departmentOptions="departmentOptions" :uplineOptions="uplineOptions" />
<BadgeDialog ref="badgeDialogRef" @success="handleSuccess" :badgeOptions="badgeOptions"/>
<PasswordDialog ref="passwordDialogRef"/>
<ConfirmDialog/>
</template>
@@ -199,7 +202,9 @@
<script setup>
import axios from 'axios'
import { inject, onMounted, ref, watch } from 'vue'
import StaffDialog from './StaffDialog.vue';
import DetailsDialog from './Dialogs/DetailsDialog.vue';
import PasswordDialog from './Dialogs/PasswordDialog.vue';
import BadgeDialog from './Dialogs/BadgeDialog.vue';
import { FilterMatchMode, FilterOperator } from 'primevue/api';
import { useConfirm } from "primevue/useconfirm";
import { useToast } from "primevue/usetoast";
@@ -219,6 +224,8 @@ const loadingStaffs = ref(true)
const loadingDelete = ref(false)
const selectedProduct = ref({})
const staffDialogRef = ref(null);
const passwordDialogRef = ref(null);
const badgeDialogRef = ref(null);
const first = ref(0);
const totalRecords = ref(0);
const lazyParams = ref({})
@@ -327,6 +334,14 @@ const handleEditStaff = (staff) => {
staffDialogRef.value.show({ title: 'Edit Staff', data, mode: 'edit', staff: staff.user_id });
}
const handleEditBadges = (staff) => {
badgeDialogRef.value.show({staff});
}
const handleEditPassword = (staff) => {
passwordDialogRef.value.show({staff: staff.user_id });
}
const handleViewStaff = (staff_id) => {
window.open(`/admin/staffs/details/${staff_id}`, "_blank");
}

View File

@@ -0,0 +1,76 @@
<template>
<div class="grid w-full">
<div class="col-12 md:col-6 md:col-offset-3">
<Listbox v-model="form.badges" :options="badges" optionLabel="name" optionValue="id" multiple filter class="w-full" >
<template #option="slotProps">
<div class="flex align-items-center">
<img :alt="slotProps.option.name" :src="slotProps.option.image_url" style="width: 35px" />
<div class="ml-2">{{ slotProps.option.name }}</div>
</div>
</template>
</Listbox>
</div>
<div class="col-12 md:col-6 md:col-offset-3">
<Button label="Update" @click="handleUpdateBadges" :loading="loading" icon="pi pi-save" class="w-auto"></Button>
</div>
<div v-if="loading" class="position-absolute w-100 h-100 d-flex justify-content-center align-items-center">
<ProgressSpinner></ProgressSpinner>
</div>
</div>
</template>
<script setup>
import axios from 'axios'
import { onMounted, defineProps, defineEmits, ref } from 'vue'
import { useToast } from 'primevue/usetoast';
const props = defineProps({
staff: {
type: Object,
required: true,
},
badges: {
type: Object,
required: true,
},
});
const emits = defineEmits([
'update'
]);
const toast = useToast();
const loading = ref(false);
const form = ref({});
const errors = ref({});
const handleUpdateBadges = () => {
loading.value = true;
axios.post(`/admin/staffs/update/${props.staff.user.id}/badges`, form.value).then(response => {
loading.value = false;
toast.add({ severity: 'success', summary: 'Success', detail: response.data.message, life: 3000 });
emits('update', response.data.staff);
}).catch(error => {
const { response } = error;
const { status, data } = response;
if (status == 422) {
errors.value = data.errors;
toast.add({ severity: 'warn', summary: 'Warning', detail: 'Some data is missing.', life: 3000 });
}
else {
toast.add({ severity: 'error', summary: 'Error', detail: 'Unknown error occured. Please try again.', life: 3000 });
}
loading.value = false;
});
}
onMounted(() => {
form.value.badges = props.staff.badges;
})
</script>

View File

@@ -0,0 +1,63 @@
<template>
<div class="grid w-full">
<div class="col-12 md:col-6 md:col-offset-3">
<div class="label">New Password</div>
<InputText v-model="form.password" type="password" autocomplete="off" class="w-100" :invalid="errors?.password"></InputText>
<small v-if="errors?.password" class="text-danger">{{ errors.password[0] }}</small>
</div>
<div class="col-12 md:col-6 md:col-offset-3">
<div class="label">Confirm New Password</div>
<InputText v-model="form.password_confirmation" type="password" autocomplete="off" class="w-100" :invalid="errors?.password_confirmation"></InputText>
<small v-if="errors?.password_confirmation" class="text-danger">{{ errors.password_confirmation[0] }}</small>
</div>
<div class="col-12 md:col-6 md:col-offset-3">
<Button label="Update" @click="handleUpdatePassword" :loading="loading" icon="pi pi-save" class="w-auto"></Button>
</div>
<div v-if="loading" class="position-absolute w-100 h-100 d-flex justify-content-center align-items-center">
<ProgressSpinner></ProgressSpinner>
</div>
</div>
</template>
<script setup>
import axios from 'axios'
import { onMounted, defineProps, ref } from 'vue'
import { useToast } from 'primevue/usetoast';
const props = defineProps({
user_id: {
type: Number,
required: true,
}
});
const toast = useToast();
const loading = ref(false);
const form = ref({});
const errors = ref({});
const handleUpdatePassword = () => {
loading.value = true;
axios.post(`/admin/staffs/update/${props.user_id}/password`, form.value).then(response => {
loading.value = false;
toast.add({ severity: 'success', summary: 'Success', detail: response.data.message, life: 3000 });
}).catch(error => {
const { response } = error;
const { status, data } = response;
if (status == 422) {
errors.value = data.errors;
toast.add({ severity: 'warn', summary: 'Warning', detail: 'Some data is missing.', life: 3000 });
}
else {
toast.add({ severity: 'error', summary: 'Error', detail: 'Unknown error occured. Please try again.', life: 3000 });
}
loading.value = false;
});
}
</script>

View File

@@ -30,16 +30,7 @@
<InputText v-model="form.phone" class="w-100" :invalid="errors?.phone"></InputText>
<small v-if="errors?.phone" class="text-danger">{{ errors.phone[0] }}</small>
</div>
<div class="col-12 md:col-6">
<div class="label">Password <small>(Leave blank if you dont want to update the staff password)</small></div>
<InputText v-model="form.password" type="password" autocomplete="off" class="w-100" :invalid="errors?.password"></InputText>
<small v-if="errors?.password" class="text-danger">{{ errors.password[0] }}</small>
</div>
<div class="col-12 md:col-6">
<div class="label">Confirm Password <small>(Leave blank if you dont want to update the staff password)</small></div>
<InputText v-model="form.password_confirmation" type="password" autocomplete="off" class="w-100" :invalid="errors?.password_confirmation"></InputText>
<small v-if="errors?.password_confirmation" class="text-danger">{{ errors.password_confirmation[0] }}</small>
</div>
<div class="col-12 md:col-6">
<div class="label">Role</div>
<Dropdown v-model="form.role_id" filter showClear :options="roles" optionValue="id" optionLabel="name" placeholder="Select Role" class="w-100" :invalid="errors?.role_id"/>
@@ -76,17 +67,6 @@
<Text-Area v-model="form.address" rows="3" cols="10" class="w-100"/>
</div>
<div class="col-6">
<div class="label">Badges</div>
<MultiSelect v-model="form.badges" :options="badges" optionLabel="name" optionValue="id" placeholder="Select badge" display="chip" class="p-inputtext-sm w-100">
<template #option="slotProps">
<div class="flex align-items-center">
<img :alt="slotProps.option.name" :src="slotProps.option.image_url" style="width: 35px" />
<div class="ml-2">{{ slotProps.option.name }}</div>
</div>
</template>
</MultiSelect>
</div>
<div class="col-6">
<div class="label">Status</div>
<SelectButton v-model="form.is_active" :options="[{ label: 'Active', status: true},{ label: 'Inactive', status: false}]" optionLabel="label" optionValue="status" class="w-full" />
@@ -141,10 +121,6 @@
type: Object,
required: true,
},
badges: {
type: Object,
required: true,
},
uplines: {
type: Object,
required: true,

View File

@@ -18,6 +18,8 @@ Route::prefix('admin')->middleware(['auth','admin'])->as('admin.')->group(functi
Route::post('/staffs/store', 'StaffAdminController@store')->name('staffs.store');
Route::post('/staffs/update/{id}', 'StaffAdminController@update')->name('staffs.update');
Route::post('/staffs/update/{id}/status', 'StaffAdminController@updateStatus')->name('staffs.update-status');
Route::post('/staffs/update/{id}/badges', 'StaffAdminController@updateBadges')->name('staffs.update-badges');
Route::post('/staffs/update/{id}/password', 'StaffAdminController@updatePassword')->name('staffs.update-password');
Route::get('/staffs/details/{id}', 'StaffAccountController@index')->name('staffs.details');
Route::get('/staffs/details/{id}/jobs/data', 'StaffAccountController@jobsData')->name('staffs.details.jobs');

View File

@@ -22,7 +22,9 @@
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"laravel-mix": "^6.0.31",
"laravel-mix-merge-manifest": "^2.0.0"
"laravel-mix-merge-manifest": "^2.0.0",
"sass": "^1.77.1",
"sass-loader": "^12.6.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -1932,6 +1934,7 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
@@ -1945,6 +1948,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -1953,6 +1957,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -1961,6 +1966,7 @@
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
@@ -1975,6 +1981,7 @@
"version": "0.3.22",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz",
"integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
@@ -2123,6 +2130,7 @@
"version": "8.56.2",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
"integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==",
"dev": true,
"dependencies": {
"@types/estree": "*",
"@types/json-schema": "*"
@@ -2132,6 +2140,7 @@
"version": "3.7.7",
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
"integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
"dev": true,
"dependencies": {
"@types/eslint": "*",
"@types/estree": "*"
@@ -2140,7 +2149,8 @@
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
},
"node_modules/@types/express": {
"version": "4.17.21",
@@ -2240,7 +2250,8 @@
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true
},
"node_modules/@types/mime": {
"version": "1.3.5",
@@ -2258,6 +2269,7 @@
"version": "20.11.17",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz",
"integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
}
@@ -2454,6 +2466,7 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
"integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
"dev": true,
"dependencies": {
"@webassemblyjs/helper-numbers": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
@@ -2462,22 +2475,26 @@
"node_modules/@webassemblyjs/floating-point-hex-parser": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw=="
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
"dev": true
},
"node_modules/@webassemblyjs/helper-api-error": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q=="
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
"dev": true
},
"node_modules/@webassemblyjs/helper-buffer": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA=="
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
"dev": true
},
"node_modules/@webassemblyjs/helper-numbers": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
"dev": true,
"dependencies": {
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
"@webassemblyjs/helper-api-error": "1.11.6",
@@ -2487,12 +2504,14 @@
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA=="
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
"dev": true
},
"node_modules/@webassemblyjs/helper-wasm-section": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
"integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
@@ -2504,6 +2523,7 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
"dev": true,
"dependencies": {
"@xtuc/ieee754": "^1.2.0"
}
@@ -2512,6 +2532,7 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
"dev": true,
"dependencies": {
"@xtuc/long": "4.2.2"
}
@@ -2519,12 +2540,14 @@
"node_modules/@webassemblyjs/utf8": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA=="
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
"dev": true
},
"node_modules/@webassemblyjs/wasm-edit": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
"integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
@@ -2540,6 +2563,7 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
"integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
@@ -2552,6 +2576,7 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
"integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
@@ -2563,6 +2588,7 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
"integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-api-error": "1.11.6",
@@ -2576,6 +2602,7 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
"integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@xtuc/long": "4.2.2"
@@ -2620,12 +2647,14 @@
"node_modules/@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
"dev": true
},
"node_modules/@xtuc/long": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
"node_modules/accepts": {
"version": "1.3.8",
@@ -2644,6 +2673,7 @@
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2655,6 +2685,7 @@
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
"integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
"dev": true,
"peerDependencies": {
"acorn": "^8"
}
@@ -2663,6 +2694,7 @@
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -2717,6 +2749,7 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"dev": true,
"peerDependencies": {
"ajv": "^6.9.1"
}
@@ -3205,6 +3238,7 @@
"version": "4.22.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz",
"integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==",
"dev": true,
"funding": [
{
"type": "opencollective",
@@ -3246,7 +3280,8 @@
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"node_modules/buffer-xor": {
"version": "1.0.3",
@@ -3323,6 +3358,7 @@
"version": "1.0.30001587",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz",
"integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==",
"dev": true,
"funding": [
{
"type": "opencollective",
@@ -3390,6 +3426,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
"dev": true,
"engines": {
"node": ">=6.0"
}
@@ -4304,7 +4341,8 @@
"node_modules/electron-to-chromium": {
"version": "1.4.668",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.668.tgz",
"integrity": "sha512-ZOBocMYCehr9W31+GpMclR+KBaDZOoAEabLdhpZ8oU1JFDwIaFY0UDbpXVEUFc0BIP2O2Qn3rkfCjQmMR4T/bQ=="
"integrity": "sha512-ZOBocMYCehr9W31+GpMclR+KBaDZOoAEabLdhpZ8oU1JFDwIaFY0UDbpXVEUFc0BIP2O2Qn3rkfCjQmMR4T/bQ==",
"dev": true
},
"node_modules/elliptic": {
"version": "6.5.4",
@@ -4355,6 +4393,7 @@
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@@ -4417,12 +4456,14 @@
"node_modules/es-module-lexer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz",
"integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w=="
"integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==",
"dev": true
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"dev": true,
"engines": {
"node": ">=6"
}
@@ -4446,6 +4487,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
"dev": true,
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
@@ -4458,6 +4500,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
"dependencies": {
"estraverse": "^5.2.0"
},
@@ -4469,6 +4512,7 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
"engines": {
"node": ">=4.0"
}
@@ -4477,6 +4521,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true,
"engines": {
"node": ">=4.0"
}
@@ -4514,6 +4559,7 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"dev": true,
"engines": {
"node": ">=0.8.x"
}
@@ -4626,7 +4672,8 @@
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"node_modules/fast-glob": {
"version": "3.3.2",
@@ -4647,7 +4694,8 @@
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true
},
"node_modules/fastest-levenshtein": {
"version": "1.0.16",
@@ -5524,6 +5572,12 @@
"node": ">=4.0.0"
}
},
"node_modules/immutable": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz",
"integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==",
"dev": true
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -5756,6 +5810,7 @@
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
"dev": true,
"dependencies": {
"@types/node": "*",
"merge-stream": "^2.0.0",
@@ -5769,6 +5824,7 @@
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -5805,12 +5861,14 @@
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"dev": true
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"node_modules/json5": {
"version": "2.2.3",
@@ -5976,6 +6034,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
"dev": true,
"engines": {
"node": ">=6.11.5"
}
@@ -6141,7 +6200,8 @@
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
"node_modules/merge2": {
"version": "1.4.1",
@@ -6209,6 +6269,7 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -6217,6 +6278,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
@@ -6372,7 +6434,8 @@
"node_modules/neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"node_modules/no-case": {
"version": "3.0.4",
@@ -6441,7 +6504,8 @@
"node_modules/node-releases": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
"dev": true
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -7550,6 +7614,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"dependencies": {
"safe-buffer": "^5.1.0"
}
@@ -7882,6 +7947,7 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
@@ -7903,6 +7969,61 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
"node_modules/sass": {
"version": "1.77.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.77.1.tgz",
"integrity": "sha512-OMEyfirt9XEfyvocduUIOlUSkWOXS/LAt6oblR/ISXCTukyavjex+zQNm51pPCOiFKY1QpWvEH1EeCkgyV3I6w==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-loader": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz",
"integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==",
"dev": true,
"dependencies": {
"klona": "^2.0.4",
"neo-async": "^2.6.2"
},
"engines": {
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"fibers": ">= 3.1.0",
"node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0",
"sass": "^1.3.0",
"sass-embedded": "*",
"webpack": "^5.0.0"
},
"peerDependenciesMeta": {
"fibers": {
"optional": true
},
"node-sass": {
"optional": true
},
"sass": {
"optional": true
},
"sass-embedded": {
"optional": true
}
}
},
"node_modules/schema-utils": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
@@ -8022,6 +8143,7 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"dependencies": {
"randombytes": "^2.1.0"
}
@@ -8263,6 +8385,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8279,6 +8402,7 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
@@ -8519,6 +8643,7 @@
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
"dev": true,
"engines": {
"node": ">=6"
}
@@ -8527,6 +8652,7 @@
"version": "5.27.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz",
"integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
@@ -8544,6 +8670,7 @@
"version": "5.3.10",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.20",
"jest-worker": "^27.4.5",
@@ -8577,6 +8704,7 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
@@ -8593,7 +8721,8 @@
"node_modules/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"node_modules/thunky": {
"version": "1.1.0",
@@ -8677,7 +8806,8 @@
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
@@ -8741,6 +8871,7 @@
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
"integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
"dev": true,
"funding": [
{
"type": "opencollective",
@@ -8770,6 +8901,7 @@
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
"dependencies": {
"punycode": "^2.1.0"
}
@@ -8778,6 +8910,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true,
"engines": {
"node": ">=6"
}
@@ -8954,6 +9087,7 @@
"version": "5.90.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz",
"integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==",
"dev": true,
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.5",
@@ -9277,6 +9411,7 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
@@ -9294,6 +9429,7 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
"dev": true,
"engines": {
"node": ">=10.13.0"
}

View File

@@ -15,7 +15,9 @@
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"laravel-mix": "^6.0.31",
"laravel-mix-merge-manifest": "^2.0.0"
"laravel-mix-merge-manifest": "^2.0.0",
"sass": "^1.77.1",
"sass-loader": "^12.6.0"
},
"dependencies": {
"axios": "^1.3.4",