Skip to content

Commit

Permalink
fix #37, fix #39 (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorinZarafu authored Jul 20, 2023
1 parent 9cc8e9e commit b941660
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 50 deletions.
97 changes: 57 additions & 40 deletions resources/js/Components/form/SelectMultiple.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<template>

<Combobox class="z-100" as="div" v-model="selectedOption" v-bind="{ disabled: isDisabled }">
<ComboboxLabel class="block text-sm font-medium leading-6 text-gray-900">{{ label }}</ComboboxLabel>
<div class="relative">
Expand All @@ -14,39 +13,43 @@
<ComboboxOptions
class="absolute z-10 w-full py-1 mt-1 overflow-auto text-base bg-white rounded-md shadow-lg max-h-60 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
>
<div class="z-20 my-1.5 sticky top-1.5 px-2">
<ComboboxInput
class="w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-primary-500 sm:text-sm sm:leading-6"
@input="query = $event.target.value"
<div class="z-100 my-1.5 sticky top-1.5 px-2 bg-white">
<input
v-model="query"
class="w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-1 outline-none focus:ring-inset focus:ring-primary-500 sm:text-sm sm:leading-6"
/>
</div>

<ComboboxOption
v-for="option in selectOptions" :key="option.id"
v-for="(option ,index) in selectOptions" :key="index"
:value="option"
as="template"
v-slot="{ active, selected }"
>
<li :class="['relative cursor-default select-none py-2 pl-3 pr-9', active ? 'bg-primary-500 text-white' : 'text-gray-900']">
<span :class="['block truncate', selected && 'font-semibold']">
<li
@click="toggleOptions(option)"
:class="['relative cursor-default select-none py-2 pl-3 pr-9',('singleValue' === type && tmpSelectedOptions.includes(option)) || ('object' === type && tmpSelectedOptions.includes(option)) ? 'bg-primary-500 text-white' : 'text-gray-900']"
>
<span :class="['block truncate', ('singleValue' === type && tmpSelectedOptions.includes(option)) || ('object' === type && tmpSelectedOptions.includes(option)) && 'font-semibold']">
{{ option.name ? option.name : option }}
</span>

<span v-if="selected"
:class="['absolute inset-y-0 right-0 flex items-center pr-4', active ? 'text-white' : 'text-primary-500']">
<span v-if="('singleValue' === type && tmpSelectedOptions.includes(option)) || ('object' === type && tmpSelectedOptions.includes(option))"
:class="['absolute inset-y-0 right-0 flex items-center pr-4', ('singleValue' === type && tmpSelectedOptions.includes(option)) || ('object' === type && tmpSelectedOptions.includes(option)) ? 'text-white' : 'text-primary-500']">
<CheckIcon class="w-5 h-5" aria-hidden="true"/>
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</div>
<div
class="text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 bg-primary text-primary rounded-full mt-2 mr-2"
@click="removeElement(option)"
class="inline-flex items-center px-3 py-1 mt-2 mr-2 text-xs font-bold text-white uppercase rounded-full cursor-pointer group bg-primary-500 leading-sm bg-primary text-primary"
v-for="option in tmpSelectedOptions"
>
{{ option.name ? option.name : option }}
<span class="ml-2" @click="removeElement(option.id)">x</span>
<XCircleIcon class="w-4 h-4 ml-2 text-white" aria-hidden="true"/>
</div>

