Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-gatsby": "^0.5.14",
"classnames": "^2.2.6",
"gatsby": "^2.24.85",
"gatsby-legacy-polyfills": "0.0.5",
"gatsby-plugin-manifest": "2.4.31",
Expand Down
69 changes: 69 additions & 0 deletions src/components/UI/blog-entries/blog-entries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from "react";
import CardFactory from "../card/card-factory";
import { getStyles } from "./utils";
import { BlogGrid, BlogCard } from "./styles";

// TODO: Fake city & event cards
const fakeCardsData = [
// {
// id: 5,
// title: "Trabajo Remoto",
// subtitle: "Enero 16 - 17:00",
// url_img:
// "https://javascriptecuador.netlify.app/static/quito-605ac9d2e0009a60014111b3bedf73c9.jpg",
// description_title: "Disertantes",
// description: "Crysfel Villa, Freddy Santacruz",
// url_entry: "!#",
// type: "event",
// },
// {
// id: 6,
// title: "Guayaquil.js",
// subtitle: null,
// url_img:
// "https://javascriptecuador.netlify.app/static/quito-605ac9d2e0009a60014111b3bedf73c9.jpg",
// description_title: "Descripción",
// description:
// "Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab, voluptas. Aperiam cumque minus eius itaque odio ullam quam repudiandae delectus. Totam, eveniet deserunt. Nobis, mollitia natus! Architecto alias asperiores rerum.",
// url_entry: "!#",
// author: "Crysfel Villa, Freddy Santacruz",
// type: "city",
// },
];

const BlogEntries = ({ data }) => {
const styles = getStyles(data.length);
const cards = data.map((card, index) => {
console.log(card);
const {
gridRow,
widthImg,
gridColumn,
flexDirection,
paddingLeftContent,
paddingTopContent,
paddingBottomTitle,
paddingBlockFooter,
} = styles[index];

return (
<BlogCard
gridRow={gridRow}
widthImg={widthImg}
gridColumn={gridColumn}
flexDirection={flexDirection}
paddingLeftContent={paddingLeftContent}
paddingTopContent={paddingTopContent}
paddingBottomTitle={paddingBottomTitle}
paddingBlockFooter={paddingBlockFooter}
key={card.id}
>
<CardFactory entry={card} />
</BlogCard>
);
});

return <BlogGrid>{cards}</BlogGrid>;
};

export default BlogEntries;
105 changes: 105 additions & 0 deletions src/components/UI/blog-entries/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import styled from "styled-components";
import {
Card,
CardContent,
CardImg,
CardTitle,
CardFooter,
} from "../card/styles";
import { card } from "../../../constants/card.config";

const BlogGrid = styled.div`
display: grid;
grid-column-gap: 3%;
grid-row-gap: 15px;
grid-template-rows: auto;

/* Small devices (landscape phones, 320px and up) */
@media (min-width: 320px) {
& {
grid-template-columns: 1fr;
}
}

/* Extra arge devices (extra large desktops, 1201px and up) */
@media (min-width: 1201px) {
& {
grid-template-columns: auto 45% auto;
}
}
`;
const BlogCard = styled.div`
grid-row: ${(props) => props.gridRow};
grid-column: ${(props) => props.gridColumn};

& > ${Card} {
flex-direction: ${(props) => props.flexDirection};
}

& ${CardContent} {
padding-left: ${(props) => props.paddingLeftContent}em;
}

/* Small devices (landscape phones, 320px and up) */
@media (min-width: 320px) {
& {
grid-area: auto;
}

& > ${Card} {
flex-direction: column;
}

& ${CardContent} {
padding-left: 0;
}
}

/* Extra large devices (extra large desktops, 1201px and up) */
@media (min-width: 1201px) {
& {
grid-row: ${(props) => props.gridRow};
grid-column: ${(props) => props.gridColumn};
}

& > ${Card} {
flex-direction: ${(props) => props.flexDirection} !important;
}

& ${CardContent} {
padding-left: ${(props) => props.paddingLeftContent}em !important;
padding-top: ${(props) => props.paddingTopContent}em !important;
}

& ${CardImg} {
width: ${(props) => props.widthImg} !important;
}
}

/* large devices (large desktops, 768px and up) */
@media (min-width: 768px) {
& > ${Card} {
flex-direction: row;
}

& ${CardContent} {
padding-left: 1em;
padding-top: 0;
}

& ${CardImg} {
width: ${card.blog.viewport_img_height}em;
background-position: left center;
}

& ${CardTitle} {
padding-bottom: ${(props) => props.paddingBottomTitle}em;
}

& ${CardFooter} {
padding-block: ${(props) => props.paddingBlockFooter}em;
}
}
`;

