From a080bc4361f1de2a536c996316a5020c0114801b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9CSalar?= <“salar.sali97@gmail.com”>
Date: Tue, 30 Aug 2022 14:05:37 +0300
Subject: [PATCH]  Featured articales section - Card component

---
 src/components/Card.tsx              |  66 ++++++----
 src/components/FeaturedArticales.tsx | 188 +++++++++++++++++++++++++++
 2 files changed, 229 insertions(+), 25 deletions(-)
 create mode 100644 src/components/FeaturedArticales.tsx

diff --git a/src/components/Card.tsx b/src/components/Card.tsx
index 11089f8..49818fc 100644
--- a/src/components/Card.tsx
+++ b/src/components/Card.tsx
@@ -1,5 +1,5 @@
-import React, { Children } from "react";
 import classNames from "classnames";
+import React from "react";
 
 /* -------------------------------------------------------------------------- */
 /*                                 Components                                 */
@@ -27,7 +27,7 @@ const Card = ({ children, className }: Props) => {
     <div
       className={classNames([
         className,
-        "inline-flex flex-col justify-between p-4 max-w-xs lg:max-w-sm h-52 items-start rounded border border-[#F0F0F0]  gap-y-8 overflow-hidden",
+        "inline-flex flex-col justify-between p-4 items-start rounded border border-gray-75  gap-y-8 overflow-hidden",
       ])}
     >
       {children}
@@ -35,69 +35,71 @@ const Card = ({ children, className }: Props) => {
   );
 };
 
-// Avatar props and function
+// Avatar function
 type AvatarProps = {
   children?: React.ReactNode;
 };
 Card.Avatar = function CardAvatar({ children }: AvatarProps) {
-  return <>{children}</>;
+  return <div>{children}</div>;
 };
-// The end of Body props and function
 
-// Title props and function
+// Title function
 Card.Title = function CardTitle({ children, className }: Props) {
   return (
-    <Heading className={classNames([className, "select-none leading-7"])}>
+    <Heading className={classNames([className, "select-none  "])}>
       {children}
     </Heading>
   );
 };
-// The end Title props and function
 
-// Body props and function
+// SubTitle function
+Card.SubTitle = function CardSubTitle({ children, className }: Props) {
+  return (
+    <Typography className={classNames([className, ""])}>{children}</Typography>
+  );
+};
+
+// Body function
 Card.Body = function CardTitle({ children, className }: Props) {
   return (
-    <Typography
+    <Typography //
       fontWeightVariant="normal"
-      className={classNames([className, "text-sm"])}
+      className={classNames([className, "text-sm h-14 overflow-hidden "])}
     >
       {children}
     </Typography>
   );
 };
-// The end of Body props and function
 