<!-- Error -->
<p v-show="error" class="mt-2 text-sm text-red-600">{{ error }}</p>
</Combobox>
Expand All @@ -57,7 +60,7 @@
import {computed, ref, watch} from 'vue';
/** Import plugins. */
import {CheckIcon, ChevronUpDownIcon} from '@heroicons/vue/20/solid';
import {CheckIcon, ChevronUpDownIcon, XCircleIcon} from '@heroicons/vue/20/solid';
import {Combobox, ComboboxButton, ComboboxInput, ComboboxLabel, ComboboxOption, ComboboxOptions} from '@headlessui/vue';
/** Component props. */
Expand All @@ -69,6 +72,10 @@ const props = defineProps({
isDisabled: {
type: Boolean,
disabled: false
},
type: {
type: String,
default: 'object'
}
});
Expand All @@ -80,37 +87,47 @@ let tmpSelectedOptions = ref(props.modelValue);
let selectedOption = ref(props.modelValue);
function removeElement(id) {
tmpSelectedOptions.value = tmpSelectedOptions.value.filter((option) => option.id !== id);
}
/** Initialize emits. */
const emit = defineEmits(['update:modelValue', 'selected']);
function removeElement(opt) {
if ('singleValue' === props.type) {
tmpSelectedOptions.value = tmpSelectedOptions.value.filter((option) => option != opt);
} else if (props.type === 'object') {
tmpSelectedOptions.value = tmpSelectedOptions.value.filter((option) => option.id !== opt.id);
}
emit('update:modelValue', tmpSelectedOptions.value)
}
/** Option list. */
const selectOptions = computed(() =>
query.value === '' ? props.options : props.options.filter((option) => {
return option.name.toLowerCase().includes(query.value.toLowerCase())
})
);
/** Watch changes in selected options. */
watch(selectedOption, (newVal, oldVal) => {
if (tmpSelectedOptions.value.filter((option) => option.id === newVal.id).length === 0) {
tmpSelectedOptions.value.push(newVal);
const selectOptions = computed(() => {
if('singleValue' === props.type) {
return query.value === '' ? props.options : props.options.filter((option) => {
return option.toLowerCase().includes(query.value.toLowerCase())
})
}else if ('object' === props.type) {
return query.value === '' ? props.options : props.options.filter((option) => {
return option.name.toLowerCase().includes(query.value.toLowerCase())
})
}
emit('update:modelValue', tmpSelectedOptions.value);
});
})
watch(tmpSelectedOptions, (newVal, oldVal) => {
const toggleOptions = (newVal) => {
if ('singleValue' === props.type) {
if(!tmpSelectedOptions.value.includes(newVal)) {
tmpSelectedOptions.value.push(newVal);
} else {
tmpSelectedOptions.value = tmpSelectedOptions.value.filter((option) => `${option}` != `${newVal}`)
}
} else if ('object' === props.type) {
if(!tmpSelectedOptions.value.includes(newVal)) {
tmpSelectedOptions.value.push(newVal);
} else {
tmpSelectedOptions.value = tmpSelectedOptions.value.filter((option) => option.id != newVal.id)
}
}
emit('update:modelValue', tmpSelectedOptions.value);
})
</script>

<style scoped>
ul {
flex-wrap: nowrap;
overflow-x: auto;
white-space: nowrap;
}
</style>
</script>
10 changes: 5 additions & 5 deletions resources/js/Components/templates/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,22 @@ const navigation = [
subroutes: ['admin.ong.project.add', 'admin.ong.project.edit'],
subMenu: [
{
name: 'admin.ong.volunteers',
name: 'volunteers_approved',
href: route('admin.ong.volunteers', {'status': 'approved'}),
route: route('admin.ong.volunteers', {'status': 'approved'}),
icon: UserGroupIcon,
subroutes: [],
},
{
name: 'admin.ong.volunteers',
href: route('admin.ong.volunteers', {'status': 'approved'}),
name: 'volunteers_pending',
href: route('admin.ong.volunteers', {'status': 'pending'}),
route: route('admin.ong.volunteers', {'status': 'pending'}),
subroutes: [],
icon: UserPlusIcon
},
{
name: 'admin.ong.volunteers',
href: route('admin.ong.volunteers', {'status': 'approved'}),
name: 'volunteers_rejected',
href: route('admin.ong.volunteers', {'status': 'rejected'}),
route: route('admin.ong.volunteers', {'status': 'rejected'}),
subroutes: [],
icon: UserMinusIcon
Expand Down
2 changes: 1 addition & 1 deletion resources/js/Pages/AdminOng/Ong/EditOng.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<div class="flex items-center justify-center w-8 h-8 rounded-lg bg-primary-500">
<SvgLoader class="shrink-0" name="menu"/>
</div>
<h2 class="text-2xl font-bold text-gray-900">{{ $t('edit_project_title') }}</h2>
<h2 class="text-2xl font-bold text-gray-900">{{ $t('ong_description') }}</h2>
</header>

<!-- Alert -->
Expand Down
9 changes: 6 additions & 3 deletions resources/js/Pages/AdminOng/Projects/AddProject.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@
/>

<!-- Project category -->
<Select
<SelectMultiple
class="w-full xl:w-1/2"
:label="$t('project_category_label')"
:options="projectCategories"
use-translation="true"
:options="projectCategories"
v-model="form.category"
type="singleValue"
v-if="!form.is_national"
:error="form.errors.category"
/>

Expand Down Expand Up @@ -91,6 +93,7 @@
class="w-full xl:w-1/2"
:label="$t('counties_label')"
:options="countries"
type="object"
v-model="selectedCounties"
v-if="!form.is_national"
:error="form.errors.counties"
Expand Down Expand Up @@ -292,7 +295,7 @@ import SelectMultiple from "@/Components/form/SelectMultiple.vue";
const form = useForm({
name: '',
target_budget: '',
category: '',
category: [],
start: '',
end: '',
counties: [],
Expand Down
3 changes: 2 additions & 1 deletion resources/js/locales/ro.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,5 +387,6 @@ export default {
"see_bcr_projects": "Vezi proiectele BCR",
"donate_for_good": "Donează pentru fapte bune",
"project_categories": "Proiecte din categoria",
"donation_period": "Perioada donatii"
"donation_period": "Perioada donatii",
"ong_description": "Descriere organizație"
}

0 comments on commit b941660

Please sign in to comment.