export { BlogGrid, BlogCard };
87 changes: 87 additions & 0 deletions src/components/UI/blog-entries/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { card } from "../../../constants/card.config";

const loop = (states, pos, cb) => states[pos].map(cb);

const getDistribution = (cardsLength) => {
const states = [
[0, 0, 0],
[0, 1, 0],
[1, 1, 0],
[1, 1, 1],
];
const jumpRelation = [1, 2, 1];
const statePosition = cardsLength % states.length;
const stateMultiplier = Math.trunc(cardsLength / states.length);

return {
inLength: () =>
loop(states, statePosition, (column, pos) => {
return column + jumpRelation[pos] * stateMultiplier;
}),
inRange: () => {
let endRange = 0;
let maxColumnSize = 0;
return loop(states, statePosition, (column, pos) => {
maxColumnSize = column + jumpRelation[pos] * stateMultiplier;
endRange += maxColumnSize;
return [endRange - maxColumnSize, endRange];
});
},
};
};

class BlogCardStyle {
constructor({
gridRow,
widthImg,
gridColumn,
flexDirection,
paddingLeftContent,
paddingTopContent,
paddingBottomTitle,
paddingBlockFooter,
}) {
this.gridRow = gridRow;
this.widthImg = widthImg;
this.gridColumn = gridColumn;
this.flexDirection = flexDirection;
this.paddingLeftContent = paddingLeftContent;
this.paddingTopContent = paddingTopContent;
this.paddingBottomTitle = paddingBottomTitle;
this.paddingBlockFooter = paddingBlockFooter;
}
}

const getStyles = (dataLength) => {
let styles = [];
const distribution = getDistribution(dataLength).inLength();

distribution.forEach((maxColumnSize, pos) => {
const columnStart = pos + 1;
const columnEnd = pos + 2;
const isMiddle = pos !== 0 && pos !== distribution.length - 1;

for (let index = 0; index < maxColumnSize; index++) {
const rowStart = isMiddle ? index + 1 : 2 * index + 1;
const rowEnd = isMiddle ? index + 2 : rowStart + 2;

styles = [
...styles,
new BlogCardStyle({
gridRow: `${rowStart} / ${rowEnd}`,
widthImg: isMiddle ? `${card.blog.viewport_img_height}em` : "initial",
gridColumn: `${columnStart} / ${columnEnd}`,
flexDirection: isMiddle ? "row" : "column",
paddingLeftContent: Number(isMiddle),
paddingTopContent: isMiddle ? "initial" : 1,
paddingBottomTitle: isMiddle ? 0.5 : 1,
paddingBlockFooter: isMiddle ? 0.5 : 1,
}),
];
}
});

return styles;
};

export { getStyles };
72 changes: 72 additions & 0 deletions src/components/UI/card/card-design.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from "react";
import PropTypes from "prop-types";
import {
Card,
CardImg,
CardBody,
CardContent,
CardTitle,
CardSubtitle,
DescriptionTitle,
CardDescription,
ReadMoreLink,
CardFooter,
FooterLine,
} from "./styles";

export const CardDesign = ({ data, optionalData, styles }) => {
const {
id,
img,
title,
subtitle,
description,
description_title,
url_entry,
} = data;
const optDataKeys = Object.keys(optionalData);
const hasOptData = optDataKeys.length > 0;
const printSubtitle = subtitle && (
<CardSubtitle fontSize={styles.subtitle_size} as="h6">
{subtitle}
</CardSubtitle>
);
const printFooterLines = optDataKeys.map((name, index) => (
<FooterLine pos={index} key={name}>
{optionalData[name]}
</FooterLine>
));

return (
<Card bgColor={styles.bg_color} allPadding={styles.padding}>
<CardImg bgImg={img} maxHeight={styles.viewport_img_height}></CardImg>
<CardBody>
<CardContent>
<CardTitle
fontSize={styles.title_size}
paddingBottom={styles.spacing}
>
{title}
</CardTitle>
{printSubtitle}
<CardDescription>
<DescriptionTitle>{description_title}:</DescriptionTitle>{" "}
{description}{" "}
</CardDescription>
<ReadMoreLink to={url_entry} color={styles.link_color}>
Leer más
</ReadMoreLink>
{hasOptData && <CardFooter>{printFooterLines}</CardFooter>}
</CardContent>
</CardBody>
</Card>
);
};

CardDesign.propTypes = {
data: PropTypes.object.isRequired,
optionalData: PropTypes.object,
styles: PropTypes.object.isRequired,
};

export default CardDesign;
Loading