spb/fabri-ka Public
Agrégateur de produits québécois — www.fabri-ka.com
HTML 57%
Python 19.9%
TypeScript 15.3%
CSS 7.7%
1import { useEffect, useState } from 'react'2import { Link } from 'react-router-dom'3import { fetchProducts, Product, ProductQuery } from '../api'4import { IconArrowRight } from './Icons'5import ProductCard from './ProductCard'6import { SkeletonRow } from './Skeleton'78interface RailProps {9 title: string10 query: ProductQuery11 seeAllHref?: string12}1314export default function Rail({ title, query, seeAllHref }: RailProps) {15 const [products, setProducts] = useState<Product[] | null>(null)16 const [error, setError] = useState(false)1718 useEffect(() => {19 const controller = new AbortController()20 setProducts(null)21 setError(false)22 fetchProducts({ per_page: 12, ...query }, controller.signal)23 .then((res) => setProducts(res.items))24 .catch((err: unknown) => {25 if (err instanceof DOMException && err.name === 'AbortError') return26 setError(true)27 setProducts([])28 })29 return () => controller.abort()30 // eslint-disable-next-line react-hooks/exhaustive-deps31 }, [JSON.stringify(query)])3233 if (error || (products !== null && products.length === 0)) {34 return null35 }3637 return (38 <section className="rail">39 <header className="section-header">40 <h2>{title}</h2>41 {seeAllHref && (42 <Link className="section-see-all" to={seeAllHref}>43 Tout voir <IconArrowRight size={15} />44 </Link>45 )}46 </header>47 {products === null ? (48 <SkeletonRow count={6} />49 ) : (50 <div className="rail-track">51 {products.map((p) => (52 <div className="rail-item" key={p.uid}>53 <ProductCard product={p} />54 </div>55 ))}56 </div>57 )}58 </section>59 )60}61