Skip to content

Commit

Permalink
状態変更メニュー
Browse files Browse the repository at this point in the history
  • Loading branch information
mehm8128 committed Apr 29, 2024
1 parent ab2d8af commit e832668
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/components/modal/StatusChangeModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const { request } = storeToRefs(requestDetailStore)
const comment = ref('')
async function putStatus(nextStatus: RequestStatus, comment: string) {
const putStatus = async (nextStatus: RequestStatus, comment: string) => {
try {
if (request.value === undefined) {
throw new Error('request is undefined')
Expand Down
18 changes: 17 additions & 1 deletion src/components/requestDetail/RequestHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import type { RequestDetail } from '/@/features/request/model'
import SimpleButton from '/@/components/shared/SimpleButton.vue'
import InputText from '/@/components/shared/InputText.vue'
import { editRequestUsecase } from '/@/features/request/usecase'
import { useStatusOptions } from '/@/features/requestStatus/composables'
import FloatingMenu from '/@/components/shared/FloatingMenu.vue'
const props = defineProps<{
request: RequestDetail
Expand All @@ -28,6 +30,9 @@ const handleUpdateTitle = async () => {
})
isEditMode.value = false
}
const showMenu = ref(false)
const { statusOptions } = useStatusOptions(props.request)
</script>

<template>
Expand All @@ -43,7 +48,18 @@ const handleUpdateTitle = async () => {
</SimpleButton>
</div>
<div class="flex items-center justify-between">
<StatusChip has-text :status="request.status" />
<div class="relative">
<StatusChip
has-text
:status="request.status"
@click.stop="showMenu = true" />
<FloatingMenu
v-if="showMenu"
class="absolute top-12 left-0 w-40"
:current-value="request.status"
:options="statusOptions"
@close-menu="showMenu = false" />
</div>
<div class="text-3xl font-bold">{{ totalAmount }}円</div>
</div>
</div>
Expand Down
62 changes: 62 additions & 0 deletions src/components/shared/FloatingMenu.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script setup lang="ts">
import type { RequestStatus } from '/@/features/requestStatus/model'
import { onMounted, onUnmounted, ref } from 'vue'
import { useModal } from '/@/components/modal/composables/useModal'
import ModalWrapper from '/@/components/modal/ModalWrapper.vue'
import StatusChangeModal from '/@/components/modal/StatusChangeModal.vue'
defineProps<{
options: { key: string; value: RequestStatus }[]
currentValue: RequestStatus
}>()
const emit = defineEmits<{
(e: 'closeMenu'): void
}>()
const handleSelectOption = (status: RequestStatus) => {
// TODO: emitして一般化
nextStatus.value = status
openModal()
}
const containerRef = ref<HTMLDivElement | null>(null)
const nextStatus = ref<RequestStatus>()
const { shouldShowModal, openModal, closeModal } = useModal()
const callback = () => {
emit('closeMenu')
}
onMounted(() => {
window.addEventListener('click', callback)
})
onUnmounted(() => {
window.removeEventListener('click', callback)
})
</script>

<template>
<div
ref="containerRef"
class="bg-white rounded-md p-2 flex flex-col gap-2 border"
@click.stop="">
<div
v-for="option in options"
:key="option.value"
class="hover:bg-gray-200 rounded p-1">
<button
class="w-full h-full text-left"
@click="handleSelectOption(option.value)">
{{ option.key }}
</button>
</div>
<ModalWrapper v-if="shouldShowModal" @close-modal="closeModal">
<StatusChangeModal
v-if="nextStatus"
:next-status="nextStatus"
@close-modal="closeModal" />
</ModalWrapper>
</div>
</template>
40 changes: 40 additions & 0 deletions src/features/requestStatus/composables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { RequestStatus } from '/@/features/requestStatus/model'

import { storeToRefs } from 'pinia'
import { useRequestDetailStore } from '/@/stores/requestDetail'
import { useUserStore } from '/@/stores/user'
import type { RequestDetail } from '/@/features/request/model'
import { computed } from 'vue'

export const useStatusOptions = (request: RequestDetail) => {
const userStore = useUserStore()
const requestDetailStore = useRequestDetailStore()
const { isRequestCreator } = requestDetailStore

const { me, isAdmin } = storeToRefs(userStore)
const hasAuthority = isRequestCreator(me.value)

const showToSubmitted =
(hasAuthority && request.status === 'fix_required') ||
(isAdmin.value &&
(request.status === 'fix_required' || request.status === 'accepted'))
const showToRequired = isAdmin.value && request.status === 'submitted'
const showToAccepted = isAdmin.value && request.status === 'submitted'
const showToRejected = isAdmin.value && request.status === 'submitted'

const statusOptions = computed<
{ value: RequestStatus; key: string; show: boolean }[]
>(() => [
{ value: 'submitted', key: '承認待ちにする', show: showToSubmitted }, //TODO: 表示するべきか確認
{ value: 'rejected', key: '却下する', show: showToRejected },
{ value: 'fix_required', key: '要修正にする', show: showToRequired },
{ value: 'accepted', key: '承認する', show: showToAccepted }
])
const showStatusOptions = computed(() =>
statusOptions.value
.filter(option => option.show)
.map(option => ({ value: option.value, key: option.key }))
)

return { statusOptions: showStatusOptions.value }
}

0 comments on commit e832668

Please sign in to comment.