pixelfed/resources/assets/components/groups/partials/GroupInviteModal.vue

191 lines
4.6 KiB
Vue
Raw Normal View History

2024-07-10 05:52:08 +00:00
<template>
<div class="group-invite-modal">
<b-modal
ref="modal"
hide-header
hide-footer
centered
rounded
body-class="rounded group-invite-modal-wrapper">
<div class="text-center py-3 d-flex align-items-center flex-column">
<div class="bg-light rounded-circle d-flex justify-content-center align-items-center mb-3" style="width: 100px;height: 100px;">
<i class="far fa-user-plus fa-2x text-lighter"></i>
</div>
<p class="h4 font-weight-bold mb-0">Invite Friends</p>
<!-- <p class="mb-0">Search {{ group.name }} for posts, comments or members.</p> -->
</div>
<transition name="fade">
<div v-if="usernames.length < 5" class="d-flex justify-content-between mt-1">
<autocomplete
:search="autocompleteSearch"
placeholder="Search friends by username"
aria-label="Search this group"
:get-result-value="getSearchResultValue"
:debounceTime="700"
@submit="onSearchSubmit"
style="width: 100%;"
ref="autocomplete"
>
<template #result="{ result, props }">
<li
v-bind="props"
class="autocomplete-result"
>
<div class="text-truncate">
<p class="result-name mb-0 font-weight-bold">
{{ result.username }}
</p>
</div>
</li>
</template>
</autocomplete>
<button class="btn btn-light border rounded-circle text-lighter ml-3" style="width: 52px;height:50px;" @click="close">
<i class="fal fa-times fa-lg"></i>
</button>
</div>
</transition>
<transition name="fade">
<div v-if="usernames.length" class="pt-3">
<div v-for="(result, index) in usernames" class="py-1">
<div class="media align-items-center">
<img src="/storage/avatars/default.jpg" class="rounded-circle border mr-3" width="45" height="45">
<div class="media-body">
<p class="lead mb-0">{{ result.username }}</p>
</div>
<button class="btn btn-link text-lighter btn-sm" @click="removeUsername(index)"><i class="far fa-times-circle fa-lg"></i></button>
</div>
</div>
</div>
</transition>
<transition name="fade">
<button v-if="usernames && usernames.length" class="btn btn-primary btn-lg btn-block font-weight-bold rounded font-weight-bold mt-3" @click="submitInvites">Invite</button>
</transition>
<div class="text-center pt-3 small">
<p class="mb-0">You can invite up to 5 friends at a time, and 20 friends in total.</p>
</div>
</b-modal>
</div>
</template>
<script type="text/javascript">
import Autocomplete from '@trevoreyre/autocomplete-vue'
import '@trevoreyre/autocomplete-vue/dist/style.css'
export default {
props: {
group: {
type: Object
},
profile: {
type: Object
}
},
components: {
'autocomplete-input': Autocomplete,
},
data() {
return {
query: '',
recent: [],
loaded: false,
usernames: [],
isSubmitting: false
}
},
methods: {
open() {
this.$refs.modal.show();
},
close() {
this.$refs.modal.hide();
},
autocompleteSearch(q) {
if (!q || q.length == 0) {
return [];
}
return axios.post(`/api/v0/groups/search/invite/friends`, {
q: q,
g: this.group.id,
v: '0.2'
}).then(res => {
let data = res.data.filter(r => {
return this.usernames.map(u => u.username).indexOf(r.username) == -1;
});
return data;
});
return [];
},
getSearchResultValue(result) {
return result.username;
},
onSearchSubmit(result) {
this.usernames.push(result);
this.$refs.autocomplete.value = '';
//
},
removeUsername(index) {
event.currentTarget.blur();
this.usernames.splice(index, 1);
},
submitInvites() {
this.isSubmitting = true;
event.currentTarget.blur();
axios.post('/api/v0/groups/search/invite/friends/send', {
g: this.group.id,
uids: this.usernames.map(u => u.id)
}).then(res => {
this.usernames = [];
this.isSubmitting = false;
this.close();
swal('Success', 'Successfully sent invite(s)', 'success');
}).catch(err => {
this.usernames = [];
this.isSubmitting = false;
if(err.response.status === 422) {
swal('Error', err.response.data.error, 'error');
} else {
swal('Oops!', 'An error occured, please try again later', 'error');
}
this.close();
})
}
}
}
</script>
<style lang="scss">
.group-invite-modal {
&-wrapper {
.media {
height: 60px;
padding: 10px;
border-radius: 10px;
user-select: none;
cursor: pointer;
&:hover {
background-color: #E5E7EB;
}
}
}
}
</style>