| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- 'use client'
- import type { ReactNode } from 'react'
- import { useRouter } from 'next/navigation'
- import { useTranslations } from 'next-intl'
- import { toast } from 'sonner'
- import { Check, ExternalLink, Pencil, Trash2, Undo2, Wrench } from 'lucide-react'
- import {
- ContextMenu,
- ContextMenuContent,
- ContextMenuItem,
- ContextMenuLabel,
- ContextMenuSeparator,
- ContextMenuTrigger,
- } from '@/components/ui/context-menu'
- import { useConfirm } from '@/components/confirm-dialog'
- import { deleteReminder, toggleReminder } from '@/features/vehicles/Actions/reminderActions'
- import { deleteScheduledMessage } from '@/features/scheduled-messages/Actions/scheduledMessageActions'
- import { getEventLink } from './calendar-utils'
- import { deleteAppointment } from '../Actions/deleteAppointment'
- import { isEditableBooking, useEventPeek } from './EventPeek'
- import type { CalendarEvent } from '../Actions/calendarActions'
- /**
- * Right-click on an event: open it, and for the things the calendar owns
- * outright, act on them here. A reminder can be ticked off or deleted; a
- * scheduled message can be deleted before it goes out. Work orders and
- * quotes carry money and paper, so they are only opened from here.
- */
- export function EventContextMenu({
- event,
- children,
- }: {
- event: CalendarEvent
- children: ReactNode
- }) {
- const t = useTranslations('calendar.eventMenu')
- const router = useRouter()
- const confirm = useConfirm()
- const { refresh, editBooking } = useEventPeek()
- const open = () => {
- if (event.type === 'external') {
- if (event.externalUrl) window.open(event.externalUrl, '_blank', 'noopener')
- return
- }
- router.push(getEventLink(event))
- }
- const run = async (
- action: () => Promise<{ success: boolean; error?: string }>,
- doneMessage: string
- ) => {
- const result = await action()
- if (result.success) {
- toast.success(doneMessage)
- refresh()
- } else {
- toast.error(result.error || t('failed'))
- }
- }
- const removeReminder = async () => {
- const ok = await confirm({
- description: t('deleteReminderConfirm', { title: event.title }),
- destructive: true,
- })
- if (ok) await run(() => deleteReminder(event.id), t('deleted'))
- }
- const removeMessage = async () => {
- const ok = await confirm({
- description: t('deleteMessageConfirm', { title: event.title }),
- destructive: true,
- })
- if (ok) await run(() => deleteScheduledMessage(event.id), t('deleted'))
- }
- const removeAppointment = async () => {
- const ok = await confirm({
- description: t('deleteAppointmentConfirm', { title: event.title }),
- destructive: true,
- })
- if (ok) await run(() => deleteAppointment(event.id), t('deleted'))
- }
- const reminderDone = event.type === 'reminder' && event.status === 'completed'
- const canEdit = Boolean(editBooking) && isEditableBooking(event)
- return (
- <ContextMenu>
- <ContextMenuTrigger asChild>{children}</ContextMenuTrigger>
- <ContextMenuContent className="min-w-52">
- <ContextMenuLabel className="truncate text-xs font-normal text-muted-foreground">
- {event.title}
- </ContextMenuLabel>
- <ContextMenuSeparator />
- {canEdit && (
- <ContextMenuItem onClick={() => editBooking?.({ mode: 'edit', event })}>
- <Pencil className="mr-2 h-4 w-4" />
- {t('edit')}
- </ContextMenuItem>
- )}
- {event.type === 'appointment' ? (
- editBooking && (
- <>
- <ContextMenuItem onClick={() => editBooking({ mode: 'convert', event })}>
- <Wrench className="mr-2 h-4 w-4" />
- {t('makeWorkOrder')}
- </ContextMenuItem>
- <ContextMenuSeparator />
- <ContextMenuItem variant="destructive" onClick={removeAppointment}>
- <Trash2 className="mr-2 h-4 w-4" />
- {t('deleteAppointment')}
- </ContextMenuItem>
- </>
- )
- ) : (
- <ContextMenuItem onClick={open}>
- <ExternalLink className="mr-2 h-4 w-4" />
- {t('open')}
- </ContextMenuItem>
- )}
- {event.type === 'reminder' && (
- <>
- <ContextMenuItem onClick={() => run(() => toggleReminder(event.id), t('updated'))}>
- {reminderDone ? (
- <Undo2 className="mr-2 h-4 w-4" />
- ) : (
- <Check className="mr-2 h-4 w-4" />
- )}
- {reminderDone ? t('markNotDone') : t('markDone')}
- </ContextMenuItem>
- <ContextMenuSeparator />
- <ContextMenuItem variant="destructive" onClick={removeReminder}>
- <Trash2 className="mr-2 h-4 w-4" />
- {t('deleteReminder')}
- </ContextMenuItem>
- </>
- )}
- {event.type === 'message' && (
- <>
- <ContextMenuSeparator />
- <ContextMenuItem variant="destructive" onClick={removeMessage}>
- <Trash2 className="mr-2 h-4 w-4" />
- {t('deleteMessage')}
- </ContextMenuItem>
- </>
- )}
- </ContextMenuContent>
- </ContextMenu>
- )
- }
|