Files
spsays-training/components/social/post-actions-footer.tsx
T
2026-05-31 00:26:05 +05:30

121 lines
3.5 KiB
TypeScript

"use client";
/**
* PostActionsFooter — the icon-button row at the bottom of a post card.
*
* Left cluster: Like · Comment · Reshare
* Right cluster: Save to Collection (folder-plus)
*
* Like / Comment / Reshare are placeholders for now — they fire a
* "coming soon" toast on click. Save to Collection mounts the existing
* CollectionsDrawer in `existingPostId` mode so the post is attached
* directly without creating a duplicate.
*
* Auth gating is handled per-action via `useAuthGate` — anonymous users
* see the in-place auth modal before the underlying action runs.
*/
import { useState } from "react";
import {
HiOutlineArrowPath,
HiOutlineChatBubbleOvalLeft,
HiOutlineFolderPlus,
HiOutlineHeart,
} from "react-icons/hi2";
import { toast } from "sonner";
import { cn } from "@/lib/utils";
import { useAuthGate } from "@/components/auth/auth-gate";
import { useMediaQuery } from "@/components/selection-toolbar/shared";
import { CollectionsDrawer } from "@/components/selection-toolbar/collections-drawer";
// All four icons come from the Heroicons v2 outline family (react-icons
// `hi2` namespace), so they share one design language — uniform stroke
// weight, matching corner radius, matching optical sizing. No more
// Lucide cross-icon visual drift.
const ICON_CLASS = "size-[1.375rem]";
export function PostActionsFooter({ postID }: { postID: string }) {
const { requireAuth } = useAuthGate();
const isMobile = useMediaQuery("(max-width: 767px)");
const [collectionsOpen, setCollectionsOpen] = useState(false);
async function withAuth(fn: () => void | Promise<void>) {
if (!(await requireAuth())) return;
await fn();
}
return (
<>
<div className="flex items-center justify-between px-2">
<div className="flex items-center gap-1">
<ActionButton
label="Like"
onClick={() =>
withAuth(() => {
toast("Likes are coming soon", { duration: 2000 });
})
}
icon={<HiOutlineHeart className={ICON_CLASS} />}
/>
<ActionButton
label="Comment"
onClick={() =>
withAuth(() => {
toast("Comments are coming soon", { duration: 2000 });
})
}
icon={<HiOutlineChatBubbleOvalLeft className={ICON_CLASS} />}
/>
<ActionButton
label="Reshare"
onClick={() =>
withAuth(() => {
toast("Resharing is coming soon", { duration: 2000 });
})
}
icon={<HiOutlineArrowPath className={ICON_CLASS} />}
/>
</div>
<ActionButton
label="Save to collection"
onClick={() => withAuth(() => setCollectionsOpen(true))}
icon={<HiOutlineFolderPlus className={ICON_CLASS} />}
/>
</div>
<CollectionsDrawer
open={collectionsOpen}
onClose={() => setCollectionsOpen(false)}
isMobile={isMobile}
existingPostId={postID}
/>
</>
);
}
function ActionButton({
label,
onClick,
icon,
}: {
label: string;
onClick: () => void;
icon: React.ReactNode;
}) {
return (
<button
type="button"
onClick={onClick}
aria-label={label}
title={label}
className={cn(
"size-10 inline-flex items-center justify-center rounded-full",
"text-muted-foreground hover:text-foreground hover:bg-muted",
"transition-colors",
)}
>
{icon}
</button>
);
}