-// Cardheader props and function
-Card.Cardheader = function CardCardheader({ children, className }: Props) {
+// Cardheader function
+Card.CardHeader = function CardCardHeader({ children, className }: Props) {
   return (
-    <div className={classNames([className, "first flex items-start gap-4"])}>
+    <div className={classNames([className, "flex items-start gap-4"])}>
       {children}
     </div>
   );
 };
-// The end of Cardheader props and function
 
-// Cardcontent props and function
-Card.Cardcontent = function CardCardcontent({ children, className }: Props) {
+// Cardcontent function
+Card.CardContent = function CardCardContent({ children, className }: Props) {
   return (
-    <div className={classNames([className, "flex flex-col gap-y-4"])}>
+    <div className={classNames([className, "flex flex-col gap-y-4 "])}>
       {children}
     </div>
   );
 };
-// The end of Cardcontent props and function
 
-// Cardaction props and function
-type CardactionProps = {
+// Cardaction function
+type CardActionProps = {
   children: React.ReactNode;
   className?: string | undefined;
   href?: string;
 };
-Card.Cardaction = function CardCardaction({
+Card.CardAction = function CardCardAction({
   children,
   className,
   href = "#",
-}: CardactionProps) {
+}: CardActionProps) {
   return (
     <Link
       href={href}
@@ -107,6 +109,20 @@ Card.Cardaction = function CardCardaction({
     </Link>
   );
 };
-// The end of Cardaction props and function
+
+// CardMedia function
+type CardMediaProps = {
+  children?: React.ReactNode;
+  className?: string | undefined;
+  src?: string;
+};
+Card.CardMedia = function CardCardMedia({
+  className,
+  src = "#",
+}: CardMediaProps) {
+  return (
+    <img src={src} className={classNames([className, "w-full h-32 rounded"])} />
+  );
+};
 
 export default Card;
diff --git a/src/components/FeaturedArticales.tsx b/src/components/FeaturedArticales.tsx
new file mode 100644
index 0000000..37eaef6
--- /dev/null
+++ b/src/components/FeaturedArticales.tsx
@@ -0,0 +1,188 @@
+import { useRef } from "react";
+
+/* -------------------------------------------------------------------------- */
+/*                                  Skeleton                                  */
+/* -------------------------------------------------------------------------- */
+import "react-loading-skeleton/dist/skeleton.css";
+
+/* -------------------------------------------------------------------------- */
+/*                                 Components                                 */
+/* -------------------------------------------------------------------------- */
+import Typography from "./typography/Typography";
+import SkeletonCard from "./SkeletonCard";
+import AspectRatio from "./AspectRatio";
+import Card from "./Card";
+import Link from "./Link";
+
+/* -------------------------------------------------------------------------- */
+/*                                    Data                                    */
+/* -------------------------------------------------------------------------- */
+import Articales from "./Articales.json";
+
+/* -------------------------------------------------------------------------- */
+/*                                    Icons                                   */
+/* -------------------------------------------------------------------------- */
+import { ReactComponent as SVGArrowRight } from "assets/svg/arrow-right.svg";
+import { ReactComponent as SVGCaretRight } from "assets/svg/caret-right.svg";
+import { ReactComponent as SVGArrowLeft } from "assets/svg/arrow-left.svg";
+
+/* -------------------------------------------------------------------------- */
+/*                                   Swiper                                   */
+/* -------------------------------------------------------------------------- */
+import { Swiper, SwiperSlide } from "swiper/react";
+import SwiperCore, { Navigation } from "swiper";
+import { Pagination } from "swiper";
+import "swiper/css/pagination";
+import "swiper/css/navigation";
+import "./styles.css";
+import "swiper/css";
+
+/* -------------------------------------------------------------------------- */
+/*            How many Skeleton cards should be added to the design           */
+/* -------------------------------------------------------------------------- */
+let twoCards: boolean = false;
+let threeCards: boolean = false;
+console.log(`Number of cards ${Articales.length}`);
+if (Articales.length == 2) {
+  twoCards = true;
+} else if (Articales.length == 3) {
+  threeCards = true;
+}
+
+SwiperCore.use([Navigation]);
+
+const FeaturedArticales = () => {
+  const navigationPrevRef = useRef(null);
+  const navigationNextRef = useRef(null);
+  const paginationRef = useRef(null);
+
+  return (
+    <div className="slider-wrapper Articales">
+      <div className="flex justify-end gap-2 my-2">
+        <div
+          className="prev inline-flex  justify-center items-center 
+        w-9 h-9 bg-blue-600 rounded cursor-pointer
+        opacity-0 md:opacity-100"
+          ref={navigationPrevRef}
+        >
+          <SVGArrowLeft className="w-6 h-6 fill-white "></SVGArrowLeft>
+        </div>
+        <div
+          className="next inline-flex  justify-center items-center 
+        w-9 h-9 bg-blue-600 rounded cursor-pointer
+        opacity-0 md:opacity-100"
+          ref={navigationNextRef}
+        >
+          <SVGArrowRight className="w-6 h-6 fill-white "></SVGArrowRight>
+        </div>
+      </div>
+
+      <Swiper
+        slidesPerView={1.25}
+        slidesPerGroup={1}
+        loop={Articales.length > 4 ? true : false}
+        pagination={{ el: ".pagination", clickable: true }}
+        navigation={{
+          prevEl: ".prev",
+          nextEl: ".next",
+        }}
+        breakpoints={{
+          768: {
+            slidesPerView: 2,
+            slidesPerGroup: 2,
+          },
+          1024: {
+            slidesPerView: 2,
+            slidesPerGroup: 2,
+          },
+          1280: {
+            slidesPerView: 4,
+            slidesPerGroup: 4,
+          },
+          1580: {
+            slidesPerView: 4,
+            slidesPerGroup: 4,
+          },
+        }}
+        spaceBetween={25}
+        loopFillGroupWithBlank={true}
+        modules={[Pagination, Navigation]}
+      >
+        {Articales.map((Articale) => (
+          <SwiperSlide>
+            <Card className="flex-1">
+              <Card.CardContent>
+                <AspectRatio>
+                  <AspectRatio.Content>
+                    <img src={Articale.CoverImg} />
+                  </AspectRatio.Content>
+                </AspectRatio>
+
+                <Card.Body className="h-14 overflow-hidden">
+                  {Articale.Body}
+                </Card.Body>
+              </Card.CardContent>
+
+              <Card.CardAction href={Articale.Link}>
+                <Link>
+                  <Typography className="text-blue-500 font-bold">
+                    Read More
+                  </Typography>
+                </Link>
+                <SVGCaretRight className="fill-blue-500 w-4 h-4" />
+              </Card.CardAction>
+            </Card>
+          </SwiperSlide>
+        ))}
+
+        {twoCards && [
+          <SwiperSlide className="hidden xl:block">
+            <SwiperSlide>
+              <SkeletonCard className="flex-1">
+                <SkeletonCard.Content>
+                  <SkeletonCard.Media />
+                  <SkeletonCard.Body />
+                </SkeletonCard.Content>
+                <SkeletonCard.Action />
+              </SkeletonCard>
+            </SwiperSlide>
+          </SwiperSlide>,
+
+          <SwiperSlide className="hidden xl:block">
+            <SwiperSlide>
+              <SkeletonCard className="flex-1">
+                <SkeletonCard.Content>
+                  <SkeletonCard.Media />
+                  <SkeletonCard.Body />
+                </SkeletonCard.Content>
+                <SkeletonCard.Action />
+              </SkeletonCard>
+            </SwiperSlide>
+          </SwiperSlide>,
+        ]}
+
+        {threeCards && [
+          <SwiperSlide className="hidden xl:block">
+            <SwiperSlide>
+              <SkeletonCard className="flex-1">
+                <SkeletonCard.Content>
+                  <SkeletonCard.Media />
+                  <SkeletonCard.Body />
+                </SkeletonCard.Content>
+                <SkeletonCard.Action />
+              </SkeletonCard>
+            </SwiperSlide>
+          </SwiperSlide>,
+        ]}
+      </Swiper>
+
+      <div
+        className="pagination my-6 w-full h-2 flex justify-center  items-center 
+        opacity-0 md:opacity-100"
+        ref={paginationRef}
+      />
+    </div>
+  );
+};
+
+export default FeaturedArticales;