"use client";
import { Container } from "@/components/container";
import { format } from "date-fns";
import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import FuzzySearch from "fuzzy-search";
import type { BlogEntry } from "./page";
function truncate(text: string, length: number) {
return text.length > length ? `${text.slice(0, length)}…` : text;
}
function SearchIcon({ className }: { className?: string }) {
return (
);
}
export function BlogWithSearchMagazine({ blogs }: { blogs: BlogEntry[] }) {
const featured = blogs[0];
if (!featured) {
return (
);
}
return (
);
}
function MagazineFeatured({ blog }: { blog: BlogEntry }) {
return (
{blog.image ? (

) : null}
Cover story
{blog.title}
{truncate(blog.description, 160)}
{blog.author}
·
);
}
function MagazineSearchGrid({
blogs: allBlogs,
featuredSlug,
}: {
blogs: BlogEntry[];
featuredSlug: string;
}) {
const [search, setSearch] = useState("");
const searcher = useMemo(
() =>
new FuzzySearch(allBlogs, ["title", "description"], {
caseSensitive: false,
}),
[allBlogs],
);
const [results, setResults] = useState(allBlogs);
useEffect(() => {
setResults(searcher.search(search));
}, [search, searcher]);
const gridItems = useMemo(() => {
if (search.trim()) {
return results;
}
return results.filter((b) => b.slug !== featuredSlug);
}, [results, search, featuredSlug]);
return (
);
}
function MagazineCard({ blog }: { blog: BlogEntry }) {
return (
{blog.image ? (

) : (
No image
)}
{blog.title}
{truncate(blog.description, 110)}
{blog.author}
);
}