import { ActionIcon, Button, Group, Paper, Text, Tooltip, } from "@mantine/core"; import { IconClockHour4, IconTrash } from "@tabler/icons-react"; import { useState } from "react"; import { Trans, useTranslation } from "react-i18next"; import { useTimeAgo } from "@/hooks/use-time-ago.tsx"; import { usePageQuery } from "@/features/page/queries/page-query.ts"; import { useTreeMutation } from "@/features/page/tree/hooks/use-tree-mutation.ts"; import { useToggleTemporaryMutation, syncTemporaryExpiresInCache, } from "@/features/page-embed/queries/page-embed-query.ts"; import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts"; import { useSpaceAbility } from "@/features/space/permissions/use-space-ability.ts"; import { SpaceCaslAction, SpaceCaslSubject, } from "@/features/space/permissions/permissions.type.ts"; type TemporaryNoteBannerProps = { slugId: string; }; /** * Banner shown on an open temporary note ("structure or die"). Mirrors * DeletedPageBanner: it reads the page from the shared query cache and offers * the explicit rescue action — "Make permanent". Children ride along to trash * with the note, which is noted in the copy. */ export function TemporaryNoteBanner({ slugId }: TemporaryNoteBannerProps) { const { t } = useTranslation(); const { data: page } = usePageQuery({ pageId: slugId }); const { data: space } = useGetSpaceBySlugQuery(page?.space?.slug); const spaceAbility = useSpaceAbility(space?.membership?.permissions); const expiresTimeAgo = useTimeAgo(page?.temporaryExpiresAt); const toggleTemporary = useToggleTemporaryMutation(); // Reuse the exact soft-delete path the tree/header menus use: optimistic // tree removal, the "Page moved to trash" undo-toast, the deletedAt cache // stamp, and the redirect to space home (which unmounts this banner). const { handleDelete: trashPage } = useTreeMutation(page?.spaceId ?? ""); const [isDeleting, setIsDeleting] = useState(false); // Don't show on a note that is already in trash; the deleted-page banner // owns that state. if (!page?.temporaryExpiresAt || page?.deletedAt) return null; const canEdit = spaceAbility.can(SpaceCaslAction.Edit, SpaceCaslSubject.Page); const handleTrashNow = async () => { // No confirm modal by convention — the undo-toast is the safety net. setIsDeleting(true); try { await trashPage(page.id); } finally { setIsDeleting(false); } }; const handleMakePermanent = async () => { try { const res = await toggleTemporary.mutateAsync({ pageId: page.id, temporary: false, }); syncTemporaryExpiresInCache(page, res.temporaryExpiresAt); } catch { // mutation surfaces the error via notifications } }; return ( {/* A non-zero flex-basis lets the outer wrap="wrap" drop the buttons to their own row on narrow screens; flex:1 (basis 0) never wraps and instead crushes the text into a one-word-per-line ladder. */} {canEdit && ( <> {/* Desktop: full labeled buttons. */} {/* Mobile: icon-only actions so they never overflow the narrow row. */} )} ); }