#134 - fill users data for resume #144
| @@ -30,7 +30,7 @@ class ResumeRequest extends FormRequest | |||||||
|             "technologies.*.level" => ["required", Rule::in(1, 2, 3, 4, 5)], |             "technologies.*.level" => ["required", Rule::in(1, 2, 3, 4, 5)], | ||||||
|  |  | ||||||
|             "projects.*.description" => ["required"], |             "projects.*.description" => ["required"], | ||||||
|             "projects.*.technologies" => ["required"], |             "projects.*.technologies" => ["exists:technologies,name", "distinct"], | ||||||
|             "projects.*.startDate" => ["required", "date_format:Y-m-d"], |             "projects.*.startDate" => ["required", "date_format:Y-m-d"], | ||||||
|             "projects.*.endDate" => ["required", "date_format:Y-m-d", "after:startDate"], |             "projects.*.endDate" => ["required", "date_format:Y-m-d", "after:startDate"], | ||||||
|             "projects.*.tasks" => ["required"], |             "projects.*.tasks" => ["required"], | ||||||
|   | |||||||
| @@ -17,6 +17,10 @@ class ResumeResource extends JsonResource | |||||||
|             "user" => new SimpleUserResource($this->user), |             "user" => new SimpleUserResource($this->user), | ||||||
|             "name" => $this->name, |             "name" => $this->name, | ||||||
|             "description" => $this->description, |             "description" => $this->description, | ||||||
|  |             "educationCount" => $this->education->count(), | ||||||
|  |             "languageCount" => $this->languages->count(), | ||||||
|  |             "technologyCount" => $this->technologies->count(), | ||||||
|  |             "projectCount" => $this->projects->count(), | ||||||
|             "createdAt" => $this->created_at->toDisplayString(), |             "createdAt" => $this->created_at->toDisplayString(), | ||||||
|             "updatedAt" => $this->updated_at->toDisplayString(), |             "updatedAt" => $this->updated_at->toDisplayString(), | ||||||
|         ]; |         ]; | ||||||
|   | |||||||
| @@ -17,7 +17,6 @@ class ResumeFactory extends Factory | |||||||
|   
				
					
						
						krzysztofrewak
					
					
						commented  
						Review
						 ```suggestion
            "name" => fn(array $attributes): bool => empty($attributes["user_id"]) ? $this->faker->name : null,
```   
				
					
						
						krzysztofrewak
					
					
						commented  
						Review
						 ```suggestion
            "name" => fn(array $attributes): bool => empty($attributes["user_id"]) ? $this->faker->name : null,
``` | |||||||
|     { |     { | ||||||
|         return [ |         return [ | ||||||
|             "name" => fn(array $attr) => empty($attr["user_id"]) ? $this->faker->name : null, |             "name" => fn(array $attr) => empty($attr["user_id"]) ? $this->faker->name : null, | ||||||
|             "description" => $this->faker->boolean(30) ? $this->faker->sentence : null, |  | ||||||
|   ```suggestion
            "name" => fn(array $attributes): bool => empty($attributes["user_id"]) ? $this->faker->name : null,
``` | |||||||
|             "education" => $this->generateEducation(), |             "education" => $this->generateEducation(), | ||||||
|             "languages" => $this->generateLanguages(), |             "languages" => $this->generateLanguages(), | ||||||
|             "technologies" => $this->generateTechnologies(), |             "technologies" => $this->generateTechnologies(), | ||||||
|   | |||||||
|   ```suggestion
            "name" => fn(array $attributes): bool => empty($attributes["user_id"]) ? $this->faker->name : null,
```   ```suggestion
            "name" => fn(array $attributes): bool => empty($attributes["user_id"]) ? $this->faker->name : null,
``` | |||||||
| @@ -14,7 +14,6 @@ return new class() extends Migration { | |||||||
|             $table->id(); |             $table->id(); | ||||||
|             $table->foreignIdFor(User::class)->nullable()->constrained()->cascadeOnDelete(); |             $table->foreignIdFor(User::class)->nullable()->constrained()->cascadeOnDelete(); | ||||||
|             $table->string("name")->nullable(); |             $table->string("name")->nullable(); | ||||||
|             $table->string("description")->nullable(); |  | ||||||
|             $table->json("education"); |             $table->json("education"); | ||||||
|             $table->json("languages"); |             $table->json("languages"); | ||||||
|             $table->json("technologies"); |             $table->json("technologies"); | ||||||
|   | |||||||
| @@ -263,11 +263,25 @@ | |||||||
|           <template #form="{ element, index }"> |           <template #form="{ element, index }"> | ||||||
|             <div class="gap-4 md:grid md:grid-cols-2 "> |             <div class="gap-4 md:grid md:grid-cols-2 "> | ||||||
|               <div class="py-4"> |               <div class="py-4"> | ||||||
|                 <Combobox |                 <label | ||||||
|                   v-model="element.name" |                   :for="`language-${index}-level`" | ||||||
|                   label="Język" |                   class="block text-sm font-medium text-gray-700" | ||||||
|                   :items="languages" |                 > | ||||||
|                 /> |                   Język | ||||||
|  |                 </label> | ||||||
|  |                 <div class="mt-2"> | ||||||
|  |                   <Combobox | ||||||
|  |                     :id="`language-${index}-level`" | ||||||
|  |                     v-model="element.name" | ||||||
|  |                     :items="languages" | ||||||
|  |                   /> | ||||||
|  |                   <p | ||||||
|  |                     v-if="form.errors[`languages.${index}.name`]" | ||||||
|  |                     class="mt-2 text-sm text-red-600" | ||||||
|  |                   > | ||||||
|  |                     {{ form.errors[`languages.${index}.name`] }} | ||||||
|  |                   </p> | ||||||
|  |                 </div> | ||||||
|               </div> |               </div> | ||||||
|               <div class="py-4"> |               <div class="py-4"> | ||||||
|                 <label |                 <label | ||||||
| @@ -313,11 +327,25 @@ | |||||||
|           <template #form="{ element, index }"> |           <template #form="{ element, index }"> | ||||||
|             <div class="gap-4 md:grid md:grid-cols-2 "> |             <div class="gap-4 md:grid md:grid-cols-2 "> | ||||||
|               <div class="py-4"> |               <div class="py-4"> | ||||||
|                 <Combobox |                 <label | ||||||
|                   v-model="element.name" |                   :for="`technology-${index}-level`" | ||||||
|                   label="Technologia" |                   class="block text-sm font-medium text-gray-700" | ||||||
|                   :items="technologies" |                 > | ||||||
|                 /> |                   Technologia | ||||||
|  |                 </label> | ||||||
|  |                 <div class="mt-2"> | ||||||
|  |                   <Combobox | ||||||
|  |                     :id="`technology-${index}-level`" | ||||||
|  |                     v-model="element.name" | ||||||
|  |                     :items="technologies" | ||||||
|  |                   /> | ||||||
|  |                   <p | ||||||
|  |                     v-if="form.errors[`technologies.${index}.name`]" | ||||||
|  |                     class="mt-2 text-sm text-red-600" | ||||||
|  |                   > | ||||||
|  |                     {{ form.errors[`technologies.${index}.name`] }} | ||||||
|  |                   </p> | ||||||
|  |                 </div> | ||||||
|               </div> |               </div> | ||||||
|               <div class="py-4"> |               <div class="py-4"> | ||||||
|                 <label |                 <label | ||||||
| @@ -367,6 +395,7 @@ | |||||||
|                 <textarea |                 <textarea | ||||||
|                   :id="`project-description-${index}`" |                   :id="`project-description-${index}`" | ||||||
|                   v-model="element.description" |                   v-model="element.description" | ||||||
|  |                   rows="5" | ||||||
|                   class="block w-full rounded-md shadow-sm sm:text-sm" |                   class="block w-full rounded-md shadow-sm sm:text-sm" | ||||||
|                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.description`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.description`] }" |                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.description`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.description`] }" | ||||||
|                 /> |                 /> | ||||||
| @@ -386,13 +415,11 @@ | |||||||
|                 Technologie |                 Technologie | ||||||
|               </label> |               </label> | ||||||
|               <div class="mt-1 sm:mt-0"> |               <div class="mt-1 sm:mt-0"> | ||||||
|                 <input |                 <MultipleCombobox | ||||||
|                   :id="`project-technologies-${index}`" |                   :id="`project-technologies-${index}`" | ||||||
|                   v-model="element.technologies" |                   v-model="element.technologies" | ||||||
|                   type="text" |                   :items="technologies" | ||||||
|                   class="block w-full rounded-md shadow-sm sm:text-sm" |                 /> | ||||||
|                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.technologies`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.technologies`] }" |  | ||||||
|                 > |  | ||||||
|                 <p |                 <p | ||||||
|                   v-if="form.errors[`projects.${index}.technologies`]" |                   v-if="form.errors[`projects.${index}.technologies`]" | ||||||
|                   class="mt-2 text-sm text-red-600" |                   class="mt-2 text-sm text-red-600" | ||||||
| @@ -458,6 +485,7 @@ | |||||||
|                 <textarea |                 <textarea | ||||||
|                   :id="`project-tasks-${index}`" |                   :id="`project-tasks-${index}`" | ||||||
|                   v-model="element.tasks" |                   v-model="element.tasks" | ||||||
|  |                   rows="5" | ||||||
|                   class="block w-full rounded-md shadow-sm sm:text-sm" |                   class="block w-full rounded-md shadow-sm sm:text-sm" | ||||||
|                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.tasks`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.tasks`] }" |                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.tasks`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.tasks`] }" | ||||||
|                 /> |                 /> | ||||||
| @@ -495,10 +523,12 @@ | |||||||
| <script setup> | <script setup> | ||||||
| import { Listbox, ListboxOption, ListboxOptions, ListboxLabel, ListboxButton } from '@headlessui/vue' | import { Listbox, ListboxOption, ListboxOptions, ListboxLabel, ListboxButton } from '@headlessui/vue' | ||||||
| import { SelectorIcon, CheckIcon } from '@heroicons/vue/outline' | import { SelectorIcon, CheckIcon } from '@heroicons/vue/outline' | ||||||
|  | import { ExclamationCircleIcon } from '@heroicons/vue/solid' | ||||||
| import { useForm } from '@inertiajs/inertia-vue3' | import { useForm } from '@inertiajs/inertia-vue3' | ||||||
| import FlatPickr from 'vue-flatpickr-component' | import FlatPickr from 'vue-flatpickr-component' | ||||||
| import DynamicSection from '@/Shared/Forms/DynamicSection' | import DynamicSection from '@/Shared/Forms/DynamicSection' | ||||||
| import Combobox from '@/Shared/Forms/Combobox' | import Combobox from '@/Shared/Forms/Combobox' | ||||||
|  | import MultipleCombobox from '@/Shared/Forms/MultipleCombobox' | ||||||
| import LevelPicker from '@/Shared/Forms/LevelPicker' | import LevelPicker from '@/Shared/Forms/LevelPicker' | ||||||
| import useLevels from '@/Composables/useLevels' | import useLevels from '@/Composables/useLevels' | ||||||
|  |  | ||||||
| @@ -527,7 +557,7 @@ const form = useForm({ | |||||||
| function addProject() { | function addProject() { | ||||||
|   form.projects.push({ |   form.projects.push({ | ||||||
|     description: null, |     description: null, | ||||||
|     technologies: null, |     technologies: [], | ||||||
|     tasks: null, |     tasks: null, | ||||||
|     startDate: null, |     startDate: null, | ||||||
|     endDate: null, |     endDate: null, | ||||||
|   | |||||||
| @@ -263,17 +263,25 @@ | |||||||
|           <template #form="{ element, index }"> |           <template #form="{ element, index }"> | ||||||
|             <div class="gap-4 md:grid md:grid-cols-2 "> |             <div class="gap-4 md:grid md:grid-cols-2 "> | ||||||
|               <div class="py-4"> |               <div class="py-4"> | ||||||
|                 <Combobox |                 <label | ||||||
|                   v-model="element.name" |                   :for="`language-${index}-level`" | ||||||
|                   label="Język" |                   class="block text-sm font-medium text-gray-700" | ||||||
|                   :items="languages" |  | ||||||
|                 /> |  | ||||||
|                 <p |  | ||||||
|                   v-if="form.errors[`languages.${index}.name`]" |  | ||||||
|                   class="mt-2 text-sm text-red-600" |  | ||||||
|                 > |                 > | ||||||
|                   {{ form.errors[`languages.${index}.name`] }} |                   Język | ||||||
|                 </p> |                 </label> | ||||||
|  |                 <div class="mt-2"> | ||||||
|  |                   <Combobox | ||||||
|  |                     :id="`language-${index}-level`" | ||||||
|  |                     v-model="element.name" | ||||||
|  |                     :items="languages" | ||||||
|  |                   /> | ||||||
|  |                   <p | ||||||
|  |                     v-if="form.errors[`languages.${index}.name`]" | ||||||
|  |                     class="mt-2 text-sm text-red-600" | ||||||
|  |                   > | ||||||
|  |                     {{ form.errors[`languages.${index}.name`] }} | ||||||
|  |                   </p> | ||||||
|  |                 </div> | ||||||
|               </div> |               </div> | ||||||
|               <div class="py-4"> |               <div class="py-4"> | ||||||
|                 <label |                 <label | ||||||
| @@ -319,17 +327,25 @@ | |||||||
|           <template #form="{ element, index }"> |           <template #form="{ element, index }"> | ||||||
|             <div class="gap-4 md:grid md:grid-cols-2 "> |             <div class="gap-4 md:grid md:grid-cols-2 "> | ||||||
|               <div class="py-4"> |               <div class="py-4"> | ||||||
|                 <Combobox |                 <label | ||||||
|                   v-model="element.name" |                   :for="`technology-${index}-level`" | ||||||
|                   label="Technologia" |                   class="block text-sm font-medium text-gray-700" | ||||||
|                   :items="technologies" |  | ||||||
|                 /> |  | ||||||
|                 <p |  | ||||||
|                   v-if="form.errors[`technologies.${index}.name`]" |  | ||||||
|                   class="mt-2 text-sm text-red-600" |  | ||||||
|                 > |                 > | ||||||
|                   {{ form.errors[`technologies.${index}.name`] }} |                   Technologia | ||||||
|                 </p> |                 </label> | ||||||
|  |                 <div class="mt-2"> | ||||||
|  |                   <Combobox | ||||||
|  |                     :id="`technology-${index}-level`" | ||||||
|  |                     v-model="element.name" | ||||||
|  |                     :items="technologies" | ||||||
|  |                   /> | ||||||
|  |                   <p | ||||||
|  |                     v-if="form.errors[`technologies.${index}.name`]" | ||||||
|  |                     class="mt-2 text-sm text-red-600" | ||||||
|  |                   > | ||||||
|  |                     {{ form.errors[`technologies.${index}.name`] }} | ||||||
|  |                   </p> | ||||||
|  |                 </div> | ||||||
|               </div> |               </div> | ||||||
|               <div class="py-4"> |               <div class="py-4"> | ||||||
|                 <label |                 <label | ||||||
| @@ -379,6 +395,7 @@ | |||||||
|                 <textarea |                 <textarea | ||||||
|                   :id="`project-description-${index}`" |                   :id="`project-description-${index}`" | ||||||
|                   v-model="element.description" |                   v-model="element.description" | ||||||
|  |                   rows="5" | ||||||
|                   class="block w-full rounded-md shadow-sm sm:text-sm" |                   class="block w-full rounded-md shadow-sm sm:text-sm" | ||||||
|                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.description`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.description`] }" |                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.description`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.description`] }" | ||||||
|                 /> |                 /> | ||||||
| @@ -398,13 +415,11 @@ | |||||||
|                 Technologie |                 Technologie | ||||||
|               </label> |               </label> | ||||||
|               <div class="mt-1 sm:mt-0"> |               <div class="mt-1 sm:mt-0"> | ||||||
|                 <input |                 <MultipleCombobox | ||||||
|                   :id="`project-technologies-${index}`" |                   :id="`project-technologies-${index}`" | ||||||
|                   v-model="element.technologies" |                   v-model="element.technologies" | ||||||
|                   type="text" |                   :items="technologies" | ||||||
|                   class="block w-full rounded-md shadow-sm sm:text-sm" |                 /> | ||||||
|                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.technologies`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.technologies`] }" |  | ||||||
|                 > |  | ||||||
|                 <p |                 <p | ||||||
|                   v-if="form.errors[`projects.${index}.technologies`]" |                   v-if="form.errors[`projects.${index}.technologies`]" | ||||||
|                   class="mt-2 text-sm text-red-600" |                   class="mt-2 text-sm text-red-600" | ||||||
| @@ -470,7 +485,7 @@ | |||||||
|                 <textarea |                 <textarea | ||||||
|                   :id="`project-tasks-${index}`" |                   :id="`project-tasks-${index}`" | ||||||
|                   v-model="element.tasks" |                   v-model="element.tasks" | ||||||
|                   rows="3" |                   rows="5" | ||||||
|                   class="block w-full rounded-md shadow-sm sm:text-sm" |                   class="block w-full rounded-md shadow-sm sm:text-sm" | ||||||
|                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.tasks`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.tasks`] }" |                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`projects.${index}.tasks`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`projects.${index}.tasks`] }" | ||||||
|                 /> |                 /> | ||||||
| @@ -513,6 +528,7 @@ import { useForm } from '@inertiajs/inertia-vue3' | |||||||
| import FlatPickr from 'vue-flatpickr-component' | import FlatPickr from 'vue-flatpickr-component' | ||||||
| import DynamicSection from '@/Shared/Forms/DynamicSection' | import DynamicSection from '@/Shared/Forms/DynamicSection' | ||||||
| import Combobox from '@/Shared/Forms/Combobox' | import Combobox from '@/Shared/Forms/Combobox' | ||||||
|  | import MultipleCombobox from '@/Shared/Forms/MultipleCombobox' | ||||||
| import LevelPicker from '@/Shared/Forms/LevelPicker' | import LevelPicker from '@/Shared/Forms/LevelPicker' | ||||||
| import useLevels from '@/Composables/useLevels' | import useLevels from '@/Composables/useLevels' | ||||||
|  |  | ||||||
| @@ -548,7 +564,7 @@ const form = useForm({ | |||||||
| function addProject() { | function addProject() { | ||||||
|   form.projects.push({ |   form.projects.push({ | ||||||
|     description: null, |     description: null, | ||||||
|     technologies: null, |     technologies: [], | ||||||
|     tasks: null, |     tasks: null, | ||||||
|     startDate: null, |     startDate: null, | ||||||
|     endDate: null, |     endDate: null, | ||||||
|   | |||||||
| @@ -25,12 +25,6 @@ | |||||||
|               > |               > | ||||||
|                 Użytkownik |                 Użytkownik | ||||||
|               </th> |               </th> | ||||||
|               <th |  | ||||||
|                 scope="col" |  | ||||||
|                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" |  | ||||||
|               > |  | ||||||
|                 Opis |  | ||||||
|               </th> |  | ||||||
|               <th |               <th | ||||||
|                 scope="col" |                 scope="col" | ||||||
|                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" |                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
| @@ -43,6 +37,30 @@ | |||||||
|               > |               > | ||||||
|                 Data aktualizacji |                 Data aktualizacji | ||||||
|               </th> |               </th> | ||||||
|  |               <th | ||||||
|  |                 scope="col" | ||||||
|  |                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |               > | ||||||
|  |                 Szkoły | ||||||
|  |               </th> | ||||||
|  |               <th | ||||||
|  |                 scope="col" | ||||||
|  |                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |               > | ||||||
|  |                 Języki | ||||||
|  |               </th> | ||||||
|  |               <th | ||||||
|  |                 scope="col" | ||||||
|  |                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |               > | ||||||
|  |                 Technologie | ||||||
|  |               </th> | ||||||
|  |               <th | ||||||
|  |                 scope="col" | ||||||
|  |                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |               > | ||||||
|  |                 Projekty | ||||||
|  |               </th> | ||||||
|               <th |               <th | ||||||
|                 scope="col" |                 scope="col" | ||||||
|                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" |                 class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
| @@ -76,18 +94,27 @@ | |||||||
|                   </div> |                   </div> | ||||||
|                 </div> |                 </div> | ||||||
|                 <template v-else> |                 <template v-else> | ||||||
|                   {{ resume.name }} |                   <span class="text-sm font-medium text-gray-900 break-all">{{ resume.name }}</span> | ||||||
|                 </template> |                 </template> | ||||||
|               </td> |               </td> | ||||||
|               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> |  | ||||||
|                 {{ resume.description ?? '-' }} |  | ||||||
|               </td> |  | ||||||
|               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> |               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||||||
|                 {{ resume.createdAt }} |                 {{ resume.createdAt }} | ||||||
|               </td> |               </td> | ||||||
|               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> |               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||||||
|                 {{ resume.updatedAt }} |                 {{ resume.updatedAt }} | ||||||
|               </td> |               </td> | ||||||
|  |               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||||||
|  |                 {{ resume.educationCount }} | ||||||
|  |               </td> | ||||||
|  |               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||||||
|  |                 {{ resume.languageCount }} | ||||||
|  |               </td> | ||||||
|  |               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||||||
|  |                 {{ resume.technologyCount }} | ||||||
|  |               </td> | ||||||
|  |               <td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||||||
|  |                 {{ resume.projectCount }} | ||||||
|  |               </td> | ||||||
|               <td class="p-4 text-sm text-right text-gray-500 whitespace-nowrap"> |               <td class="p-4 text-sm text-right text-gray-500 whitespace-nowrap"> | ||||||
|                 <Menu |                 <Menu | ||||||
|                   as="div" |                   as="div" | ||||||
|   | |||||||
| @@ -3,11 +3,9 @@ | |||||||
|     as="div" |     as="div" | ||||||
|     nullable |     nullable | ||||||
|   > |   > | ||||||
|     <ComboboxLabel class="block text-sm font-medium text-gray-700"> |     <div class="relative"> | ||||||
|       {{ label }} |  | ||||||
|     </ComboboxLabel> |  | ||||||
|     <div class="relative mt-2"> |  | ||||||
|       <ComboboxInput |       <ComboboxInput | ||||||
|  |         :id="id" | ||||||
|         class="w-full h-12 rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-blumilk-500 focus:outline-none focus:ring-1 focus:ring-blumilk-500 sm:text-sm" |         class="w-full h-12 rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-blumilk-500 focus:outline-none focus:ring-1 focus:ring-blumilk-500 sm:text-sm" | ||||||
|         @change="query = $event.target.value" |         @change="query = $event.target.value" | ||||||
|       /> |       /> | ||||||
| @@ -51,14 +49,13 @@ import { | |||||||
|   Combobox, |   Combobox, | ||||||
|   ComboboxButton, |   ComboboxButton, | ||||||
|   ComboboxInput, |   ComboboxInput, | ||||||
|   ComboboxLabel, |  | ||||||
|   ComboboxOption, |   ComboboxOption, | ||||||
|   ComboboxOptions, |   ComboboxOptions, | ||||||
| } from '@headlessui/vue' | } from '@headlessui/vue' | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   label: null, |  | ||||||
|   items: Array, |   items: Array, | ||||||
|  |   id: String, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| const query = ref('') | const query = ref('') | ||||||
|   | |||||||
| @@ -23,7 +23,6 @@ | |||||||
|           </button> |           </button> | ||||||
|           <Disclosure |           <Disclosure | ||||||
|             v-slot="{ open }" |             v-slot="{ open }" | ||||||
|             :default-open="false" |  | ||||||
|             as="div" |             as="div" | ||||||
|             class="flex-1 border border-gray-200" |             class="flex-1 border border-gray-200" | ||||||
|           > |           > | ||||||
|   | |||||||
| @@ -1,21 +1,27 @@ | |||||||
| <template> | <template> | ||||||
|   <Combobox |   <Combobox | ||||||
|  |     v-model="selectedItems" | ||||||
|     as="div" |     as="div" | ||||||
|     nullable |     nullable | ||||||
|     multiple |     multiple | ||||||
|   > |   > | ||||||
|     <ComboboxLabel class="block text-sm font-medium text-gray-700"> |     <div class="flex flex-wrap gap-3"> | ||||||
|       {{ label }} |       <button | ||||||
|     </ComboboxLabel> |         v-for="(item, index) in selectedItems" | ||||||
|  |         :key="index" | ||||||
|  |         type="button" | ||||||
|  |         class="py-1 px-2 bg-gray-200 rounded-md" | ||||||
|  |         @click="selectedItems.splice(index, 1)" | ||||||
|  |       > | ||||||
|  |         {{ item }} | ||||||
|  |       </button> | ||||||
|  |     </div> | ||||||
|     <div class="relative mt-2"> |     <div class="relative mt-2"> | ||||||
|       <ComboboxInput |       <ComboboxInput | ||||||
|         as="template" |         :id="id" | ||||||
|         class="w-full h-12 rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-blumilk-500 focus:outline-none focus:ring-1 focus:ring-blumilk-500 sm:text-sm" |         class="w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-blumilk-500 focus:outline-none focus:ring-1 focus:ring-blumilk-500 sm:text-sm" | ||||||
|         :display-value="(item) => item" |  | ||||||
|         @change="query = $event.target.value" |         @change="query = $event.target.value" | ||||||
|       > |       /> | ||||||
|         <span>aee</span> |  | ||||||
|       </ComboboxInput> |  | ||||||
|       <ComboboxButton class="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none"> |       <ComboboxButton class="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none"> | ||||||
|         <SelectorIcon class="h-5 w-5 text-gray-400" /> |         <SelectorIcon class="h-5 w-5 text-gray-400" /> | ||||||
|       </ComboboxButton> |       </ComboboxButton> | ||||||
| @@ -33,7 +39,7 @@ | |||||||
|         > |         > | ||||||
|           <li :class="['relative cursor-default select-none py-2 pl-3 pr-9', active ? 'bg-blumilk-600 text-white' : 'text-gray-900']"> |           <li :class="['relative cursor-default select-none py-2 pl-3 pr-9', active ? 'bg-blumilk-600 text-white' : 'text-gray-900']"> | ||||||
|             <span :class="['block truncate', selected && 'font-semibold']"> |             <span :class="['block truncate', selected && 'font-semibold']"> | ||||||
|               {{ item.name }} |               {{ item }} | ||||||
|             </span> |             </span> | ||||||
|  |  | ||||||
|             <span |             <span | ||||||
| @@ -56,21 +62,31 @@ import { | |||||||
|   Combobox, |   Combobox, | ||||||
|   ComboboxButton, |   ComboboxButton, | ||||||
|   ComboboxInput, |   ComboboxInput, | ||||||
|   ComboboxLabel, |  | ||||||
|   ComboboxOption, |   ComboboxOption, | ||||||
|   ComboboxOptions, |   ComboboxOptions, | ||||||
| } from '@headlessui/vue' | } from '@headlessui/vue' | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   label: null, |  | ||||||
|   items: Array, |   items: Array, | ||||||
|  |   modelValue: Array, | ||||||
|  |   id: String, | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | const emit = defineEmits(['update:modelValue']) | ||||||
|  |  | ||||||
| const query = ref('') | const query = ref('') | ||||||
|  |  | ||||||
|  | const selectedItems = computed({ | ||||||
|  |   get: () => props.modelValue, | ||||||
|  |   set: (value) => { | ||||||
|  |     query.value = '' | ||||||
|  |     emit('update:modelValue', value) | ||||||
|  |   }, | ||||||
|  | }) | ||||||
|  |  | ||||||
| const filteredItems = computed(() => | const filteredItems = computed(() => | ||||||
|   query.value === '' |   query.value === '' | ||||||
|     ? props.items |     ? props.items | ||||||
|     : props.items.filter((item) => item.name.toLowerCase().includes(query.value.toLowerCase())), |     : props.items.filter((item) => item.toLowerCase().includes(query.value.toLowerCase())), | ||||||
| ) | ) | ||||||
| </script> | </script> | ||||||
		Reference in New Issue
	
	Block a user