Skip to content

Commit

Permalink
feature(Landing-page): add article cards carousel
Browse files Browse the repository at this point in the history
> - add article-card carousel

[Starts #167701704]
  • Loading branch information
tunedev authored and devPinheiro committed Aug 7, 2019
1 parent 9d5601e commit 9d7d715
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/components/ArticleCard/ArticleCard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
box-shadow: 0px 0px 26px rgba(0, 0, 0, 0.3);

.card-img-top {
width: 320px;
height: 182px;
max-width: 100%;
max-height: 182px;
border-radius: 4px 4px 0px 0px;
}

Expand Down Expand Up @@ -40,13 +40,13 @@
justify-content: space-between;
}

.avatar p {
.avatar span {
font-size: 10px;
margin-top: 7px;
line-height: 12px;
}

.avatar p small {
.avatar span small {
font-weight: 300;
font-size: 6px;
line-height: 7px;
Expand All @@ -64,6 +64,10 @@
.dark-theme {
color: white;
background: rgba(22, 22, 22, 0.89);

.avatar span small {
color: #c4c4c4;
}
}

.light-theme {
Expand Down
105 changes: 105 additions & 0 deletions src/components/Carousel/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React, { Component } from 'react';
import ArticleCard from '../ArticleCard/index.jsx';
import PropTypes from 'prop-types';
import paginator from '../../utils/paginator';
import './style.scss';
import Carousel from 'react-bootstrap/Carousel';

const CarouselSections = ({ sectionItems }) => {
return sectionItems.map((articleDetails, id) => {
return <ArticleCard key={id} {...articleDetails} />;
});
};

class CarouselContainer extends Component {
state = {
index: 0,
direction: null,
articlesCardPerCarousel: 4
};

componentDidMount() {
window.addEventListener('resize', () => {
this.setArticleCardPerCarousel(screen.width);
});
}

componentWillMount() {
this.setArticleCardPerCarousel(screen.width);
}

setArticleCardPerCarousel(width) {
let result;
if (width >= 1308) result = 4;
else if (width >= 983) result = 3;
else if (width >= 667) result = 2;
else {
result = 1;
}

this.setState({ articlesCardPerCarousel: result });
}

setDirection(direction) {
this.setState({
index: direction
});
}

setIndex(changeIndex) {
this.setState({
index: changeIndex
});
}

render() {
const { articles, category } = this.props;
const { articlesCardPerCarousel, index, direction } = this.state;

const handleSelect = (selectedIndex, e) => {
this.setIndex(selectedIndex);
this.setDirection(e.direction);
};

const sections = paginator(articles, articlesCardPerCarousel);

const finalSections = sections.map((sectionItems, id) => {
return (
<Carousel.Item key={id}>
<section className={'customFeel'} key={id}>
<CarouselSections key={id} sectionItems={sectionItems} />
</section>
</Carousel.Item>
);
});

return (
<div className="carousel-container">
<div className="carousel-top-Label">
<h1 className="carousel-label">
{category} <span className="explore-all">> explore all</span>
</h1>
<hr className="carousel-line" />
</div>
<Carousel
indicators={false}
activeIndex={index}
direction={direction}
onSelect={handleSelect}
interval={null}
keyboard={true}
touch={true}
>
{finalSections}
</Carousel>
</div>
);
}
}

CarouselContainer.propTypes = {
articles: PropTypes.array.isRequired,
category: PropTypes.string.isRequired
};

export default CarouselContainer;
90 changes: 90 additions & 0 deletions src/components/Carousel/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
import Carousel from './index.jsx';

const articleDetails = {
articleImage: '../../src/assets/images/profileImage.jpg',
light: false,
articleTitle: 'Understanding React and redux',
authorImage: '../../src/assets/images/react.png',
author: 'Damilola Adekoya',
email: 'damilola.adekoya@andela.com',
readTime: '6 mins'
};
const articles = [
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails,
articleDetails
];

describe('Render component', () => {
it('should render the carousel component', () => {
const wrapper = shallow(
<Carousel articles={articles} category="Technology" />
);
expect(wrapper.exists()).toEqual(true);
expect(wrapper.hasClass('carousel-container')).toEqual(true);
});

it('should confirm the carousel prev click', () => {
const wrapper = mount(
<Carousel articles={articles} category="Technology" />
);
expect(wrapper.exists()).toEqual(true);
expect(wrapper.find('.carousel-control-prev')).toBeTruthy();

expect(
wrapper.find('a.carousel-control-prev').simulate('click')
).toBeTruthy();

expect(wrapper.find('.articleCard')).toHaveLength(articles.length);
});

it('should successfully simulate the carousel prev button click', () => {
const wrapper = mount(
<Carousel articles={articles} category="Technology" />
);
expect(wrapper.exists()).toEqual(true);
expect(wrapper.find('.carousel-control-prev')).toBeTruthy();

wrapper.find('a.carousel-control-prev').simulate('click');

expect(wrapper.find('.articleCard')).toHaveLength(articles.length);
});

it('should confirm the carousel next click', () => {
const wrapper = mount(
<Carousel articles={articles} category="Technology" />
);
expect(wrapper.exists()).toEqual(true);
expect(wrapper.find('.carousel-control-next')).toBeTruthy();

expect(
wrapper.find('a.carousel-control-next').simulate('click')
).toBeTruthy();

expect(wrapper.find('.articleCard')).toHaveLength(articles.length);
});

it('should successfully simulate the carousel next button click', () => {
const wrapper = mount(
<Carousel articles={articles} category="Technology" />
);
expect(wrapper.exists()).toEqual(true);
expect(wrapper.find('.carousel-control-next')).toBeTruthy();

wrapper.find('a.carousel-control-next').simulate('click');

expect(wrapper.find('.articleCard')).toHaveLength(articles.length);
});
});
62 changes: 62 additions & 0 deletions src/components/Carousel/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
* {
box-sizing: border-box;
}

.carousel-container {
max-width: 100%;
padding: 0 5px;
margin: 0 auto;
.customFeel {
display: flex;
justify-content: space-evenly;
max-width: 95%;
margin: 0 auto;

div.articleCard:hover {
opacity: 0.7;
cursor: pointer;
}
}

.carousel-control-prev,
.carousel-control-next {
color: white;
background: #219653;
display: inline-block;
width: 63px !important;
height: 63px;
border-radius: 50%;
top: 40% !important;

.carousel-control-prev-icon,
.carousel-control-next-icon {
position: relative;
top: 35%;
}
}
}

.carousel-top-Label {
text-transform: capitalize;
margin: 5px auto;
width: 95%;
.carousel-label {
font-size: 14px;
}

.carousel-line {
background: rgba(255, 255, 255, 0.19);
}

.explore-all {
color: #919090;
font-size: 11px;
opacity: 0;
transition: 0.3s all;
}

.explore-all:hover {
opacity: 1;
cursor: pointer;
}
}
17 changes: 17 additions & 0 deletions src/utils/paginator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const paginator = (items, itemCount) => {
const sections = [];
let section = [];
let count = 0;

items.forEach(element => {
section.push(element);
count++;
if (section.length === itemCount || count === items.length) {
sections.push(section);
section = [];
}
});
return sections;
};

export default paginator;

0 comments on commit 9d7d715

Please sign in to comment.