Files
chill-bundles/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources.vue
2024-11-14 18:47:38 +01:00

178 lines
5.0 KiB
Vue

<template>
<div class="vue-component">
<h2><a id="section-90" />{{ $t("resources.title") }}</h2>
<div v-if="resources.length > 0">
<label class="col-form-label">{{
$tc("resources.counter", counter)
}}</label>
</div>
<div v-else>
<label class="chill-no-data-statement">{{
$tc("resources.counter", counter)
}}</label>
</div>
<div class="flex-table mb-3">
<resource-item
v-for="resource in resources"
:resource="resource"
:key="resource.id"
@remove="removeResource"
/>
</div>
<div v-if="suggestedEntities.length > 0">
<ul class="list-suggest add-items inline">
<li
v-for="p in suggestedEntities"
:key="uniqueId(p)"
@click="addSuggestedEntity(p)"
>
<person-text v-if="p.type === 'person'" :person="p" />
<span v-else>{{ p.text }}</span>
</li>
</ul>
</div>
<div>
<ul class="record_actions">
<li class="add-persons">
<add-persons
button-title="resources.add_resources"
modal-title="resources.add_resources"
:key="addPersons.key"
:options="addPersons.options"
@add-new-persons="addNewPersons"
ref="addPersons"
>
<!-- to cast child method -->
</add-persons>
</li>
</ul>
</div>
</div>
</template>
<script>
import { mapState } from "vuex";
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
import ResourceItem from "./Resources/ResourceItem.vue";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
export default {
name: "Resources",
components: {
AddPersons,
ResourceItem,
PersonText,
},
data() {
return {
addPersons: {
key: "resources",
options: {
type: ["person", "thirdparty"],
priority: null,
uniq: false,
},
},
};
},
computed: mapState({
resources: (state) => state.accompanyingCourse.resources,
counter: (state) => state.accompanyingCourse.resources.length,
suggestedEntities: (state) =>
[
state.accompanyingCourse.requestor,
...state.accompanyingCourse.participations
.filter((p) => p.endDate === null)
.map((p) => p.person),
]
.filter((e) => e !== null)
.filter((e) => {
if (e.type === "person") {
return !state.accompanyingCourse.resources
.filter((r) => r.resource.type === "person")
.map((r) => r.resource.id)
.includes(e.id);
}
if (e.type === "thirdparty") {
return !state.accompanyingCourse.resources
.filter((r) => r.resource.type === "thirdparty")
.map((r) => r.resource.id)
.includes(e.id);
}
})
// filter persons appearing twice in requestor and resources
.filter((e, index, suggested) => {
for (let i = 0; i < suggested.length; i = i + 1) {
if (i < index && e.id === suggested[i].id) {
return false;
}
}
return true;
}),
}),
methods: {
removeResource(item) {
//console.log('@@ CLICK remove resource: item', item);
this.$store
.dispatch("removeResource", item)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
addNewPersons({ selected, modal }) {
//console.log('@@@ CLICK button addNewPersons', selected);
selected.forEach(function (item) {
this.$store
.dispatch("addResource", item)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: violations });
}
});
}, this);
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
},
addSuggestedEntity(e) {
this.$store
.dispatch("addResource", { result: e, type: e.type })
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
uniqueId(e) {
return `${e.type}-${e.id}`;
},
},
};
</script>
<style lang="scss">
div.flex-bloc {
div.item-bloc {
flex-basis: 50%;
}
}
</style>