From d28269ebb0e67b2a741d5f2f16da38fe923a6340 Mon Sep 17 00:00:00 2001 From: Gregor Vostrak Date: Mon, 3 Jun 2024 18:44:00 +0200 Subject: [PATCH] add project member edit modal, fixes ST-119 --- e2e/projects.spec.ts | 2 + .../Common/Member/MemberCombobox.vue | 14 ++- .../ProjectMember/ProjectMemberEditModal.vue | 87 +++++++++++++++++++ .../ProjectMemberMoreOptionsDropdown.vue | 11 ++- .../ProjectMember/ProjectMemberTableRow.vue | 17 +++- resources/js/utils/api.ts | 5 ++ resources/js/utils/useProjectMembers.ts | 23 +++++ 7 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 resources/js/Components/Common/ProjectMember/ProjectMemberEditModal.vue diff --git a/e2e/projects.spec.ts b/e2e/projects.spec.ts index 797963a1..d9bb0038 100644 --- a/e2e/projects.spec.ts +++ b/e2e/projects.spec.ts @@ -69,3 +69,5 @@ test('test that creating and deleting a new project via the modal works', async // Add Project with billable rate // Edit Project with billable rate + +// Edit Project Member Billable Rate diff --git a/resources/js/Components/Common/Member/MemberCombobox.vue b/resources/js/Components/Common/Member/MemberCombobox.vue index 8a40ed54..ed0f97f9 100644 --- a/resources/js/Components/Common/Member/MemberCombobox.vue +++ b/resources/js/Components/Common/Member/MemberCombobox.vue @@ -16,9 +16,16 @@ const model = defineModel({ default: '', }); -const props = defineProps<{ - hiddenMembers: ProjectMember[]; -}>(); +const props = withDefaults( + defineProps<{ + hiddenMembers: ProjectMember[]; + disabled: boolean; + }>(), + { + hiddenMembers: () => [] as ProjectMember[], + disabled: false, + } +); const searchInput = ref(null); @@ -161,6 +168,7 @@ function onUnfocus() { +import SecondaryButton from '@/Components/SecondaryButton.vue'; +import DialogModal from '@/Components/DialogModal.vue'; +import { ref, watch } from 'vue'; +import type { ProjectMember, UpdateProjectMemberBody } from '@/utils/api'; +import PrimaryButton from '@/Components/PrimaryButton.vue'; +import { useFocus } from '@vueuse/core'; +import { useProjectMembersStore } from '@/utils/useProjectMembers'; +import BillableRateInput from '@/Components/Common/BillableRateInput.vue'; +import { UserIcon } from '@heroicons/vue/24/solid'; +const { updateProjectMember } = useProjectMembersStore(); + +const show = defineModel('show', { default: false }); +const saving = ref(false); + +const props = defineProps<{ + projectMember: ProjectMember; + name?: string; +}>(); + +const projectMemberBody = ref({ + billable_rate: props.projectMember.billable_rate, +}); + +async function submit() { + await updateProjectMember(props.projectMember.id, projectMemberBody.value); + show.value = false; + projectMemberBody.value = { + billable_rate: null, + }; +} + +watch( + () => show.value, + (value) => { + if (value) { + projectMemberBody.value = { + billable_rate: props.projectMember.billable_rate, + }; + } + } +); + +const projectNameInput = ref(null); + +useFocus(projectNameInput, { initialValue: true }); + + + + + diff --git a/resources/js/Components/Common/ProjectMember/ProjectMemberMoreOptionsDropdown.vue b/resources/js/Components/Common/ProjectMember/ProjectMemberMoreOptionsDropdown.vue index 109afb20..86216c81 100644 --- a/resources/js/Components/Common/ProjectMember/ProjectMemberMoreOptionsDropdown.vue +++ b/resources/js/Components/Common/ProjectMember/ProjectMemberMoreOptionsDropdown.vue @@ -1,12 +1,13 @@ diff --git a/resources/js/utils/api.ts b/resources/js/utils/api.ts index 94fae14a..d24a332f 100644 --- a/resources/js/utils/api.ts +++ b/resources/js/utils/api.ts @@ -54,6 +54,11 @@ export type CreateProjectMemberBody = ZodiosBodyByAlias< 'createProjectMember' >; +export type UpdateProjectMemberBody = ZodiosBodyByAlias< + SolidTimeApi, + 'updateProjectMember' +>; + export type ProjectMember = ProjectMemberResponse['data'][0]; export type CreateTaskBody = ZodiosBodyByAlias; diff --git a/resources/js/utils/useProjectMembers.ts b/resources/js/utils/useProjectMembers.ts index 18b5f6e4..03e8ec19 100644 --- a/resources/js/utils/useProjectMembers.ts +++ b/resources/js/utils/useProjectMembers.ts @@ -5,6 +5,7 @@ import type { CreateProjectMemberBody, ProjectMember, ProjectMemberResponse, + UpdateProjectMemberBody, } from '@/utils/api'; import { getCurrentOrganizationId } from '@/utils/useUser'; import { useNotificationsStore } from '@/utils/notification'; @@ -51,6 +52,27 @@ export const useProjectMembersStore = defineStore('project-members', () => { } } + async function updateProjectMember( + projectMemberId: string, + projectMemberBody: UpdateProjectMemberBody + ) { + const organization = getCurrentOrganizationId(); + if (organization) { + const response = await handleApiRequestNotifications( + () => + api.updateProjectMember(projectMemberBody, { + params: { + organization: organization, + projectMember: projectMemberId, + }, + }), + 'Project member updated successfully', + 'Failed to update project member' + ); + await fetchProjectMembers(response.data.project_id); + } + } + async function deleteProjectMember( projectId: string, projectMemberId: string @@ -84,5 +106,6 @@ export const useProjectMembersStore = defineStore('project-members', () => { fetchProjectMembers, createProjectMember, deleteProjectMember, + updateProjectMember, }; });