mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-04 20:05:50 +00:00
244 lines
9.0 KiB
TypeScript
244 lines
9.0 KiB
TypeScript
import * as React from "react";
|
|
import { useState, useRef, useEffect } from "react";
|
|
import { useThemeHooks } from "@redocly/theme/core/hooks";
|
|
import { Link } from "@redocly/theme/components/Link/Link";
|
|
import moment from "moment";
|
|
|
|
export const frontmatter = {
|
|
seo: {
|
|
title: "XRP Ledger Community Blog",
|
|
description: "Browse the XRP Ledger Community Blog.",
|
|
},
|
|
};
|
|
|
|
const categories = {
|
|
general: "General",
|
|
release_notes: "Release Notes",
|
|
advisories: "Advisories",
|
|
amendments: "Amendments",
|
|
case_study: "Case Study",
|
|
development: "Development",
|
|
developer_reflections: "Developer Reflections",
|
|
features: "Features",
|
|
security: "Security",
|
|
};
|
|
|
|
export default function Index() {
|
|
const { useTranslate, usePageSharedData } = useThemeHooks();
|
|
const { translate } = useTranslate();
|
|
const { blogPosts } = usePageSharedData<any>("blog-posts");
|
|
|
|
const heroPost = blogPosts[0];
|
|
const otherPosts = blogPosts.slice(1);
|
|
const defaultSelectedCategories = new Set(Object.keys(categories));
|
|
|
|
const [selectedCategories, setSelectedCategories] = useState(
|
|
defaultSelectedCategories
|
|
);
|
|
|
|
const [cards, setCards] = useState(otherPosts);
|
|
|
|
const toggleCategory = (category) => {
|
|
const newSelectedCategories = new Set(selectedCategories);
|
|
if (newSelectedCategories.has(category)) {
|
|
newSelectedCategories.delete(category);
|
|
} else {
|
|
newSelectedCategories.add(category);
|
|
}
|
|
setSelectedCategories(newSelectedCategories);
|
|
};
|
|
|
|
const filteredCards = cards.filter((card) =>
|
|
selectedCategories.has(card.category_id)
|
|
);
|
|
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
<div className="landing dev-blog">
|
|
<div className="justify-content-center align-items-lg-center">
|
|
<div className="position-relative d-none-sm">
|
|
<img
|
|
alt="background purple waves"
|
|
src={require("../static/img/backgrounds/home-purple.svg")}
|
|
id="blog-purple"
|
|
/>
|
|
</div>
|
|
<section className="py-lg-5 text-center mt-lg-5">
|
|
<div className="mx-auto text-center col-lg-5">
|
|
<div className="d-flex flex-column">
|
|
<h6 className="eyebrow mb-3">{translate("XRPL Community")}</h6>
|
|
<h1 className="mb-3">{translate("XRPL Blog")}</h1>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Banner */}
|
|
<section className="container-new">
|
|
<div className="row justify-content-center align-items-lg-center">
|
|
{/* Banner Image */}
|
|
<div className="image-container">
|
|
<img
|
|
alt="blog hero"
|
|
src={require("../static/img/blog/blog-hero.svg")}
|
|
className="w-100"
|
|
/>
|
|
</div>
|
|
{/* Text */}
|
|
<div className="col">
|
|
<div className="text-bg">
|
|
<h4 className="mb-3 eyebrow text-uppercase font-weight-light">
|
|
<span className="hero-post-date pb-2">
|
|
{moment(heroPost.date).format(translate("blog.banner.date.part1","MMM"))}
|
|
</span>
|
|
{translate("blog.banner.date.part2", " ")}
|
|
{moment(heroPost.date).format(translate("blog.banner.date.part3","DD YYYY"))}
|
|
</h4>
|
|
<div className="pb-8">
|
|
<div
|
|
className={`d-inline-block mb-2 label blog-category-${heroPost.category_id}`}
|
|
>
|
|
{translate(`${heroPost.category}`)}
|
|
</div>
|
|
</div>
|
|
<h4 className="mb-8 h2-sm font-weight-bold">
|
|
<Link to={`/blog/${heroPost.link}`}>
|
|
{translate(`${heroPost.title}`)}
|
|
</Link>
|
|
</h4>
|
|
<p className="mb-4">{translate(`${heroPost.description}`)}</p>
|
|
<div className="d-lg-block">
|
|
<Link
|
|
className="btn btn-primary btn-arrow"
|
|
to={`/blog/${heroPost.link}`}
|
|
>
|
|
{translate("Read More")}
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Other Blog Posts*/}
|
|
<section className="container-new py-26">
|
|
<div className="row w-100 mx-auto px-2">
|
|
<div className="col-lg-4 m-0 p-0 mt-2">
|
|
{/* Filters Desktop*/}
|
|
<div className="p-3 category_sidebar d-none d-lg-block">
|
|
<p className="mb-2 category-header">{translate("Filter by Category:")}</p>
|
|
<div className="d-flex flex-column p-3">
|
|
{Object.keys(categories).map((item) => (
|
|
<div key={item} className="category-checkbox pb-2">
|
|
<input
|
|
className={`blog-filter input_${item}`}
|
|
type="checkbox"
|
|
name="categories"
|
|
id={`input_desktop_${item}`}
|
|
defaultValue={`${item}`}
|
|
onChange={() => toggleCategory(item)}
|
|
defaultChecked
|
|
/>
|
|
<label
|
|
className="font-weight-bold"
|
|
htmlFor={`input_desktop_${item}`}
|
|
>
|
|
{translate(categories[item])}
|
|
</label>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
{/* End Desktop Filters */}
|
|
{/* Filters Mobile */}
|
|
<div className="col d-flex flex-column p-0 d-lg-none mb-4">
|
|
<p className="mb-2 category-header">{translate("Filter by:")}</p>
|
|
<div className="dropdown">
|
|
<button
|
|
className="dropdown-btn"
|
|
onClick={() => setOpen((open) => !open)}
|
|
>
|
|
{translate("Category")}
|
|
<img alt="dropdown arrow" />
|
|
</button>
|
|
{open && (
|
|
<div
|
|
className="dropdown-content d-flex flex-column mt-2"
|
|
aria-labelledby="blog-dropdown-button"
|
|
>
|
|
{Object.keys(categories).map((item, i) => (
|
|
<div key={item + i} className="category-checkbox pl-2 pb-2">
|
|
<input
|
|
className={`blog-filter input_${item}`}
|
|
type="checkbox"
|
|
name="categories"
|
|
id={`input_mobile_${item}`}
|
|
defaultValue={`${item}`}
|
|
onChange={() => toggleCategory(item)}
|
|
defaultChecked
|
|
/>
|
|
<label
|
|
className="font-weight-bold"
|
|
htmlFor={`input_mobile_${item}`}
|
|
>
|
|
{translate(categories[item])}
|
|
</label>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
{/* End Filters Mobile */}
|
|
</div>
|
|
{/* Cards */}
|
|
<div className="row col row-cols-lg-2 m-0 p-0">
|
|
{filteredCards.map((card, i) => (
|
|
<div
|
|
key={card.title + i}
|
|
className={`${card.category_id} pb-5 px-lg-4`}
|
|
id={card.title + i}
|
|
>
|
|
<div className="mb-4 category-list">
|
|
<img
|
|
alt=""
|
|
className="mb-4"
|
|
/>
|
|
<div
|
|
className={`d-block label blog-category-${card.category_id}`}
|
|
>
|
|
{translate(card.category)}
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<p className="mb-0 card-date">
|
|
{moment(card.date).format(translate("blog.card.date","MMM DD, YYYY"))}
|
|
{ card.author ? ` by ${card.author}` : ""}
|
|
</p>
|
|
<h5 className="mb-2-sm h3-sm">
|
|
<Link to={`/blog/${card.link}`}>
|
|
{translate(card.title)}
|
|
</Link>
|
|
</h5>
|
|
</div>
|
|
<div className="d-lg-block">
|
|
<p className="line-clamp">{translate(card.description)}</p>
|
|
</div>
|
|
<div className="d-lg-block">
|
|
<Link
|
|
className="btn btn-primary btn-arrow"
|
|
to={`/blog/${card.link}`}
|
|
>
|
|
{translate("Read More")}
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|