From 6afa7bd1224552392e4c0e33bdd0637a3bd09504 Mon Sep 17 00:00:00 2001 From: arc-alex Date: Sun, 24 Aug 2025 13:42:13 -0700 Subject: [PATCH] make event hit group target duration --- apps/client/src/common/hooks/useEntryAction.ts | 15 +++++++++++++++ .../rundown/rundown-event/RundownEvent.tsx | 15 +++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/client/src/common/hooks/useEntryAction.ts b/apps/client/src/common/hooks/useEntryAction.ts index c47e65226..d7ec25a3f 100644 --- a/apps/client/src/common/hooks/useEntryAction.ts +++ b/apps/client/src/common/hooks/useEntryAction.ts @@ -365,6 +365,19 @@ function useEntryActionsForRundown(scopedRundownId: string | undefined) { [getCurrentRundownData, updateEntryMutation], ); + const matchGroupDuration = useCallback(async (eventId: EntryId, groupId: EntryId) => { + const rundown = queryClient.getQueryData(RUNDOWN); + if (!rundown) return; + const group = rundown.entries[groupId]; + if (!group || !isOntimeGroup(group) || group.targetDuration === null) return; + const event = rundown.entries[eventId]; + if (!event || !isOntimeEvent(event)) return; + const durationDiff = group.targetDuration - group.duration; + const newDuration = event.duration + durationDiff; + if (newDuration < 0) return; + updateTimer(eventId, 'duration', String(newDuration / MILLIS_PER_SECOND) + 's', false); + }, []); + /** * Updates time of existing event * @param eventId {EntryId} - id of the event @@ -1003,6 +1016,7 @@ function useEntryActionsForRundown(scopedRundownId: string | undefined) { swapEvents, updateEntry, updateTimer, + matchGroupDuration, }), [ addEntry, @@ -1020,6 +1034,7 @@ function useEntryActionsForRundown(scopedRundownId: string | undefined) { swapEvents, updateEntry, updateTimer, + matchGroupDuration, ], ); } diff --git a/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx b/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx index aea2c4ef2..e530505c6 100644 --- a/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx +++ b/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx @@ -13,7 +13,7 @@ import { IoTrash, IoUnlink, } from 'react-icons/io5'; -import { TbFlagFilled, TbListNumbers } from 'react-icons/tb'; +import { TbClockPin, TbFlagFilled, TbListNumbers } from 'react-icons/tb'; import { useEntryActionsContext } from '../../../common/context/EntryActionsContext'; import { useContextMenu } from '../../../common/hooks/useContextMenu'; @@ -102,7 +102,8 @@ export default function RundownEvent({ const clearSelectedEventId = useEventIdSwapping((state) => state.clearSelectedEventId); const openRenumberDialog = useRenumberCuesDialogStore((state) => state.onOpen); - const { updateEntry, batchUpdateEvents, clone, deleteEntry, groupEntries, swapEvents } = useEntryActionsContext(); + const { updateEntry, batchUpdateEvents, clone, deleteEntry, groupEntries, swapEvents, matchGroupDuration } = + useEntryActionsContext(); const isSelected = useEventSelection((state) => state.selectedEvents.has(eventId)); const unselect = useEventSelection((state) => state.unselect); @@ -172,6 +173,16 @@ export default function RundownEvent({ updateEntry({ id: eventId, flag: !flag }); }, }, + { + type: 'item', + label: 'Match Group Target Duration', + icon: TbClockPin, + onClick: () => { + if (!parent) return; + matchGroupDuration(eventId, parent); + }, + disabled: !parent, + }, { type: 'divider' }, { type: 'item',