feat(dimentorin): articles page integrated with API (list, filter, detail)
This commit is contained in:
@@ -1,14 +1,22 @@
|
||||
import { ReactElement, useRef, useState } from "react";
|
||||
import { ArticleCard } from "./_components/card/article";
|
||||
import { cn, For } from "@imphnen-frontend-service/utils";
|
||||
import { cn, For, Show } from "@imphnen-frontend-service/utils";
|
||||
import { Button } from "@imphnen-frontend-service/ui/atoms";
|
||||
import { motion, useInView, Variants } from "framer-motion";
|
||||
|
||||
const CATEGORIES = ['UI/UX Design', 'Software/Web Dev', 'Data & AI', 'Cloud & DevOps', 'Cybersecurity', 'IT & Network', 'Project Management', 'QA & Testing'] as const
|
||||
type Category = typeof CATEGORIES[number]
|
||||
import { useGetArticleCategories, useGetArticles } from "@imphnen-frontend-service/service";
|
||||
|
||||
export default function Components(): ReactElement {
|
||||
const [activeTab, setActiveTab] = useState<Category>('UI/UX Design')
|
||||
const [activeTab, setActiveTab] = useState<string>("Semua")
|
||||
const { data: articles = [], isLoading } = useGetArticles({ per_page: 20 })
|
||||
const { data: categories = [] } = useGetArticleCategories()
|
||||
|
||||
const tabs = ["Semua", ...categories]
|
||||
|
||||
const featured = articles[0]
|
||||
const recent = articles.slice(1, 4)
|
||||
const filtered = activeTab === "Semua"
|
||||
? articles
|
||||
: articles.filter((a) => a.category === activeTab)
|
||||
|
||||
const ref = useRef(null)
|
||||
const isInView = useInView(ref, { once: true, amount: 0.2 })
|
||||
@@ -52,29 +60,34 @@ export default function Components(): ReactElement {
|
||||
Featuring Articles
|
||||
</motion.h1>
|
||||
|
||||
<div className="grid gap-12 xl:grid-cols-2">
|
||||
<motion.div variants={childVariants}>
|
||||
<ArticleCard variant="featured" />
|
||||
</motion.div>
|
||||
<Show
|
||||
condition={!isLoading}
|
||||
fallback={<p className="text-neutral-500">Memuat artikel...</p>}
|
||||
>
|
||||
<div className="grid gap-12 xl:grid-cols-2">
|
||||
<motion.div variants={childVariants}>
|
||||
<ArticleCard variant="featured" article={featured} />
|
||||
</motion.div>
|
||||
|
||||
<div>
|
||||
<motion.h1
|
||||
className="text-[19px] text-neutral-800 font-semibold mb-10 md:text-[29px] xl:text-[37px] xl:mb-12"
|
||||
variants={childVariants}
|
||||
>
|
||||
Recent Articles
|
||||
</motion.h1>
|
||||
<div className="grid gap-10">
|
||||
<For data={Array.from({ length: 3 })}>
|
||||
{(_, index) => (
|
||||
<motion.div key={index} variants={childVariants}>
|
||||
<ArticleCard variant="recent" />
|
||||
</motion.div>
|
||||
)}
|
||||
</For>
|
||||
<div>
|
||||
<motion.h1
|
||||
className="text-[19px] text-neutral-800 font-semibold mb-10 md:text-[29px] xl:text-[37px] xl:mb-12"
|
||||
variants={childVariants}
|
||||
>
|
||||
Recent Articles
|
||||
</motion.h1>
|
||||
<div className="grid gap-10">
|
||||
<For data={recent}>
|
||||
{(article, index) => (
|
||||
<motion.div key={article.id ?? index} variants={childVariants}>
|
||||
<ArticleCard variant="recent" article={article} />
|
||||
</motion.div>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto">
|
||||
@@ -86,7 +99,7 @@ export default function Components(): ReactElement {
|
||||
</motion.h1>
|
||||
<div className="scrollbar-hide mb-8 w-full overflow-auto mx-auto">
|
||||
<motion.div className="min-w-max w-auto flex gap-x-3" variants={childVariants}>
|
||||
<For data={CATEGORIES}>
|
||||
<For data={tabs}>
|
||||
{(category) => (
|
||||
<Button
|
||||
key={category}
|
||||
@@ -106,15 +119,20 @@ export default function Components(): ReactElement {
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-8 xl:grid-cols-3">
|
||||
<For data={Array.from({ length: 3 })}>
|
||||
{(_, index) => (
|
||||
<motion.div key={index} variants={childVariants}>
|
||||
<ArticleCard />
|
||||
</motion.div>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
<Show
|
||||
condition={filtered.length > 0}
|
||||
fallback={<p className="text-neutral-500 text-center py-10">Belum ada artikel di kategori ini.</p>}
|
||||
>
|
||||
<div className="grid gap-8 xl:grid-cols-3">
|
||||
<For data={filtered}>
|
||||
{(article, index) => (
|
||||
<motion.div key={article.id ?? index} variants={childVariants}>
|
||||
<ArticleCard article={article} />
|
||||
</motion.div>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</motion.section>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user