"use client";
import Link from "next/link";
import Image from "next/image";
import {
ArrowRight,
Clock,
Calendar,
MessageCircle,
Share2,
CheckCircle2,
ExternalLink,
ChevronRight,
Building2,
ShieldCheck,
Compass,
Quote,
HelpCircle,
} from "lucide-react";
import Breadcrumbs from "@/components/ui/breadcrumbs";
import TableOfContents, { TocItem } from "@/components/ui/table-of-contents";
import CalloutBox from "@/components/ui/callout-box";
import PortableTextRenderer from "@/components/portable-text-renderer";
import FounderBioSection from "@/components/sections/founder-bio-section";
import LuxuryCTABanner from "@/components/sections/luxury-cta-banner";
import { getWhatsAppUrl } from "@/lib/whatsapp";
import { WhatsAppIcon } from "@/components/ui/whatsapp-icon";
import { useState, useMemo } from "react";
import { toast } from "sonner";
import type { PortableTextProps } from "@portabletext/react";
export interface ArticleData {
title: string;
slug: string;
excerpt?: string;
tag?: string;
readTime?: string;
publishedAt?: string;
coverImage?: string;
author?: {
name: string;
role?: string;
avatar?: string;
};
toc?: TocItem[];
body?: PortableTextProps["value"] | null;
fallbackContent?: {
introduction?: string[];
sections: {
id: string;
title: string;
level?: number;
paragraphs?: string[];
callout?: {
title: string;
text: string;
};
bulletPoints?: string[];
scenarios?: {
title: string;
upside: string;
downside: string;
}[];
}[];
};
}
export interface BlogArticleViewProps {
article: ArticleData;
relatedArticles?: {
title: string;
slug: string;
excerpt: string;
tag: string;
}[];
}
export default function BlogArticleView({
article,
relatedArticles = [],
}: BlogArticleViewProps) {
const [copied, setCopied] = useState(false);
const handleCopyLink = () => {
if (typeof window !== "undefined") {
navigator.clipboard.writeText(window.location.href);
setCopied(true);
toast.success("Article link copied to clipboard");
setTimeout(() => setCopied(false), 2000);
}
};
const shareText = `Check out this wedding guide: ${article.title}`;
const currentUrl = typeof window !== "undefined" ? window.location.href : "";
const breadcrumbLinks = [
{ label: "Home", href: "/" },
{ label: "Wedding Guides", href: "/blog" },
{ label: article.title, href: "#" },
];
// Compute Table of Contents from Portable Text headings or fallbackContent
const tocItems: TocItem[] = useMemo(() => {
if (article.toc && article.toc.length > 0) return article.toc;
if (Array.isArray(article.body)) {
const headings: TocItem[] = [];
for (const block of article.body) {
if (
block._type === "block" &&
(block.style === "h2" || block.style === "h3")
) {
const text =
block.children?.map((c: any) => c.text).join("") || "";
if (text) {
const cleanTitle = text.replace(/[*#→>_]/g, "").trim();
const id = cleanTitle
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-|-$/g, "");
if (cleanTitle && id) {
headings.push({
id,
title: cleanTitle,
level: block.style === "h2" ? 2 : 3,
});
}
}
}
}
if (headings.length > 0) return headings;
}
return (
article.fallbackContent?.sections.map((s) => ({
id: s.id,
title: s.title,
level: s.level || 2,
})) || []
);
}, [article.toc, article.body, article.fallbackContent]);
return (
{/* 1. ARTICLE HEADER HERO */}
{/* Meta Ribbon */}
{article.tag || "Wedding Guide"}
{article.readTime || "10 min read"}
{article.publishedAt && (
{article.publishedAt}
)}
{/* Main Title in Philosopher */}
{article.title}
{/* Excerpt / Lead */}
{article.excerpt && (
{article.excerpt}
)}
{/* Author Byline & Social Sharing */}
{/* Author */}
{article.author?.name || "Nhi Võ"}
{article.author?.role || "Founder & Senior Destination Consultant"}
{/* Share Actions */}
{/* 2. MAIN EDITORIAL CONTENT + STICKY SIDEBAR */}
{/* MAIN ARTICLE BODY (8 Columns) */}
{/* Featured Cover Image if available */}
{article.coverImage && (
)}
{/* MOBILE TABLE OF CONTENTS */}
{tocItems.length > 0 && (
)}
{/* SANITY PORTABLE TEXT CONTENT (If Available) */}
{article.body ? (
) : (
/* STRUCTURED FALLBACK CONTENT */
{/* Introduction Paragraphs */}
{article.fallbackContent?.introduction && (
{article.fallbackContent.introduction.map((p, idx) => (
{p}
))}
)}
{/* Fallback Sections with Headings */}
{article.fallbackContent?.sections.map((sec) => (
{sec.title}
{/* Paragraphs */}
{sec.paragraphs &&
sec.paragraphs.map((para, pIdx) => (
{para}
))}
{/* Consultant Callout Box */}
{sec.callout && (
{sec.callout.text}
)}
{/* Bullet points */}
{sec.bulletPoints && (
{sec.bulletPoints.map((bp, bpIdx) => (
-
{bp}
))}
)}
{/* Scenarios Comparison */}
{sec.scenarios && (
{sec.scenarios.map((scen, sIdx) => (
{scen.title}
Advantage: {scen.upside}
Trade-off: {scen.downside}
))}
)}
))}
)}
{/* 3. AUTHOR BIO CARD (Founder Credibility) */}
{/* STICKY SIDEBAR (4 Columns on Desktop) */}
{/* 4. RELATED WEDDING GUIDES */}
{relatedArticles && relatedArticles.length > 0 && (
Continue Reading
Related Wedding Guides
View All Guides
{relatedArticles.map((item) => (
{item.tag}
Vietnam Wedding Guide
{item.title}
{item.excerpt}
))}
)}
{/* 5. BOTTOM LUXURY CTA BANNER */}
);
}