Ngiler SH3LL 360
Home
Information
Create File
Create Folder
:
/
home
/
tbf
/
tbfguest.tbf.ro
/
src
/
views
/
public
/
positions
/
Information Server
MySQL :
OFF
Perl :
OFF
CURL :
ON
WGET :
OFF
PKEXEC :
OFF
Directive
Local Value
IP Address
89.40.16.97
System
Linux server.atelieruldeit.ro 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64
User
tbf
PHP Version
7.3.33
Software
Apache
Doc root
Writable
close
Edit File :
Show.vue
| Size :
30.16
KB
Copy
<template> <!-- Content --> <div class="relative"> <div class="bg-gray-50 px-16 pt-14 py-10 border-b border-gray-200"> <div class="flex justify-between items-center"> <div class="flex items-center gap-x-3 relative"> <!-- Back button --> <router-link :to="{ name: 'positions' }" class="inset-y-0 -left-10 flex items-center absolute transition duration-300 hover:-translate-x-1 hover:text-gray-500"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6"> <path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M7.72 12.53a.75.75 0 010-1.06l7.5-7.5a.75.75 0 111.06 1.06L9.31 12l6.97 6.97a.75.75 0 11-1.06 1.06l-7.5-7.5z" clip-rule="evenodd" /> </svg> </router-link> <!-- Titlu funcție --> <h3 class="text-base font-semibold leading-6 text-gray-900">Funcția {{ name }}</h3> </div> </div> </div> <Transition enter-active-class="ease-out duration-500" enter-from-class="opacity-0" enter-to-class="opacity-100" leave-active-class="ease-in duration-200" leave-from-class="opacity-100" leave-to-class="opacity-0"> <div v-if="loaded" class="pt-10 pb-0 px-16 max-w-none mx-auto"> <div class="space-y-12"> <div class="grid grid-cols-1 gap-x-8 gap-y-10 border-b border-gray-900/10 pb-12 md:grid-cols-3"> <div> <h2 class="text-base font-semibold leading-7 text-gray-900">Despre Funcție</h2> <p class="mt-1 text-sm leading-6 text-gray-600">Numele și descrierea funcției</p> </div> <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6 md:col-span-2"> <div class="sm:col-span-4"> <label for="name" class="block text-sm font-semibold leading-6 text-gray-900"> Nume funcție </label> <div class="mt-2 relative"> <p class="text-sm text-gray-700 leading-6">{{ name }}</p> </div> </div> <div class="col-span-full"> <div class="flex justify-between"> <label for="description" class="block text-sm font-semibold leading-6 text-gray-900"> Descriere funcție </label> </div> <div class="mt-2 relative"> <p v-if="description" class="text-sm text-gray-700 leading-6 whitespace-pre-wrap" v-html="description.replace(/(?:\r\n|\r|\n)/g, `<div class='h-[6px]'></div>`)"></p> </div> </div> </div> </div> <div class="grid grid-cols-1 gap-x-8 gap-y-10 border-b border-gray-900/10 pb-12 md:grid-cols-3"> <div> <h2 class="text-base font-semibold leading-7 text-gray-900">Detalii Funcție</h2> </div> <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6 md:col-span-2"> <fieldset class="col-span-2"> <legend class="text-sm font-semibold leading-6 text-gray-900">Locație</legend> <div class="mt-4 space-y-3"> <div class="relative flex items-start" v-for="option in options.filter((el) => el.category == 'location')"> <div class="flex h-6 items-center"> <input :id="`optionLocations${option.code}`" v-model="optionsSelected" :value="option.id" type="checkbox" class="h-4 w-4 rounded border-gray-300 text-blue-500 focus:ring-blue-500" disabled="true" /> </div> <div class="ml-3 text-sm leading-6"> <label :for="`optionLocations${option.code}`" :class="[optionsSelected.find((el) => el == option.id) ? 'text-gray-900' : 'text-gray-500']">{{ option.name }}</label> </div> </div> </div> </fieldset> <fieldset class="col-span-2"> <legend class="text-sm font-semibold leading-6 text-gray-900">Softuri Folosite</legend> <div class="mt-4 space-y-3"> <div class="relative flex items-start" v-for="option in options.filter((el) => el.category == 'software')"> <div class="flex h-6 items-center"> <input :id="`optionSoftwares${option.code}`" v-model="optionsSelected" :value="option.id" type="checkbox" class="h-4 w-4 rounded border-gray-300 text-blue-500 focus:ring-blue-500" disabled="true" /> </div> <div class="ml-3 text-sm leading-6"> <label :for="`optionSoftwares${option.code}`" :class="[optionsSelected.find((el) => el == option.id) ? 'text-gray-900' : 'text-gray-500']">{{ option.name }}</label> </div> </div> </div> </fieldset> <fieldset class="col-span-2"> <legend class="text-sm font-semibold leading-6 text-gray-900">Altele</legend> <div class="mt-4 space-y-3"> <div class="relative flex items-start" v-for="option in options.filter((el) => el.category == 'detail')"> <div class="flex h-6 items-center"> <input :id="`optionDetails${option.code}`" v-model="optionsSelected" :value="option.id" type="checkbox" class="h-4 w-4 rounded border-gray-300 text-blue-500 focus:ring-blue-500" disabled="true" /> </div> <div class="ml-3 text-sm leading-6"> <label :for="`optionDetails${option.code}`" :class="[optionsSelected.find((el) => el == option.id) ? 'text-gray-900' : 'text-gray-500']">{{ option.name }}</label> </div> </div> </div> </fieldset> </div> </div> <div class="grid grid-cols-1 gap-x-8 gap-y-10 border-b border-gray-900/10 pb-12 md:grid-cols-3"> <div> <h2 class="text-base font-semibold leading-7 text-gray-900">Angajați Funcție</h2> <p class="mt-1 text-sm leading-6 text-gray-600">Echipa de documentare a activităților pentru funcție</p> </div> <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6 md:col-span-2"> <div class="col-span-full"> <div> <div class="max-w-lg"> <h2 class="block text-sm font-semibold leading-6 text-gray-900">Responsabil de verificare</h2> <p class="mt-1 text-sm text-gray-600"> Această persoană este de cele mai multe ori managerul departamentului din care face parte funcția. Va fi responsabilă să verifice activitățile documentate de angajați. </p> </div> <div class="max-w-lg mt-6 grid grid-cols-2 gap-x-5"> <div v-if="responsible"> <div class="relative h-full rounded-lg border-2 border-dashed border-gray-300 text-center flex flex-col items-center justify-center p-3"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="w-7 h-7 text-gray-900 mx-auto"> <path stroke-width="1.2" vector-effect="non-scaling-stroke" stroke-linecap="round" stroke-linejoin="round" d="M4.26 10.147a60.436 60.436 0 00-.491 6.347A48.627 48.627 0 0112 20.904a48.627 48.627 0 018.232-4.41 60.46 60.46 0 00-.491-6.347m-15.482 0a50.57 50.57 0 00-2.658-.813A59.905 59.905 0 0112 3.493a59.902 59.902 0 0110.399 5.84c-.896.248-1.783.52-2.658.814m-15.482 0A50.697 50.697 0 0112 13.489a50.702 50.702 0 017.74-3.342M6.75 15a.75.75 0 100-1.5.75.75 0 000 1.5zm0 0v-3.675A55.378 55.378 0 0112 8.443m-7.007 11.55A5.981 5.981 0 006.75 15.75v-1.5" /> </svg> <span class="max-w-full mt-2 block text-sm font-medium text-gray-900 truncate">{{ responsible.first_name }}</span> <p class="max-w-full text-sm text-gray-500 truncate">{{ responsible.email }}</p> </div> </div> <div v-else> <div class="relative h-full rounded-lg border-2 border-gray-300 border-dashed text-center flex items-center justify-center"> <div> <div class="w-7 h-7 bg-gray-200 mx-auto rounded-full flex items-center justify-center"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-4 h-4 text-white"> <path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM3.751 20.105a8.25 8.25 0 0116.498 0 .75.75 0 01-.437.695A18.683 18.683 0 0112 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 01-.437-.695z" clip-rule="evenodd" /> </svg> </div> <div class="mt-3 h-2 w-32 bg-gray-200 rounded-md mx-auto"></div> <div class="mt-2 h-2 w-24 bg-gray-100 rounded-md mx-auto"></div> </div> <div class="absolute top-3 right-3 flex-shrink-0 flex items-center content-center" style="height: 20px"> <div class="bg-gray-100 rounded-md w-5 h-5 flex items-center justify-center"></div> </div> </div> </div> </div> <div class="mt-10 max-w-lg"> <h2 class="block text-sm font-semibold leading-6 text-gray-900">Responsabili de documentare</h2> <p class="mt-1 text-sm text-gray-600"> Acești angajați vor documenta activitățile pe care le fac lună de lună. Folosind aceste activități vom genera responsabilități măsurabile și corecte. </p> </div> </div> <div class="mt-6 max-w-lg"> <ul role="list" class="mt-4 divide-y divide-gray-200"> <li v-for="(person, personIdx) in selectedUsers" :key="personIdx" class="flex items-center justify-between space-x-3 py-3"> <div class="flex min-w-0 flex-1 items-center space-x-3"> <div class="flex-shrink-0"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="w-7 h-7"> <path stroke-width="1.1" vector-effect="non-scaling-stroke" stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg> </div> <div class="flex items-center gap-5"> <p class="truncate text-sm font-medium text-gray-900 w-40">{{ person.first_name }}</p> <p class="truncate text-sm text-gray-500">{{ person.email }}</p> </div> </div> </li> <template v-if="selectedUsers.length < 4"> <li v-for="item in 4 - selectedUsers.length" class="flex items-center justify-between space-x-3 py-3"> <div class="flex min-w-0 flex-1 items-center space-x-3"> <div class="flex-shrink-0"> <div class="w-7 h-7 bg-gray-200 rounded-full flex items-center justify-center"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-4 h-4 text-white"> <path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM3.751 20.105a8.25 8.25 0 0116.498 0 .75.75 0 01-.437.695A18.683 18.683 0 0112 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 01-.437-.695z" clip-rule="evenodd" /> </svg> </div> </div> <div class="flex items-center gap-5"> <div class="h-5 w-40 rounded-md bg-gray-200"></div> <div class="h-5 w-52 rounded-md bg-gray-100"></div> </div> </div> </li> </template> </ul> </div> </div> </div> </div> <template v-if="$auth.impersonating()"> <div class="grid grid-cols-1 gap-x-8 gap-y-10 border-b border-gray-900/10 pb-12 md:grid-cols-3"> <div> <h2 class="text-base font-semibold leading-7 text-gray-900">Administratori Funcție</h2> <p class="mt-1 text-sm leading-6 text-gray-600"> Acești angajați vor verifica activitățile introduse de responsabilii de documentare și vor avea acces la responsabilități, proceduri și procese de recrutare. </p> </div> <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6 md:col-span-2"> <div class="col-span-full"> <div> <form class="max-w-2xl mt-0 grid grid-cols-10 gap-x-2" @submit.prevent="addUserAdmin()" autocomplete="off"> <Combobox class="col-span-5 relative" as="div" v-model="selectedAdmin" nullable> <ComboboxInput class="w-full rounded-md border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-500 sm:text-sm sm:leading-6 disabled:cursor-not-allowed" @change="querySearchAdmin = $event.target.value" :display-value="(person) => person?.email" @blur="setCurrentOptionAdmin" placeholder="Adresa de email..." autocomplete="off" /> <ComboboxOptions class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"> <ComboboxOption v-if="queryAdmin" as="template" :value="queryAdmin"> <li :class="['relative cursor-default select-none py-2 pl-3 pr-9']"> <div class="flex"> <span :class="['truncate text-gray-500']"> Adauga "{{ querySearchAdmin }}" </span> </div> </li> </ComboboxOption> <ComboboxOption v-for="person in filteredUsers(false)" :key="person.first_name" :value="person" as="template" v-slot="{ active, selected }"> <li :class="['relative cursor-default select-none py-2 pl-3 pr-9', active ? 'bg-blue-600 text-white' : 'text-gray-900']"> <div class="flex flex-col"> <span :class="['truncate', selected && 'font-semibold']"> {{ person.first_name }} </span> <span :class="['truncate text-gray-500', active ? 'text-indigo-200' : 'text-gray-500']"> {{ person.email }} </span> </div> <span v-if="selected" :class="['absolute inset-y-0 right-0 flex items-center pr-4', active ? 'text-white' : 'text-blue-600']"> <svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 448 512" class="h-5 w-5"> <path fill="currentColor" d="M443.3 100.7c6.2 6.2 6.2 16.4 0 22.6l-272 272c-6.2 6.2-16.4 6.2-22.6 0l-144-144c-6.2-6.2-6.2-16.4 0-22.6s16.4-6.2 22.6 0L160 361.4 420.7 100.7c6.2-6.2 16.4-6.2 22.6 0z" /> </svg> </span> </li> </ComboboxOption> </ComboboxOptions> </Combobox> <label for="new-user_name" class="sr-only">Nume</label> <input v-model="admin_name" id="new-user_name" class="col-span-3 block w-full rounded-md border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-500 sm:text-sm sm:leading-6 disabled:cursor-not-allowed" placeholder="Nume" autocomplete="off" /> <button type="submit" class="col-span-2 flex-shrink-0 rounded-md bg-blue-500 px-3 py-2 text-sm font-semibold text-white hover:bg-blue-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 disabled:cursor-not-allowed"> Adaugă </button> </form> </div> <div class="mt-6 max-w-lg"> <ul role="list" class="mt-4 divide-y divide-gray-200"> <li v-for="(person, personIdx) in selectedAdmins" :key="personIdx" class="flex items-center justify-between space-x-3 py-3"> <div class="flex min-w-0 flex-1 items-center space-x-3"> <div class="flex-shrink-0"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="w-7 h-7"> <path stroke-width="1.1" vector-effect="non-scaling-stroke" stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg> </div> <div class="flex items-center gap-5"> <p class="truncate text-sm font-medium text-gray-900 w-40">{{ person.first_name }}</p> <p class="truncate text-sm text-gray-500">{{ person.email }}</p> </div> </div> <div class="flex-shrink-0"> <button @click="selectedAdmins.splice(personIdx, 1)" class="inline-flex items-center gap-x-1.5 font-semibold leading-6 text-gray-500 hover:text-gray-900 hover:bg-gray-50 rounded-lg p-2"> <svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 384 512"> <path fill="currentColor" d="M324.5 411.1c6.2 6.2 16.4 6.2 22.6 0s6.2-16.4 0-22.6L214.6 256 347.1 123.5c6.2-6.2 6.2-16.4 0-22.6s-16.4-6.2-22.6 0L192 233.4 59.5 100.9c-6.2-6.2-16.4-6.2-22.6 0s-6.2 16.4 0 22.6L169.4 256 36.9 388.5c-6.2 6.2-6.2 16.4 0 22.6s16.4 6.2 22.6 0L192 278.6 324.5 411.1z" /> </svg> </button> </div> </li> <template v-if="selectedAdmins.length < 4"> <li v-for="item in 4 - selectedAdmins.length" class="flex items-center justify-between space-x-3 py-3"> <div class="flex min-w-0 flex-1 items-center space-x-3"> <div class="flex-shrink-0"> <div class="w-7 h-7 bg-gray-200 rounded-full flex items-center justify-center"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-4 h-4 text-white"> <path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM3.751 20.105a8.25 8.25 0 0116.498 0 .75.75 0 01-.437.695A18.683 18.683 0 0112 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 01-.437-.695z" clip-rule="evenodd" /> </svg> </div> </div> <div class="flex items-center gap-5"> <div class="h-5 w-40 rounded-md bg-gray-200"></div> <div class="h-5 w-52 rounded-md bg-gray-100"></div> </div> </div> <div class="flex-shrink-0 flex items-center content-center" style="height: 32px"> <div class="bg-gray-200 rounded-md w-5 h-5 flex items-center justify-center"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="w-4 h-4 text-white"> <path vector-effect="non-scaling-stroke" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" /> </svg> </div> </div> </li> </template> </ul> </div> </div> </div> </div> <div class="grid grid-cols-1 gap-x-8 gap-y-10 border-b border-gray-900/10 pb-12 md:grid-cols-3"> <div> <h2 class="text-base font-semibold leading-7 text-gray-900">Setări Funcție</h2> <p class="mt-1 text-sm leading-6 text-gray-600">Bifează ceea ce ai nevoie</p> </div> <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6 md:col-span-2"> <div class="col-span-full"> <SwitchGroup as="div" class="flex items-center justify-between col-span-1"> <span class="flex flex-grow flex-col"> <SwitchLabel as="span" class="text-sm font-medium leading-6 text-gray-900" passive>Anunț de recrutare</SwitchLabel> <SwitchDescription as="span" class="text-sm text-gray-500 mt-1" >Dacă ai nevoie de anunț de recrutare, te rugăm să bifezi această opțiune.</SwitchDescription > </span> <Switch v-model="need_for_recruitment" :class="[ need_for_recruitment ? 'bg-blue-500' : 'bg-gray-200', 'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2', ]"> <span aria-hidden="true" :class="[ need_for_recruitment ? 'translate-x-5' : 'translate-x-0', 'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out', ]" /> </Switch> </SwitchGroup> </div> </div> </div> <div class="grid grid-cols-1 gap-x-8 pb-14 md:grid-cols-3"> <div class="col-span-2 flex items-center gap-x-4"> <button type="submit" :disabled="loadingSubmit" class="flex items-center gap-1 rounded-md bg-blue-500 px-3 py-2 text-sm font-semibold text-white hover:bg-blue-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 disabled:bg-blue-400 disabled:cursor-not-allowed" @click="savePosition(false)"> <LoaderTbf color="text-white" v-if="loadingSubmit" /> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5 -mt-px" v-else> <path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M6.32 2.577a49.255 49.255 0 0111.36 0c1.497.174 2.57 1.46 2.57 2.93V21a.75.75 0 01-1.085.67L12 18.089l-7.165 3.583A.75.75 0 013.75 21V5.507c0-1.47 1.073-2.756 2.57-2.93z" clip-rule="evenodd" /> </svg> Salvează Funcție </button> </div> </div> </template> </div> </div> <LoaderCreatePage v-else /> </Transition> </div> </template> <script> // Import the required components import LoaderCreatePage from "@/components/public/positions/loaders/CreatePage.vue"; import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions, Switch, SwitchDescription, SwitchGroup, SwitchLabel } from "@headlessui/vue"; import { useModalsStore } from "@/stores/modals.js"; import { userNotificationsStore } from "@/stores/notifications.js"; import LoaderTbf from "@/components/public/LoadingTbf.vue"; export default { components: { LoaderCreatePage, Combobox, ComboboxInput, ComboboxOption, ComboboxOptions, Switch, SwitchDescription, SwitchGroup, SwitchLabel, LoaderTbf, }, data() { return { loaded: false, realTimeModals: useModalsStore(), realTimeNotifications: userNotificationsStore(), name: "", description: "", options: [], optionsSelected: [], selectedUsers: [], responsible: "", loadingSubmit: false, need_for_recruitment: true, selectedAdmins: [], selectedAdmin: "", admin_name: "", querySearchAdmin: "", emailRegex: /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/, }; }, computed: { queryAdmin() { return this.querySearchAdmin === "" || this.optionsUsers.find((el) => el.email.toLowerCase() == this.querySearchAdmin.toLowerCase()) ? null : { first_name: this.admin_name ? this.admin_name : "", email: this.querySearchAdmin.toLowerCase() }; }, }, watch: { selectedAdmin(newVal, oldVal) { this.admin_name = newVal?.first_name ? newVal.first_name : ""; this.querySearchAdmin = newVal?.email ? newVal.email.toLowerCase() : this.querySearchAdmin.toLowerCase(); }, }, async mounted() { await this.getUsers(); await this.getOptions(); await this.getPositionData(); }, methods: { async getPositionData() { await axios .get(`instances/${this.$auth.user().instance.id}/positions/${this.$route.params.id}`) .then(({ data }) => { var positionData = data.data; this.name = positionData.name; this.description = positionData.description; this.optionsSelected = positionData.options.map((el) => { return el.id; }); this.responsible = positionData.users.find((el) => el.is_responsible); this.selectedUsers = positionData.users.filter((el) => !el.is_responsible); this.selectedAdmins = positionData.admins; this.need_for_recruitment = positionData.need_for_recruitment; }) .finally(() => { this.loaded = true; }); }, async getOptions() { await axios.get(`options?type=position`).then(({ data }) => { this.options = data.data; }); }, async getUsers() { await axios .get(`instances/${this.$auth.user().instance.id}/users`) .then(({ data }) => { this.optionsUsers = data.data; }) }, filteredUsers() { var querySearch = this.querySearchAdmin; const selectedUserIDs = this.selectedUsers.map((user) => user.id); const selectedAdminIDs = this.selectedAdmins.map((user) => user.id); const filtered = this.optionsUsers.filter((user) => ![...selectedUserIDs, ...selectedAdminIDs].includes(user.id)); const remainingUsers = [...filtered]; return querySearch === "" ? remainingUsers.filter((el) => !el.unavailable) : remainingUsers.filter((person) => { const lowerCaseQuery = querySearch.toLowerCase(); return !person.unavailable && (person.first_name.toLowerCase().includes(lowerCaseQuery) || (person.email && person.email.toLowerCase().includes(lowerCaseQuery))); }); }, async addUserAdmin() { if (this.selectedAdmin && this.selectedAdmin.email && this.admin_name && this.emailRegex.test(this.selectedAdmin.email)) { if (this.responsible && this.responsible.email.toLowerCase() == this.selectedAdmin.email.toLowerCase()) { this.realTimeModals.toggleShowModal("modal_error_add_users", { error: "exist_on_responsible" }); this.clearUserInputs("admin"); return; } if (this.selectedUsers.length && this.selectedUsers.find((el) => el.email.toLowerCase() == this.selectedAdmin.email.toLowerCase())) { this.realTimeModals.toggleShowModal("modal_error_add_users", { error: "user_exist_on_users" }); this.clearUserInputs("admin"); return; } if (this.selectedAdmins.length && this.selectedAdmins.find((el) => el.email.toLowerCase() == this.selectedAdmin.email.toLowerCase())) { this.realTimeModals.toggleShowModal("modal_error_add_users", { error: "user_exist_on_admins" }); this.clearUserInputs("admin"); return; } var userData = { first_name: this.admin_name, email: this.selectedAdmin.email.toLowerCase() }; if (this.selectedAdmin.id) { userData.id = this.selectedAdmin.id; } else { try { const { data } = await axios.post(`/users/check/email`, { email: this.selectedAdmin.email.toLowerCase() }); if (data.exists) { this.realTimeNotifications.addNotification({ type: "error", title: "Adresă de email invalidă.", description: "Această adresă de email este deja înregistrată.", }); return; } } catch (error) { var responseError = error.response.data; this.realTimeNotifications.addNotification({ type: "error", title: "TBF ERROR", description: `"${responseError.message}".`, }); return; // This ensures we stop the function execution in case of an error } } this.selectedAdmins.push(userData); this.clearUserInputs(); } else { this.realTimeNotifications.addNotification({ type: "error", title: "Verifica formularul.", description: "Adresa de email și numele sunt obligatorii. Verifică ca adresa de email să fie validă.", }); } }, clearUserInputs() { this.selectedAdmin = ""; this.admin_name = ""; this.querySearchAdmin = ""; }, async savePosition() { this.loadingSubmit = true; var usedUsers = []; if (this.responsible) { usedUsers.push(this.responsible); } usedUsers = usedUsers.concat([...this.selectedUsers]); var formData = { name: this.name, need_for_recruitment: this.need_for_recruitment, description: this.description, options: this.optionsSelected, users: usedUsers, admins: this.selectedAdmins, }; this.updatePosition(formData); }, updatePosition(formData) { axios .patch(`/instances/${this.$auth.user().instance.id}/positions/${this.$route.params.id}`, formData) .then(({ data }) => { var positionData = data.data; this.responsible = positionData.users.find((el) => el.is_responsible); this.selectedUsers = positionData.users.filter((el) => !el.is_responsible); this.selectedAdmins = positionData.admins; this.realTimeNotifications.addNotification({ type: "success", title: "Actualizat cu success.", description: "Funcția a fost actualizata cu success.", }); }) .catch((error) => { var responseError = error.response.data; this.realTimeNotifications.addNotification({ type: "error", title: "TBF ERROR", description: `"${responseError.message}"<br>Vă rugăm să ne contactați și să ne transmiteți eroare. În interesul remedierii acestei probleme cât mai curând posibil.`, }); }) .finally(() => { this.loadingSubmit = false; }); }, setCurrentOptionAdmin(event) { if (this.optionsUsers.find((el) => el.email.toLowerCase() == this.querySearchAdmin.toLowerCase())) { this.selectedAdmin = this.optionsUsers.find((el) => el.email.toLowerCase() == this.querySearchAdmin.toLowerCase()); } else { this.selectedAdmin = { first_name: this.admin_name ? this.admin_name : "", email: this.querySearchAdmin.toLowerCase() }; } }, async checkEmail(email) { var isValid = false; await axios.post(`/users/check/email`, { email: email }).then(({ data }) => { if (data.user) { isValid = false; } else { isValid = true; } }); return isValid; }, }, }; </script>
Back