Commit 30ba4def by Madhankumar

pagination in bloglist

parent bf43f185
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
box-sizing: border-box; box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
text-decoration: none;
--heading1: clamp(1rem, 1.3rem + 2vw, 3rem); --heading1: clamp(1rem, 1.3rem + 2vw, 3rem);
--heading2: clamp(1rem, 1rem + 2vw, 1.7rem); --heading2: clamp(1rem, 1rem + 2vw, 1.7rem);
--heading3: clamp(0.8rem, 0.5rem + 1.5vw, 1.5rem); --heading3: clamp(0.8rem, 0.5rem + 1.5vw, 1.5rem);
......
...@@ -3,21 +3,11 @@ import Button from "."; ...@@ -3,21 +3,11 @@ import Button from ".";
export default { export default {
title: "Base/Button", title: "Base/Button",
component: Button, component: Button,
argTypes: {
backgroundColor: { control: "color" },
},
}; };
const Template = (args) => <Button {...args} />; export const button = {
args: {
export const Primary = Template.bind({}); variant: "primary",
Primary.args = { children: "Button",
label: "Primary", },
primary: true,
};
export const Secondary = Template.bind({});
Secondary.args = {
label: "Secondary",
primary: false,
}; };
import PropTypes from "prop-types";
import cn from "classnames";
import styles from "./styles.module.css"; import styles from "./styles.module.css";
const Button = ({ label, primary, classes }) => { const Button = ({ children, variant, className, ...props }) => {
const background = primary ? styles.primary : styles.secondary; const classNames = cn({
[styles[variant]]: variant,
[styles[className]]: className,
});
return ( return (
<button className={`${background} ${styles[classes]}`}>{label}</button> <button className={`${classNames}`} {...props}>
{children}
</button>
); );
}; };
Button.propTypes = {
variant: PropTypes.oneOf(["primary", "secondary", "disabled"]),
};
export default Button; export default Button;
...@@ -15,16 +15,20 @@ button { ...@@ -15,16 +15,20 @@ button {
background-color: var(--secondary-bgcolor); background-color: var(--secondary-bgcolor);
color: var(--secondary-color); color: var(--secondary-color);
} }
.disabled {
button .active { opacity: 0.7;
background-color: var(--secondary-bgcolor);
color: var(--secondary-color);
}
/* button .active {
background: #5a67d8; background: #5a67d8;
color: #fff; color: #fff;
border: 1px solid #7cbddb; border: 1px solid #7cbddb;
border-radius: 10px; border-radius: 10px;
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
} } */
/*
button.secondary:hover:not(.active) { button.secondary:hover:not(.active) {
color: var(--font-color-900); color: var(--font-color-900);
} }
...@@ -33,10 +37,7 @@ button .disabled { ...@@ -33,10 +37,7 @@ button .disabled {
cursor: not-allowed; cursor: not-allowed;
} }
/* .next {
font-size: 20px;
} */
button:hover:is(.no-cursor) { button:hover:is(.no-cursor) {
cursor: not-allowed; cursor: not-allowed;
user-select: none; user-select: none;
} } */
...@@ -5,18 +5,23 @@ export default { ...@@ -5,18 +5,23 @@ export default {
title: "Base/Card", title: "Base/Card",
component: Card, component: Card,
}; };
export const card = (args) => <Card {...args} />; export const card = {
card.args = { args: {
title: "How to get a perfect start for beginning runners", title: "How to get a perfect start for beginning runners",
description: description:
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.", "Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: { image: {
url: require("@img/lifestyle1.jpg"), url: require("@img/lifestyle1.jpg").default.src,
width: 470,
height: 300,
},
publishedDate: "July 13, 2020.",
author: "Isabella Ava",
images: {
url: require("@img/a1.jpg").default.src,
width: 80,
height: 80, // Use require to load images
},
readingTime: "1 min",
}, },
publishedDate: "July 13, 2020.",
authorName: "Isabella Ava",
images: {
url: require("@img/a1.jpg"), // Use require to load images
},
readingTime: "1 min",
}; };
import styles from "./styles.module.css"; import PropTypes from "prop-types";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import Icons from "../icons"; import Icons from "@components/base/icons";
import PropTypes from "prop-types"; import styles from "./styles.module.css";
const Card = ({ const Card = ({
title, title,
description, description,
image, image,
publishedDate, publishedDate,
authorName, author,
images, images,
readingTime, readingTime,
}) => { }) => {
return ( return (
<div className={styles.card}> <div className={styles.card}>
<Link href="#"> <Link href="#">
<Image className={styles.img} src={image.url} alt={title} /> <Image
className={styles.img}
src={image.url}
height={image.height}
width={image.width}
alt={title}
/>
<p className={styles.title}>{title}</p>
</Link> </Link>
<div className={styles["card-content"]}> <div className={styles.authorcontainer}>
<Link href="#" className={styles.title}>
<p>{title}</p>
</Link>
<p className={styles.description}>{description}</p> <p className={styles.description}>{description}</p>
<div className={styles.authorcontainer}> <div className={styles.cardbottom}>
<div className={styles.cardbottom}> <Image
<Image className={styles.img} src={images.url} alt={authorName} /> className={styles.img}
<div className={styles.authordescription}> src={images.url}
<p>{authorName}</p> height={images.height}
<div className={styles["author-desc"]}> width={images.width}
{publishedDate} alt={author}
<span className={styles.icon}> />
<Icons name="clock" size="small" /> <div className={styles.authordescription}>
{readingTime} <p className={styles.authorName}>{author}</p>
</span> <div className={styles["author-desc"]}>
</div> {publishedDate}
<span className={styles.icon}>
<Icons name="clock" size="small" />
{readingTime}
</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -49,7 +57,7 @@ Card.propTypes = { ...@@ -49,7 +57,7 @@ Card.propTypes = {
url: PropTypes.string, url: PropTypes.string,
}), }),
publishedDate: PropTypes.string, publishedDate: PropTypes.string,
authorName: PropTypes.string, author: PropTypes.string,
images: PropTypes.shape({ images: PropTypes.shape({
url: PropTypes.string, // Use PropTypes.string for images url: PropTypes.string, // Use PropTypes.string for images
}), }),
......
.img {
max-width: 100%;
height: auto;
border-top-right-radius: 20px;
border-top-left-radius: 20px;
}
.card { .card {
background-color: var(--card-bg); background-color: var(--card-bg);
border-radius: 20px; border-radius: 20px;
...@@ -13,66 +5,73 @@ ...@@ -13,66 +5,73 @@
flex-direction: column; flex-direction: column;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
word-wrap: break-word; word-wrap: break-word;
} &:hover {
.card:hover { transform: translateY(-10px);
transform: translateY(-10px); }
} .img {
max-width: 100%;
.card-content { height: auto;
padding: 1.5rem;
padding-bottom: 1rem;
}
.authordescription > p {
font-size: 18px;
font-weight: 500;
}
.cardbottom {
display: grid;
grid-template-columns: 0.5fr 2fr;
line-height: 0;
align-items: center;
grid-gap: 16px;
color: var(--font-color-900);
}
.cardbottom img { border-top-right-radius: 20px;
border-radius: 50%; border-top-left-radius: 20px;
height: auto; }
max-width: 100%;
} }
.description { .authorcontainer {
color: var(--font-color-300); padding: 1.5rem;
line-height: 1.5em; padding-top: 0rem;
font-weight: 600px; margin-top: -20px;
word-wrap: break-word; & .description {
color: var(--font-color-300);
line-height: 1.5em;
font-weight: 600px;
word-wrap: break-word;
}
.cardbottom {
display: grid;
grid-template-columns: 0.5fr 2fr;
line-height: 0;
align-items: center;
grid-gap: 16px;
color: var(--font-color-900);
.img {
border-radius: 50%;
height: auto;
max-width: 100%;
}
.authordescription {
.authorName {
font-size: 18px;
font-weight: 500;
}
.author-desc {
display: flex;
align-items: center;
gap: 1rem;
color: var(--font-color-300);
line-height: 0.5em;
& span {
display: flex;
align-items: center;
}
}
}
}
} }
.title { .title {
color: var(--font-color-900); color: var(--font-color-900);
font-size: 22px; font-size: 22px;
text-decoration: none;
line-height: 1.5em; line-height: 1.5em;
font-weight: 600; font-weight: 600;
padding: 1.5rem;
padding-bottom: 0rem;
&:hover {
color: #5a67d8;
}
} }
.title:hover { @media screen and (min-width: 768px) {
color: #5a67d8;
}
.author-desc {
display: flex;
align-items: center;
gap: 1rem;
color: var(--font-color-300);
line-height: 0.5em;
}
.author-desc span {
display: flex;
align-items: center;
}
@media screen and (min-width: 802px) {
.card { .card {
width: min(90%, 25rem); width: min(90%, 25rem);
} }
......
import styles from "./styles.module.css";
import Search from "../search";
import Icons from "../icons";
import { useTheme } from "@/app/context/index";
import Link from "next/link"; import Link from "next/link";
import Search from "@components/base/search";
import Icons from "@components/base/icons";
import { useTheme } from "@context/index";
import styles from "./styles.module.css";
function Header({ name, onThemeChange, onSearch, onClose }) { function Header({ name, onThemeChange, onSearch, onClose }) {
const { theme, toggleTheme } = useTheme(); const { theme, toggleTheme } = useTheme();
...@@ -32,9 +32,6 @@ function Header({ name, onThemeChange, onSearch, onClose }) { ...@@ -32,9 +32,6 @@ function Header({ name, onThemeChange, onSearch, onClose }) {
<div onClick={handleTheme} className={styles.themelight}> <div onClick={handleTheme} className={styles.themelight}>
<Icons name={theme == "light" ? "moon" : "sun"} size="medium" /> <Icons name={theme == "light" ? "moon" : "sun"} size="medium" />
<span className={styles.mobilemenu}>
<Icons name="hamburger" size="medium" classes="menu-icon" />
</span>
</div> </div>
</nav> </nav>
</div> </div>
......
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.7em 10%;
}
.container {
background-color: var(--card-bg);
width: 100%;
}
.header { .header {
position: sticky; position: sticky;
top: 57px; top: 57px;
height: 179px; height: 179px;
} .container {
.navbar-brand { background-color: var(--card-bg);
display: grid; width: 100%;
grid-template-columns: auto 1fr; .navbar {
gap: 1rem; display: flex;
align-items: center; align-items: center;
text-decoration: none; justify-content: space-between;
} padding: 0.7em 10%;
.navbar-brand h2 { .navbar-brand {
color: var(--title-color); display: grid;
} grid-template-columns: auto 1fr;
.mobilemenu { gap: 1rem;
display: block; align-items: center;
} text-decoration: none;
.themelight { h2 {
display: flex; color: var(--title-color);
gap: 1rem; }
} .themelight {
.search { display: flex;
display: none; gap: 1rem;
}
.search {
display: none;
}
}
}
}
} }
@media screen and (min-width: 991px) { @media screen and (min-width: 991px) {
.mobilemenu {
display: none;
}
.search { .search {
display: block; display: block;
} }
......
...@@ -3,7 +3,6 @@ import Icons from "."; ...@@ -3,7 +3,6 @@ import Icons from ".";
export default { export default {
title: "Base/Icons", title: "Base/Icons",
component: Icons, component: Icons,
argTypes: {},
}; };
const iconList = [ const iconList = [
"close", "close",
......
import styles from "./styles.module.css";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import cn from "classnames";
import styles from "./styles.module.css";
const Icons = ({ name, size, classes }) => { const Icons = ({ name, size, classes }) => {
const icons = { const icons = {
search: ( search: (
...@@ -92,10 +94,11 @@ const Icons = ({ name, size, classes }) => { ...@@ -92,10 +94,11 @@ const Icons = ({ name, size, classes }) => {
</svg> </svg>
), ),
}; };
const classNames = cn({
return ( [styles[classes]]: classes,
<span className={`${styles[classes]} ${styles[size]}`}>{icons[name]}</span> [styles[size]]: size,
); });
return <span className={classNames}>{icons[name]}</span>;
}; };
Icons.propTypes = { Icons.propTypes = {
......
import styles from "./styles.module.css";
import Icons from "../icons";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import Icons from "@components/base/icons";
import styles from "./styles.module.css";
const Search = ({ onSearch, onClose }) => { const Search = ({ onSearch, onClose }) => {
const [text, setText] = useState(""); const [text, setText] = useState("");
...@@ -26,12 +26,12 @@ const Search = ({ onSearch, onClose }) => { ...@@ -26,12 +26,12 @@ const Search = ({ onSearch, onClose }) => {
}; };
return ( return (
<div className={styles["search-input"]}> <div className={styles["search"]}>
<span className={`${styles["search-icon"]}`}> <span className={`${styles["search-icon"]}`}>
<Icons name="search" size="small" /> <Icons name="search" size="small" />
</span> </span>
<input <input
className={styles.search} className={styles["search-input"]}
type="text" type="text"
autoFocus={true} autoFocus={true}
value={text} value={text}
...@@ -40,7 +40,7 @@ const Search = ({ onSearch, onClose }) => { ...@@ -40,7 +40,7 @@ const Search = ({ onSearch, onClose }) => {
/> />
{text && ( {text && (
<span className={`${styles["close-icon"]}`} onClick={handleCustomClear}> <span className={`${styles["close-icon"]}`} onClick={handleCustomClear}>
<Icons name="close" /> <Icons name="close" size="small" />
</span> </span>
)} )}
</div> </div>
......
.search {
.search{
position: relative;
display: inline-block;
border-radius: 2px;
box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px;
.search-input {
height: 48px; height: 48px;
width: 30vw; width: 30vw;
background: #f4f4f4; background: #f4f4f4;
...@@ -7,12 +13,6 @@ ...@@ -7,12 +13,6 @@
padding-left: 3rem; padding-left: 3rem;
font-size: 16px; font-size: 16px;
} }
.search-input {
position: relative;
display: inline-block;
border-radius: 2px;
box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px;
}
.search-icon { .search-icon {
position: absolute; position: absolute;
top: 14px; top: 14px;
...@@ -28,3 +28,5 @@ ...@@ -28,3 +28,5 @@
top: 15px; top: 15px;
right: 15px; right: 15px;
} }
}
const Typography = () => {
return (
<div>
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer congue
placerat lobortis. Pellentesque facilisis nisl orci, non accumsan massa
auctor quis. Proin blandit sollicitudin turpis id laoreet. Vivamus
tincidunt maximus sem sit amet pulvinar. Praesent faucibus et tellus
quis hendrerit. Vestibulum a dui et sem egestas luctus.
</p>
</div>
);
};
export default Typography;
import Typography from ".";
export default { export default {
title: "Base/Typography", title: "Base/Typography",
component: Typography,
}; };
export const typography = {}; export const Typography = () => (
<div>
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer congue
placerat lobortis. Pellentesque facilisis nisl orci, non accumsan massa
auctor quis. Proin blandit sollicitudin turpis id laoreet. Vivamus
tincidunt maximus sem sit amet pulvinar. Praesent faucibus et tellus quis
hendrerit. Vestibulum a dui et sem egestas luctus.
</p>
</div>
);
...@@ -3,101 +3,143 @@ export default { ...@@ -3,101 +3,143 @@ export default {
title: "Top-Level/Blog-Lists", title: "Top-Level/Blog-Lists",
component: BlogLists, component: BlogLists,
}; };
export const blogLists = (args) => <BlogLists {...args} />; export const blogLists = {
args: {
title: "Lifestyle",
description:
"Lorem ipsum dolor sit amet elit. Id quaerat amet ipsum sunt et quos dolorum",
blogs: [
{
title: "How to get perfect start for beginning runners",
description:
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle1.jpg"),
},
publishedDate: "July 13, 2020.",
author: "Isabella ava",
images: {
url: require("@img/a1.jpg"),
},
blogLists.args = { readingTime: "1min",
title: "Lifestyle",
description:
"Lorem ipsum dolor sit amet elit. Id quaerat amet ipsum sunt et quos dolorum",
blogs: [
{
title: "How to get perfect start for beginning runners",
description:
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle1.jpg"),
},
publishedDate: "July 13, 2020.",
authorName: "Isabella ava",
images: {
url: require("@img/a1.jpg"),
}, },
{
title: "Great tools to improve your personal blogging experience",
description:
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle2.jpg"),
},
readingTime: "1min", publishedDate: "July 13, 2020.",
}, author: "Charlotte mia",
{ images: {
title: "Great tools to improve your personal blogging experience", url: require("@img/a2.jpg"),
description: },
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle2.jpg"),
},
publishedDate: "July 13, 2020.", readingTime: "1min",
authorName: "Charlotte mia",
images: {
url: require("@img/a2.jpg"),
}, },
{
title: "Blog Guide: How to Start a Personal blog on WordPress",
description:
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle3.jpg"),
},
publishedDate: "July 13, 2020.",
author: "Elizabeth",
images: {
url: require("@img/a3.jpg"),
},
readingTime: "1min", readingTime: "1min",
},
{
title: "Blog Guide: How to Start a Personal blog on WordPress",
description:
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle3.jpg"),
}, },
publishedDate: "July 13, 2020.", {
authorName: "Elizabeth", title: "The technical setup when starting a personal blog",
images: { description:
url: require("@img/a3.jpg"), "Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle4.jpg"),
},
publishedDate: "July 13, 2020.",
author: "Charlotte mia",
images: {
url: require("@img/a1.jpg"),
},
readingTime: "1min",
}, },
{
title: "3 New outfit Formulas To Add to your Capsule Wardrobe",
description:
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle5.jpg"),
},
publishedDate: "July 13, 2020.",
author: "Elizabeth",
images: {
url: require("@img/a3.jpg"),
},
readingTime: "1min", readingTime: "1min",
},
{
title: "The technical setup when starting a personal blog",
description:
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle4.jpg"),
}, },
publishedDate: "July 13, 2020.", {
authorName: "Charlotte mia", title: "3 New outfit Formulas To Add to your Capsule Wardrobe",
images: { description:
url: require("@img/a1.jpg"), "Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle6.jpg"),
},
publishedDate: "July 13, 2020.",
author: "Isabella ava",
images: {
url: require("@img/a1.jpg"),
},
readingTime: "1min",
}, },
readingTime: "1min", {
}, title: "3 New outfit Formulas To Add to your Capsule Wardrobe",
{ description:
title: "3 New outfit Formulas To Add to your Capsule Wardrobe", "Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
description: image: {
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.", url: require("@img/lifestyle6.jpg"),
image: { },
url: require("@img/lifestyle5.jpg"), publishedDate: "July 13, 2020.",
author: "Isabella ava",
images: {
url: require("@img/a1.jpg"),
},
readingTime: "1min",
}, },
publishedDate: "July 13, 2020.", {
authorName: "Elizabeth", title: "3 New outfit Formulas To Add to your Capsule Wardrobe",
images: { description:
url: require("@img/a3.jpg"), "Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
}, image: {
url: require("@img/lifestyle6.jpg"),
readingTime: "1min", },
}, publishedDate: "July 13, 2020.",
{ author: "Isabella ava",
title: "3 New outfit Formulas To Add to your Capsule Wardrobe", images: {
description: url: require("@img/a1.jpg"),
"Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.", },
image: { readingTime: "1min",
url: require("@img/lifestyle6.jpg"),
}, },
publishedDate: "July 13, 2020.", {
authorName: "Isabella ava", title: "3 New outfit Formulas To Add to your Capsule Wardrobe",
images: { description:
url: require("@img/a1.jpg"), "Lorem ipsum dolor sit amet consectetur ipsum adipisicing elit. Quis vitae sit.",
image: {
url: require("@img/lifestyle6.jpg"),
},
publishedDate: "July 13, 2020.",
author: "Isabella ava",
images: {
url: require("@img/a1.jpg"),
},
readingTime: "1min",
}, },
readingTime: "1min", ],
}, },
],
}; };
import React, { useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Card from "@/components/base/card"; import Card from "@/components/base/card";
import Pagination from "@components/top-level/pagination";
import styles from "./styles.module.css"; import styles from "./styles.module.css";
const BlogLists = ({ title, description, blogs }) => { const BlogLists = ({ title, description, blogs }) => {
const length = blogs.length;
const itemsPerPage = 6;
const [currentPage, setCurrentPage] = useState(1);
// Calculate the start and end indices for the current page
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const slicedData = blogs.slice(startIndex, endIndex);
// Handle page change
const handlePageChange = (pageNumber) => {
setCurrentPage(pageNumber);
};
return ( return (
<div className={styles["blog-container"]}> <div className={styles["blog-container"]}>
<h1 className={styles.title}>{title}</h1> <h1 className={styles.title}>{title}</h1>
<p className={styles.description}>{description}</p> <p className={styles.description}>{description}</p>
<div className={styles.row}> <div className={styles.row}>
{blogs.map((blogData, i) => ( {slicedData.map((blogData, i) => (
<div key={i} className={styles["card-container"]}> <div key={i} className={styles.col}>
<Card {...blogData} /> <Card {...blogData} />
</div> </div>
))} ))}
</div> </div>
<div className={styles.pagination}>
<Pagination
currentPage={currentPage}
total={length}
perPage={itemsPerPage}
onPageChange={handlePageChange}
/>
</div>
</div> </div>
); );
}; };
BlogLists.propTypes = { BlogLists.propTypes = {
title: PropTypes.string, title: PropTypes.string,
description: PropTypes.string, description: PropTypes.string,
......
.blog-container { .blog-container {
max-width: 1200px; max-width: 1200px;
margin: 0 auto; margin: 0 auto;
} .title {
.row {
display: grid;
grid-row-gap: 3rem;
}
.card-container {
display: flex;
align-self: normal;
flex: 1 0 auto;
}
.title {
font-size: 38px; font-size: 38px;
line-height: 25px; line-height: 25px;
font-weight: 600; font-weight: 600;
...@@ -25,18 +13,36 @@ ...@@ -25,18 +13,36 @@
padding-inline: 1.5rem; padding-inline: 1.5rem;
margin-bottom: 3em; margin-bottom: 3em;
} }
@media screen and (min-width: 802px) { .row {
display: grid;
grid-row-gap: 3rem;
.col {
display: flex;
align-self: normal;
flex: 1 0 auto;
}
}
}
.pagination{
margin-top: 3rem;
}
@media screen and (min-width: 768px) {
.row { .row {
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
justify-items: center; justify-items: center;
} }
} }
@media screen and (min-width: 1440px) { @media screen and (min-width: 1440px) {
.row {
.bloglist-container {
padding: 0 100px;
.row {
grid-template-columns: repeat(auto-fill, minmax(25rem, 1fr)); grid-template-columns: repeat(auto-fill, minmax(25rem, 1fr));
justify-items: center; justify-items: center;
} }
.bloglist-container {
padding: 0 100px;
} }
} }
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import styles from "./styles.module.css";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Button from "@/components/base/button"; import Button from "@/components/base/button";
import styles from "./styles.module.css";
function Pagination({ total, currentPage, onPageChange }) { function Pagination({ total, currentPage, onPageChange, perPage }) {
//Set number of pages //Set number of pages
const numberOfPages = []; const numberOfPages = [];
const totalPage = total <= 1 ? 1 : total; const totalPages = Math.round(total / perPage);
const totalPage = totalPages <= 1 ? 1 : totalPages;
for (let i = 1; i <= totalPage; i++) { for (let i = 1; i <= totalPage; i++) {
numberOfPages.push(i); numberOfPages.push(i);
} }
...@@ -18,7 +20,7 @@ function Pagination({ total, currentPage, onPageChange }) { ...@@ -18,7 +20,7 @@ function Pagination({ total, currentPage, onPageChange }) {
const [arrOfCurrButtons, setArrOfCurrButtons] = useState([]); const [arrOfCurrButtons, setArrOfCurrButtons] = useState([]);
useEffect(() => { useEffect(() => {
let tempNumberOfPages = [...arrOfCurrButtons]; let tempNumberOfPages = [...arrOfCurrButtons];
//adding dots
let dotsInitial = "..."; let dotsInitial = "...";
let dotsLeft = "..."; let dotsLeft = "...";
let dotsRight = "..."; let dotsRight = "...";
...@@ -49,7 +51,7 @@ function Pagination({ total, currentPage, onPageChange }) { ...@@ -49,7 +51,7 @@ function Pagination({ total, currentPage, onPageChange }) {
} }
setArrOfCurrButtons(tempNumberOfPages); setArrOfCurrButtons(tempNumberOfPages);
}, [total, currentButton]); }, [total, currentButton, perPage]);
//update currentButton value if currentPageNo changes //update currentButton value if currentPageNo changes
useEffect(() => { useEffect(() => {
...@@ -64,43 +66,42 @@ function Pagination({ total, currentPage, onPageChange }) { ...@@ -64,43 +66,42 @@ function Pagination({ total, currentPage, onPageChange }) {
return ( return (
<div className={styles["pagination-container"]}> <div className={styles["pagination-container"]}>
<span className={styles.previous}>
<Button
variant={currentButton <= 1 ? "disabled" : "secondary"}
onClick={() =>
currentButton <= 1 ? "" : handleCurrentPage(currentButton - 1)
}
>
&laquo; Prev
</Button>
</span>
{arrOfCurrButtons.map((item, index) => { {arrOfCurrButtons.map((item, index) => {
return ( return (
<span <span key={index}>
key={index}
onClick={() => (item === "..." ? "" : handleCurrentPage(item))}
>
<Button <Button
label={item} variant={currentButton === item ? "primary" : "secondary"}
primary={currentButton === item ? true : false} primary={currentButton === item ? true : false}
classes={`${ onClick={() => (item === "..." ? "" : handleCurrentPage(item))}
item === "..." >
? "no-cursor" {item}
: currentButton === item </Button>
? "active"
: ""
}`}
/>
</span> </span>
); );
})} })}
<span <span className={styles.next}>
onClick={() =>
currentButton === "..." || currentButton === numberOfPages.length
? ""
: handleCurrentPage(currentButton + 1)
}
>
<Button <Button
label="Next »" variant={
className={`${ currentButton === numberOfPages.length ? "disabled" : "secondary"
currentButton === "..." }
? "no-cursor" onClick={() =>
: currentButton === numberOfPages.length currentButton === numberOfPages.length
? "disabled" ? ""
: "" : handleCurrentPage(currentButton + 1)
}`} }
/> >
Next &raquo;
</Button>
</span> </span>
</div> </div>
); );
......
...@@ -11,5 +11,6 @@ export const pagination = { ...@@ -11,5 +11,6 @@ export const pagination = {
args: { args: {
total: 10, total: 10,
currentPage: 1, currentPage: 1,
perPage: 2,
}, },
}; };
...@@ -6,17 +6,25 @@ ...@@ -6,17 +6,25 @@
width: 100%; width: 100%;
font-weight: 500; font-weight: 500;
font-size: 15px; font-size: 15px;
> span {
display: flex;
justify-content: center;
align-items: center;
margin: 0 0.2em;
padding-inline: 4px;
border-radius: 10px;
height: 40px;
text-decoration: none;
transition: background-color 0.2s;
cursor: pointer;
}
} }
/* .previous button:active,
.pagination-container span { .next button:active {
display: flex; background-color: var(--primary-bgcolor);
justify-content: center; color: var(--primary-color);
align-items: center; } */
margin: 0 0.2em; :is(.previous, .next) button:active {
padding-inline: 4px; background-color: var(--primary-bgcolor);
border-radius: 10px; color: var(--primary-color);
height: 40px;
text-decoration: none;
transition: background-color 0.2s;
cursor: pointer;
} }
import PropTypes from "prop-types";
import Image from "next/image"; import Image from "next/image";
import styles from "./styles.module.css";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
import PropTypes from "prop-types"; import styles from "./styles.module.css";
function SingleBlog({ function SingleBlog({
title, title,
publishedDate, publishedDate,
authorName, author,
category, category,
readingTime, readingTime,
images, image,
categories, categories,
markdown, markdown,
}) { }) {
...@@ -29,7 +28,7 @@ function SingleBlog({ ...@@ -29,7 +28,7 @@ function SingleBlog({
<li> <li>
By&nbsp; By&nbsp;
<a href="#" className={styles["list-bold"]}> <a href="#" className={styles["list-bold"]}>
{authorName} {author}
</a> </a>
</li> </li>
<li> <li>
...@@ -48,7 +47,13 @@ function SingleBlog({ ...@@ -48,7 +47,13 @@ function SingleBlog({
</div> </div>
<div className={styles["blog-container"]}> <div className={styles["blog-container"]}>
<div className={styles.blogimage}> <div className={styles.blogimage}>
<Image className={styles.img} src={images.url} alt={title} /> <Image
className={styles.img}
src={image.url}
alt={title}
width={image.width}
height={image.height}
/>
</div> </div>
<div className={styles["blog-content"]}> <div className={styles["blog-content"]}>
<ReactMarkdown remarkPlugins={[remarkGfm]}>{markdown}</ReactMarkdown> <ReactMarkdown remarkPlugins={[remarkGfm]}>{markdown}</ReactMarkdown>
...@@ -73,6 +78,8 @@ SingleBlog.propTypes = { ...@@ -73,6 +78,8 @@ SingleBlog.propTypes = {
categories: PropTypes.array, categories: PropTypes.array,
image: PropTypes.shape({ image: PropTypes.shape({
url: PropTypes.string, url: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
}), }),
}; };
export default SingleBlog; export default SingleBlog;
...@@ -2,22 +2,22 @@ import SingleBlog from "."; ...@@ -2,22 +2,22 @@ import SingleBlog from ".";
export default { export default {
title: "Top-Level/Single-Blog", title: "Top-Level/Single-Blog",
component: SingleBlog, component: SingleBlog,
argTypes: {},
}; };
export const singleBlog = (args) => <SingleBlog {...args} />; export const singleBlog = {
args: {
singleBlog.args = { title: "Create an Art that shows the beauty in everyone ideas of flaws.",
title: "Create an Art that shows the beauty in everyone ideas of flaws.", publishedDate: "July 11,2020",
publishedDate: "July 11,2020", author: "Charlotte mia",
authorName: "Charlotte mia", image: {
images: { url: require("@/public/images/blogsingle.jpg").default.src,
url: require("@/public/images/blogsingle.jpg"), width: 1100,
}, height: 400,
},
category: "Fashion",
readingTime: "1 min read", category: "Fashion",
categories: ["Fashion", "Beauty"], readingTime: "1 min read",
markdown: ` categories: ["Fashion", "Beauty"],
markdown: `
## How to create an Art that shows the beauty in everyone ideas of flaws. ## How to create an Art that shows the beauty in everyone ideas of flaws.
Fusce faucibus ante vitae justo efficitur elementum.Donec et ipsum faucibus arcu ipsum elementum ,luctus justo. ac purus semper.Fusce Fusce faucibus ante vitae justo efficitur elementum.Donec et ipsum faucibus arcu ipsum elementum ,luctus justo. ac purus semper.Fusce
...@@ -54,4 +54,5 @@ Lorem faucibus fusce ante vitae justo efficitur elementum.Donec ipsum faucibus a ...@@ -54,4 +54,5 @@ Lorem faucibus fusce ante vitae justo efficitur elementum.Donec ipsum faucibus a
vitae justo efficitur elementum.Donec et ipsum faucibus.Donec et ipsum faucibus arcu. vitae justo efficitur elementum.Donec et ipsum faucibus.Donec et ipsum faucibus arcu.
Fusce faucibus arcu faucibus ante vitae justo efficitur elementum.Donec ipsum faucibus.Donec ipsum faucibus arcu.`, Fusce faucibus arcu faucibus ante vitae justo efficitur elementum.Donec ipsum faucibus.Donec ipsum faucibus arcu.`,
},
}; };
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./*"], "@/*": ["./*"],
"@components/*": ["components/*"],
"@img/*": ["public/images/*"], "@img/*": ["public/images/*"],
"@context/*": ["app/context/*"], "@context/*": ["app/context/*"],
} }
......
...@@ -11,9 +11,11 @@ ...@@ -11,9 +11,11 @@
"@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/react-fontawesome": "^0.1.14", "@fortawesome/react-fontawesome": "^0.1.14",
"classnames": "^2.3.2",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"next": "14.0.2", "next": "14.0.2",
"next-themes": "^0.2.1", "next-themes": "^0.2.1",
"prettier": "^3.1.0",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"react-icons": "^4.12.0", "react-icons": "^4.12.0",
...@@ -4396,6 +4398,21 @@ ...@@ -4396,6 +4398,21 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/@storybook/cli/node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/@storybook/client-logger": { "node_modules/@storybook/client-logger": {
"version": "7.5.3", "version": "7.5.3",
"resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.5.3.tgz", "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.5.3.tgz",
...@@ -4434,6 +4451,21 @@ ...@@ -4434,6 +4451,21 @@
"url": "https://opencollective.com/storybook" "url": "https://opencollective.com/storybook"
} }
}, },
"node_modules/@storybook/codemod/node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/@storybook/components": { "node_modules/@storybook/components": {
"version": "7.5.3", "version": "7.5.3",
"resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.5.3.tgz", "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.5.3.tgz",
...@@ -7637,6 +7669,11 @@ ...@@ -7637,6 +7669,11 @@
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
}, },
"node_modules/classnames": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
"node_modules/clean-css": { "node_modules/clean-css": {
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz",
...@@ -14437,15 +14474,14 @@ ...@@ -14437,15 +14474,14 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "2.8.8", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==",
"dev": true,
"bin": { "bin": {
"prettier": "bin-prettier.js" "prettier": "bin/prettier.cjs"
}, },
"engines": { "engines": {
"node": ">=10.13.0" "node": ">=14"
}, },
"funding": { "funding": {
"url": "https://github.com/prettier/prettier?sponsor=1" "url": "https://github.com/prettier/prettier?sponsor=1"
......
...@@ -13,10 +13,12 @@ ...@@ -13,10 +13,12 @@
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/react-fontawesome": "^0.1.14", "@fortawesome/react-fontawesome": "^0.1.14",
"classnames": "^2.3.2",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"next": "14.0.2", "next": "14.0.2",
"next-themes": "^0.2.1", "next-themes": "^0.2.1",
"prettier": "^3.1.0",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"react-icons": "^4.12.0", "react-icons": "^4.12.0",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment