chore: perauset customer project
This commit is contained in:
208
apps/app/src/components/task-actions.tsx
Normal file
208
apps/app/src/components/task-actions.tsx
Normal file
@@ -0,0 +1,208 @@
|
||||
import { useState } from 'react'
|
||||
import { Button, Group, Modal, Textarea } from '@pikku/mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import { m } from '@/i18n/messages'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { usePikkuMutation } from '@perauset/functions-sdk/pikku/api.gen'
|
||||
|
||||
interface TaskActionsProps {
|
||||
taskId: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export function TaskActions({ taskId, status }: TaskActionsProps) {
|
||||
const queryClient = useQueryClient()
|
||||
const [blockOpened, { open: openBlock, close: closeBlock }] = useDisclosure()
|
||||
const [blockReason, setBlockReason] = useState('')
|
||||
const [completeOpened, { open: openComplete, close: closeComplete }] =
|
||||
useDisclosure()
|
||||
const [completeNotes, setCompleteNotes] = useState('')
|
||||
|
||||
// Tasks appear under several listing queries (listTasks, listMyTasks, …);
|
||||
// invalidate any task-related query after a mutation.
|
||||
const invalidateTasks = () => {
|
||||
queryClient.invalidateQueries({
|
||||
predicate: (q) =>
|
||||
typeof q.queryKey[0] === 'string' &&
|
||||
(q.queryKey[0] as string).toLowerCase().includes('task'),
|
||||
})
|
||||
}
|
||||
|
||||
const onError = (err: Error) => {
|
||||
notifications.show({
|
||||
title: m.common_error(),
|
||||
message: err.message ?? 'Something went wrong',
|
||||
color: 'red',
|
||||
})
|
||||
}
|
||||
|
||||
const claimMutation = usePikkuMutation('claimTask', {
|
||||
onSuccess: () => {
|
||||
notifications.show({
|
||||
title: m.common_success(),
|
||||
message: m.tasks_claimed(),
|
||||
color: 'teal',
|
||||
})
|
||||
invalidateTasks()
|
||||
},
|
||||
onError,
|
||||
})
|
||||
|
||||
const startMutation = usePikkuMutation('startTask', {
|
||||
onSuccess: () => {
|
||||
notifications.show({
|
||||
title: m.common_success(),
|
||||
message: m.tasks_started(),
|
||||
color: 'teal',
|
||||
})
|
||||
invalidateTasks()
|
||||
},
|
||||
onError,
|
||||
})
|
||||
|
||||
const completeMutation = usePikkuMutation('completeTask', {
|
||||
onSuccess: () => {
|
||||
notifications.show({
|
||||
title: m.common_success(),
|
||||
message: m.tasks_completed(),
|
||||
color: 'teal',
|
||||
})
|
||||
closeComplete()
|
||||
setCompleteNotes('')
|
||||
invalidateTasks()
|
||||
},
|
||||
onError,
|
||||
})
|
||||
|
||||
const blockMutation = usePikkuMutation('markTaskBlocked', {
|
||||
onSuccess: () => {
|
||||
notifications.show({
|
||||
title: m.common_success(),
|
||||
message: m.tasks_blocked(),
|
||||
color: 'teal',
|
||||
})
|
||||
closeBlock()
|
||||
setBlockReason('')
|
||||
invalidateTasks()
|
||||
},
|
||||
onError,
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Group gap="xs" wrap="nowrap">
|
||||
{status === 'open' && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="filled"
|
||||
color="teal"
|
||||
loading={claimMutation.isPending}
|
||||
onClick={() => claimMutation.mutate({ taskId })}
|
||||
>
|
||||
{m.tasks_claim()}
|
||||
</Button>
|
||||
)}
|
||||
{status === 'assigned' && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="filled"
|
||||
color="blue"
|
||||
loading={startMutation.isPending}
|
||||
onClick={() => startMutation.mutate({ taskId })}
|
||||
>
|
||||
{m.tasks_start()}
|
||||
</Button>
|
||||
)}
|
||||
{status === 'in_progress' && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="filled"
|
||||
color="green"
|
||||
loading={completeMutation.isPending}
|
||||
onClick={openComplete}
|
||||
>
|
||||
{m.tasks_complete()}
|
||||
</Button>
|
||||
)}
|
||||
{(status === 'open' ||
|
||||
status === 'assigned' ||
|
||||
status === 'in_progress') && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="light"
|
||||
color="red"
|
||||
loading={blockMutation.isPending}
|
||||
onClick={openBlock}
|
||||
>
|
||||
{m.tasks_block()}
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
<Modal
|
||||
opened={blockOpened}
|
||||
onClose={closeBlock}
|
||||
title={m.tasks_block_title()}
|
||||
centered
|
||||
>
|
||||
<Textarea
|
||||
label={m.tasks_reason()}
|
||||
placeholder={m.tasks_reason_placeholder()}
|
||||
value={blockReason}
|
||||
onChange={(e) => setBlockReason(e.currentTarget.value)}
|
||||
minRows={3}
|
||||
mb="md"
|
||||
/>
|
||||
<Group justify="flex-end">
|
||||
<Button variant="default" onClick={closeBlock}>
|
||||
{m.common_cancel()}
|
||||
</Button>
|
||||
<Button
|
||||
color="red"
|
||||
loading={blockMutation.isPending}
|
||||
onClick={() => {
|
||||
if (blockReason.trim())
|
||||
blockMutation.mutate({ taskId, reason: blockReason })
|
||||
}}
|
||||
>
|
||||
{m.tasks_mark_blocked()}
|
||||
</Button>
|
||||
</Group>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
opened={completeOpened}
|
||||
onClose={closeComplete}
|
||||
title={m.tasks_complete_title()}
|
||||
centered
|
||||
>
|
||||
<Textarea
|
||||
label={m.tasks_notes_optional()}
|
||||
placeholder={m.tasks_notes_placeholder()}
|
||||
value={completeNotes}
|
||||
onChange={(e) => setCompleteNotes(e.currentTarget.value)}
|
||||
minRows={3}
|
||||
mb="md"
|
||||
/>
|
||||
<Group justify="flex-end">
|
||||
<Button variant="default" onClick={closeComplete}>
|
||||
{m.common_cancel()}
|
||||
</Button>
|
||||
<Button
|
||||
color="green"
|
||||
loading={completeMutation.isPending}
|
||||
onClick={() =>
|
||||
completeMutation.mutate({
|
||||
taskId,
|
||||
...(completeNotes ? { notes: completeNotes } : {}),
|
||||
})
|
||||
}
|
||||
>
|
||||
{m.tasks_complete()}
|
||||
</Button>
|
||||
</Group>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user