web/satellite: update project member invite modal

The project member invite modal has been updated to match the new figma
design.

Issue: https://github.com/storj/storj/issues/5744

Change-Id: I9ed7ad4ede0fb6f7f42f56b2d8386e12a5a5b6c1
This commit is contained in:
Wilfred Asomani 2023-05-04 13:33:40 +00:00 committed by Storj Robot
parent f61230a670
commit e3573f44ea
2 changed files with 157 additions and 331 deletions

View File

@ -4,75 +4,58 @@
<template>
<VModal :on-close="closeModal">
<template #content>
<div class="add-user">
<div class="add-user__main">
<div class="add-user__info-panel-container">
<h2 class="add-user__info-panel-container__title">Add Team Member</h2>
<img src="@/../static/images/team/addMember.jpg" alt="add team member image">
</div>
<div class="add-user__form-container">
<h2 class="add-user__form-container__title">Add Team Member</h2>
<p v-if="!formError" class="add-user__form-container__common-label">Email Address</p>
<div v-if="formError" class="add-user__form-container__label">
<ErrorIcon alt="Red error icon" />
<p class="add-user__form-container__label__error">{{ formError }}</p>
</div>
<div class="add-user__form-container__inputs-group">
<div
v-for="(input, index) in inputs"
:key="index"
class="add-user__form-container__inputs-group__item"
>
<input
v-model="input.value"
placeholder="email@example.com"
class="no-error-input"
:class="{ 'error-input': input.error }"
@keyup="resetFormErrors(index)"
>
<DeleteFieldIcon
class="add-user__form-container__inputs-group__item__image"
@click="deleteInput(index)"
/>
</div>
</div>
<div class="add-user-row">
<div id="add-user-button" class="add-user-row__item" @click="addInput">
<div :class="{ 'inactive-image': isMaxInputsCount }">
<AddFieldIcon class="add-user-row__item__image" />
</div>
<p class="add-user-row__item__label" :class="{ 'inactive-label': isMaxInputsCount }">Add More</p>
</div>
</div>
<div class="add-user__form-container__button-container">
<VButton
label="Cancel"
width="100%"
height="48px"
:on-press="closeModal"
:is-transparent="true"
/>
<VButton
label="Add Team Members"
width="100%"
height="48px"
:on-press="onAddUsersClick"
:is-disabled="!isButtonActive"
/>
</div>
<div class="modal">
<div class="modal__header">
<TeamMembersIcon />
<h1 class="modal__header__title">Invite team members</h1>
</div>
<p class="modal__info">
Add team members to contribute to this project.
</p>
<div class="modal__input-group">
<VInput
v-for="(_, index) in inputs"
:key="index"
class="modal__input-group__item"
label="Email"
height="38px"
placeholder="email@email.com"
role-description="email"
:error="formError"
@setData="(str) => setInput(index, str)"
/>
</div>
<div class="modal__more">
<div
tabindex="0"
class="modal__more__button"
@click.stop="addInput"
>
<AddCircleIcon class="modal__more__button__icon" :class="{ inactive: isMaxInputsCount }" />
<span class="modal__more__button__label" :class="{ inactive: isMaxInputsCount }">Add more</span>
</div>
</div>
<div class="notification-wrap">
<AddMemberNotificationIcon class="notification-wrap__image" />
<div class="notification-wrap__text-area">
<p class="notification-wrap__text-area__text">
If the team member you want to invite to join the project is still not on this Satellite, please
share this link to the signup page and ask them to register here:
<router-link target="_blank" rel="noopener noreferrer" exact to="/signup">
{{ registerPath }}
</router-link>
</p>
</div>
<div class="modal__buttons">
<VButton
label="Cancel"
height="48px"
font-size="14px"
border-radius="10px"
:is-transparent="true"
:on-press="closeModal"
/>
<VButton
label="Invite"
height="48px"
font-size="14px"
border-radius="10px"
:on-press="onAddUsersClick"
:is-disabled="!isButtonActive"
/>
</div>
</div>
</template>
@ -96,11 +79,10 @@ import { useProjectsStore } from '@/store/modules/projectsStore';
import VButton from '@/components/common/VButton.vue';
import VModal from '@/components/common/VModal.vue';
import VInput from '@/components/common/VInput.vue';
import ErrorIcon from '@/../static/images/register/ErrorInfo.svg';
import AddFieldIcon from '@/../static/images/team/addField.svg';
import AddMemberNotificationIcon from '@/../static/images/team/addMemberNotification.svg';
import DeleteFieldIcon from '@/../static/images/team/deleteField.svg';
import TeamMembersIcon from '@/../static/images/team/teamMembers.svg';
import AddCircleIcon from '@/../static/images/common/addCircle.svg';
const appStore = useAppStore();
const pmStore = useProjectMembersStore();
@ -111,7 +93,7 @@ const notify = useNotify();
const FIRST_PAGE = 1;
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
const inputs = ref<EmailInput[]>([new EmailInput(), new EmailInput(), new EmailInput()]);
const inputs = ref<EmailInput[]>([new EmailInput()]);
const formError = ref<string>('');
const isLoading = ref<boolean>(false);
@ -151,6 +133,11 @@ const registerPath = computed((): string => {
return location.host + RouteConfig.Register.path;
});
function setInput(index: number, str: string) {
resetFormErrors(index);
inputs.value[index].value = str;
}
/**
* Tries to add users related to entered emails list to current project.
*/
@ -183,7 +170,7 @@ async function onAddUsersClick(): Promise<void> {
newInputsArray.unshift(element);
areAllEmailsValid = false;
formError.value = 'Field is required. Please enter a valid email address';
formError.value = 'Please enter a valid email address';
}
inputs.value = [...newInputsArray];
@ -220,7 +207,7 @@ async function onAddUsersClick(): Promise<void> {
}
analytics.eventTriggered(AnalyticsEvent.PROJECT_MEMBERS_INVITE_SENT);
await notify.notify(`The user(s) you've invited to your project will receive your invitation if they have an account on this satellite.`);
await notify.notify('Invites sent!');
pmStore.setSearchQuery('');
try {
@ -275,297 +262,127 @@ function resetFormErrors(index: number): void {
</script>
<style scoped lang='scss'>
.add-user {
width: 100%;
max-width: 1200px;
display: flex;
flex-direction: column;
justify-content: center;
font-family: 'font_regular', sans-serif;
.modal {
width: 346px;
padding: 32px;
&__main {
border-radius: 6px 6px 0 0;
display: flex;
align-items: flex-start;
justify-content: center;
background-color: #fff;
padding: 80px 24px;
width: calc(100% - 48px);
@media screen and (max-width: 950px) {
padding: 48px 24px;
}
@media screen and (max-width: 460px) {
width: 280px;
padding: 16px;
}
&__info-panel-container {
&__header {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
margin-right: 150px;
padding-bottom: 16px;
margin-bottom: 16px;
border-bottom: 1px solid var(--c-grey-2);
@media screen and (max-width: 950px) {
display: none;
@media screen and (max-width: 460px) {
flex-direction: column;
align-items: flex-start;
}
&__title {
margin-left: 16px;
font-family: 'font_bold', sans-serif;
font-size: 32px;
line-height: 29px;
color: #384b65;
margin: 0 0 90px;
width: 130%;
text-align: end;
}
}
&__attention-text {
font-size: 10px !important;
line-height: 15px !important;
}
&__form-container {
width: 100%;
max-width: 600px;
@media screen and (max-width: 950px) {
max-width: unset;
}
&__title {
display: none;
font-family: 'font_bold', sans-serif;
font-size: 28px;
color: #384b65;
margin-bottom: 20px;
font-size: 24px;
line-height: 31px;
letter-spacing: -0.02em;
color: var(--c-black);
text-align: left;
@media screen and (max-width: 950px) {
display: block;
}
}
&__label {
display: flex;
padding-left: 50px;
margin-bottom: 15px;
@media screen and (max-width: 950px) {
padding: 0;
}
@media screen and (max-width: 550px) {
svg {
display: none;
}
}
&__error {
margin-left: 10px;
color: #eb5757;
text-align: left;
@media screen and (max-width: 550px) {
margin: 0;
}
}
}
&__inputs-group {
padding: 3px 50px 0;
@media screen and (max-width: 950px) {
padding: 0;
}
&__item {
display: flex;
align-items: center;
.no-error-input {
font-size: 16px;
line-height: 21px;
resize: none;
margin-bottom: 18px;
height: 48px;
width: 100%;
text-indent: 20px;
border-color: rgb(56 75 101 / 40%);
border-radius: 6px;
&:last-child {
margin-bottom: 0;
}
}
&__image {
margin-bottom: 18px;
margin-left: 20px;
cursor: pointer;
&:hover .delete-input-svg-path {
fill: #2683ff;
}
}
}
}
.full-input {
margin-bottom: 18px;
&:last-child {
margin-bottom: 0;
}
}
&__common-label {
margin: 0 0 10px;
font-family: 'font_medium', sans-serif;
font-size: 16px;
line-height: 25px;
padding-left: 50px;
text-align: left;
@media screen and (max-width: 950px) {
padding-left: unset;
}
}
&__button-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 30px;
padding: 0 80px 0 50px;
column-gap: 20px;
@media screen and (max-width: 950px) {
padding: 0;
}
@media screen and (max-width: 420px) {
flex-direction: column-reverse;
row-gap: 10px;
column-gap: unset;
@media screen and (max-width: 460px) {
margin: 10px 0 0;
}
}
}
}
.add-user-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 80px 0 50px;
@media screen and (max-width: 950px) {
padding: 0;
&__info {
font-family: 'font_regular', sans-serif;
font-size: 14px;
line-height: 19px;
color: var(--c-black);
border-bottom: 1px solid var(--c-grey-2);
text-align: left;
padding-bottom: 16px;
margin-bottom: 16px;
}
&__item {
display: flex;
align-items: center;
justify-content: space-between;
&__input-group {
&__image {
margin-right: 20px;
&__item {
border-bottom: 1px solid var(--c-grey-2);
padding-bottom: 16px;
margin-bottom: 16px;
}
}
&__label {
font-family: 'font_medium', sans-serif;
font-size: 16px;
margin-left: 0;
padding-left: 0;
margin-block-start: 0;
margin-block-end: 0;
}
&__more {
border-bottom: 1px solid var(--c-grey-2);
padding-bottom: 16px;
margin-bottom: 16px;
&:first-child {
&__button {
width: fit-content;
display: flex;
column-gap: 5px;
align-items: flex-end;
cursor: pointer;
&__icon {
width: 18px;
height: 18px;
&.inactive {
:deep(path) {
fill: var(--c-grey-5);
}
}
:deep(path) {
fill: var(--c-blue-3);
}
}
&__label {
font-family: 'font_regular', sans-serif;
font-size: 16px;
text-decoration: underline;
text-align: center;
color: var(--c-blue-3);
&.inactive {
color: var(--c-grey-5);
}
}
}
}
}
.inactive-label {
cursor: default;
color: #dadde5;
}
.error-input {
border: 1px solid red !important;
}
.inactive-image {
cursor: default;
.add-user-row__item__image {
&__rect {
fill: #dadde5;
}
&__path {
fill: #acb0bc;
}
}
}
.input-container.full-input {
width: 100%;
}
.red {
background-color: #eb5757;
}
.notification-wrap {
background-color: rgb(194 214 241 / 100%);
height: 98px;
display: flex;
justify-content: flex-start;
padding: 0 50px;
align-items: center;
border-radius: 0 0 6px 6px;
@media screen and (max-width: 950px) {
height: unset;
padding: 24px;
}
&__image {
margin-right: 40px;
min-width: 40px;
&__buttons {
display: flex;
column-gap: 10px;
margin-top: 10px;
width: 100%;
@media screen and (max-width: 500px) {
display: none;
}
}
&__text-area {
display: flex;
align-items: center;
&__text {
font-family: 'font_medium', sans-serif;
font-size: 16px;
text-align: left;
@media screen and (max-width: 500px) {
font-size: 14px;
}
flex-direction: column-reverse;
column-gap: unset;
row-gap: 10px;
}
}
}
:deep(.container) {
padding: 0 10px;
:deep(.label-container__main__label) {
font-size: 14px;
}
@media screen and (max-width: 500px) {
:deep(.label-container__main__error) {
font-size: 14px;
}
:deep(.container) {
padding: 0;
}
:deep(.input-container) {
margin-top: 0;
}
</style>

View File

@ -0,0 +1,9 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.4423 0H23.3463C28.8835 0 31.0805 0.613723 33.2353 1.76617C35.3902 2.91861 37.0814 4.60977 38.2338 6.76466L38.3214 6.93056C39.4029 9.00672 39.9846 11.2 40 16.4423V23.3463C40 28.8835 39.3863 31.0805 38.2338 33.2353C37.0814 35.3902 35.3902 37.0814 33.2353 38.2338L33.0694 38.3214C30.9933 39.4029 28.8 39.9846 23.5577 40H16.6537C11.1165 40 8.91954 39.3863 6.76466 38.2338C4.60977 37.0814 2.91861 35.3902 1.76617 33.2353L1.67858 33.0694C0.597074 30.9933 0.0154219 28.8 0 23.5577V16.6537C0 11.1165 0.613723 8.91954 1.76617 6.76466C2.91861 4.60977 4.60977 2.91861 6.76466 1.76617L6.93055 1.67858C9.00672 0.597074 11.2 0.0154219 16.4423 0Z" fill="#0218A7"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M31.2125 30.6406C33.8621 30.6406 36.3477 31.3403 38.493 32.5643C38.3859 32.791 38.2729 33.0134 38.1542 33.2354C37.0017 35.3903 35.3106 37.0815 33.1557 38.2339L32.9898 38.3215C30.9231 39.3981 28.7404 39.9794 23.5498 39.9999L17.5205 40.0001C19.637 34.5254 24.9692 30.6406 31.2125 30.6406Z" fill="#00E366"/>
<path d="M31.2401 28.0743C34.4485 28.0743 37.0495 25.4841 37.0495 22.2891C37.0495 19.094 34.4485 16.5039 31.2401 16.5039C28.0316 16.5039 25.4307 19.094 25.4307 22.2891C25.4307 25.4841 28.0316 28.0743 31.2401 28.0743Z" fill="#0149FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.6541 30.6406C14.8974 30.6406 20.2296 34.5254 22.3461 40L16.5744 40.0001C11.0373 40.0001 8.8403 39.3863 6.68542 38.2339C4.53054 37.0814 2.83938 35.3903 1.68693 33.2354L1.59935 33.0695C1.5143 32.9062 1.43235 32.7422 1.35352 32.5761C3.50327 31.3447 5.99611 30.6406 8.6541 30.6406Z" fill="#0149FF"/>
<path d="M8.68049 28.0743C11.8889 28.0743 14.4899 25.4841 14.4899 22.2891C14.4899 19.094 11.8889 16.5039 8.68049 16.5039C5.47205 16.5039 2.87109 19.094 2.87109 22.2891C2.87109 25.4841 5.47205 28.0743 8.68049 28.0743Z" fill="#FF458B"/>
<path d="M20.0174 28.075C23.9523 28.075 27.1422 24.8984 27.1422 20.9799C27.1422 17.0614 23.9523 13.8848 20.0174 13.8848C16.0825 13.8848 12.8926 17.0614 12.8926 20.9799C12.8926 24.8984 16.0825 28.075 20.0174 28.075Z" fill="#FFC600"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.9725 30.6406C25.5731 30.6406 30.4404 33.7667 32.9111 38.3622L32.9895 38.3215C30.9229 39.398 28.7402 39.9793 23.5495 39.9998L16.5737 40.0001C11.316 40.0001 9.06986 39.4467 7.01172 38.4042C9.47493 33.7858 14.3549 30.6406 19.9725 30.6406Z" fill="#FFC600"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB