diff --git a/components/personal-card/PersonalCard.stories.tsx b/components/personal-card/PersonalCard.stories.tsx index 42c5367..c412b25 100644 --- a/components/personal-card/PersonalCard.stories.tsx +++ b/components/personal-card/PersonalCard.stories.tsx @@ -1,6 +1,6 @@ import { storiesOf } from '@storybook/react'; import PersonalCard from './PersonalCard'; -storiesOf('Components/Personal Card', module).add('with emoji', () => { +storiesOf('Components/Personal Card', module).add('static', () => { return ; }); diff --git a/components/personal-card/elements/ContactsButtons.tsx b/components/personal-card/elements/ContactsButtons.tsx index 14e9f77..2588e23 100644 --- a/components/personal-card/elements/ContactsButtons.tsx +++ b/components/personal-card/elements/ContactsButtons.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import '@fortawesome/fontawesome-svg-core'; import { faEnvelope } from '@fortawesome/free-solid-svg-icons'; import { - faTelegram, faTwitter, faGithub, faLinkedin, @@ -32,7 +31,7 @@ const ContactComp = ({ id, type }: Contact) => { return (
diff --git a/components/post-feed/PostFeed.stories.tsx b/components/post-feed/PostFeed.stories.tsx new file mode 100644 index 0000000..67722b1 --- /dev/null +++ b/components/post-feed/PostFeed.stories.tsx @@ -0,0 +1,56 @@ +import { storiesOf } from '@storybook/react'; +// import { DateTime } from 'luxon'; +// import PostOverviewCard, { PostOverviewCardProps } from './PostOverviewCard'; + +// storiesOf('Components/Post Overview Card', module) +// .add('static', () => { +// const defaultPreview: PostOverviewCardProps = { +// createdAt: DateTime.now(), +// createdBy: { +// name: 'fido_node', +// avatar: 'avatar.jpg' +// }, +// path: '/blog/asdasdasdasd', +// title: 'Awesome title', +// preview: {}, +// tags: [{ text: 'asdf' }, { text: 'ghjkl' }, { text: 'qwertyuioio' }] +// }; + +// return ; +// }) +// .add('with preview', () => { +// const defaultPreview: PostOverviewCardProps = { +// createdAt: DateTime.now(), +// createdBy: { +// name: 'fido_node', +// avatar: 'avatar.jpg' +// }, +// path: '/blog/asdasdasdasd', +// title: 'Awesome title', +// preview: { +// headerMedia: { +// key: 'Image', +// url: './pattern.png', +// alt: 'awesome pattern' +// } +// }, +// tags: [{ text: 'asdf' }, { text: 'ghjkl' }, { text: 'qwertyuioio' }] +// }; + +// return ; +// }) +// .add('without tags', () => { +// const defaultPreview: PostOverviewCardProps = { +// createdAt: DateTime.now(), +// createdBy: { +// name: 'fido_node', +// avatar: 'avatar.jpg' +// }, +// path: '/blog/asdasdasdasd', +// title: 'Awesome title', +// preview: {}, +// tags: [] +// }; + +// return ; +// }); diff --git a/components/post-feed/PostFeed.tsx b/components/post-feed/PostFeed.tsx new file mode 100644 index 0000000..834545d --- /dev/null +++ b/components/post-feed/PostFeed.tsx @@ -0,0 +1,8 @@ +import * as React from 'react'; +import { PostOverviewCardProps } from '../post-overview/PostOverviewCard'; + +export type PostFeedProps = { + posts: PostOverviewCardProps[]; +}; + +export default ({ posts }: PostFeedProps) =>
; diff --git a/components/post-overview/PostOverviewCard.stories.tsx b/components/post-overview/PostOverviewCard.stories.tsx new file mode 100644 index 0000000..922d165 --- /dev/null +++ b/components/post-overview/PostOverviewCard.stories.tsx @@ -0,0 +1,61 @@ +import { storiesOf } from '@storybook/react'; +import { DateTime } from 'luxon'; +import PostOverviewCard, { PostOverviewCardProps } from './PostOverviewCard'; + +storiesOf('Components/Post Overview Card', module) + .add('static', () => { + const defaultPreview: PostOverviewCardProps = { + createdAt: DateTime.now(), + createdBy: { + name: 'fido_node', + avatar: 'avatar.jpg' + }, + path: '/blog/asdasdasdasd', + title: ' The Ultimate Web Developer Resources List 🔥Awesome 200+ Resources', + preview: {}, + tags: [{ text: 'asdf' }, { text: 'ghjkl' }, { text: 'qwertyuioio' }] + }; + + return ; + }) + .add('with preview', () => { + const defaultPreview: PostOverviewCardProps = { + createdAt: DateTime.now(), + createdBy: { + name: 'fido_node', + avatar: 'avatar.jpg' + }, + path: '/blog/asdasdasdasd', + title: 'How to create your personal static blog and do not lost your mind. 🔥', + preview: { + headerMedia: { + key: 'Image', + url: './pattern.png', + alt: 'awesome pattern' + } + }, + tags: [ + { text: 'next.js' }, + { text: 'typescript' }, + { text: 'tailwind' }, + { text: 'storybook' } + ] + }; + + return ; + }) + .add('without tags', () => { + const defaultPreview: PostOverviewCardProps = { + createdAt: DateTime.now(), + createdBy: { + name: 'fido_node', + avatar: 'avatar.jpg' + }, + path: '/blog/asdasdasdasd', + title: ' The Ultimate Web Developer Resources List 🔥Awesome 200+ Resources', + preview: {}, + tags: [] + }; + + return ; + }); diff --git a/components/post-overview/PostOverviewCard.tsx b/components/post-overview/PostOverviewCard.tsx new file mode 100644 index 0000000..64355a2 --- /dev/null +++ b/components/post-overview/PostOverviewCard.tsx @@ -0,0 +1,50 @@ +import { DateTime } from 'luxon'; +import * as React from 'react'; +import { PostBody, Preview, Tag } from '../../src/posts/post'; +import { User } from '../../src/user/user'; +import { isDefined } from '../../src/util/types'; +import Avatar from './elements/Avatar'; +import NameAndData from './elements/NameAndData'; +import Share from './elements/Share'; +import Tags from './elements/Tags'; + +export type PostOverviewCardProps = { + createdAt: DateTime; + createdBy: User; + path: string; + title: string; + preview: Preview; + tags: Tag[]; +}; + +export default ({ createdBy, createdAt, title, tags, path, preview }: PostOverviewCardProps) => ( +
+ {isDefined(preview.headerMedia) ? ( + {preview.headerMedia.alt} + ) : null} + +
+ + +
+
+ + {title} + +
+ {tags.length > 0 ? ( +
+ +
+ ) : null} + +
+ +
+ +
+
+); diff --git a/components/post-overview/elements/Avatar.tsx b/components/post-overview/elements/Avatar.tsx new file mode 100644 index 0000000..79ba545 --- /dev/null +++ b/components/post-overview/elements/Avatar.tsx @@ -0,0 +1,9 @@ +import * as React from 'react'; + +type Props = { + imgUrl: string; +}; + +export default ({ imgUrl }: Props) => ( + +); diff --git a/components/post-overview/elements/NameAndData.tsx b/components/post-overview/elements/NameAndData.tsx new file mode 100644 index 0000000..d440ab4 --- /dev/null +++ b/components/post-overview/elements/NameAndData.tsx @@ -0,0 +1,16 @@ +import { DateTime } from 'luxon'; +import * as React from 'react'; + +type Props = { + name: string; + date: DateTime; +}; + +export default ({ name, date }: Props) => ( +
+
{name}
+
+ {date.toLocaleString({ month: 'long', day: 'numeric' })} +
+
+); diff --git a/components/post-overview/elements/Share.tsx b/components/post-overview/elements/Share.tsx new file mode 100644 index 0000000..c179954 --- /dev/null +++ b/components/post-overview/elements/Share.tsx @@ -0,0 +1,31 @@ +import { DateTime } from 'luxon'; +import * as React from 'react'; + +import { faTwitter } from '@fortawesome/free-brands-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +const twitterShareLink = 'https://twitter.com/intent/tweet'; + +type Props = { + link: string; + text: string; +}; + +function buildTwitterShareLink(link: string, text: string): string { + return `${twitterShareLink}?text=${escape(text.slice(0, 279))}&url=${encodeURI(link)}`; +} + +export default ({ link, text }: Props) => { + const twitterUrl = buildTwitterShareLink(link, text); + return ( +
+
Share:
+ + + +
+ ); +}; diff --git a/components/post-overview/elements/Tags.tsx b/components/post-overview/elements/Tags.tsx new file mode 100644 index 0000000..533899d --- /dev/null +++ b/components/post-overview/elements/Tags.tsx @@ -0,0 +1,16 @@ +import * as React from 'react'; +import { Tag } from '../../../src/posts/post'; + +type Props = { + tags: Tag[]; +}; + +export default ({ tags }: Props) => ( +
+ {tags.map((t) => ( +
+ {'#' + t.text} +
+ ))} +
+); diff --git a/package.json b/package.json index 5f96af7..9d3feff 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "export": "next build && next export", "build": "next build", "start": "next start", - "storybook": "start-storybook -s ./public -p 6006 ", + "storybook": "start-storybook -s ./story-static -p 6006 ", "build-storybook": "build-storybook" }, "dependencies": { @@ -15,6 +15,9 @@ "@fortawesome/free-brands-svg-icons": "^5.15.3", "@fortawesome/free-solid-svg-icons": "^5.15.3", "@fortawesome/react-fontawesome": "^0.1.14", + "@types/luxon": "^1.26.5", + "install": "^0.13.0", + "luxon": "^1.26.0", "next": "^10.1.0", "react": "17.0.1", "react-dom": "17.0.1" diff --git a/src/posts/paging.ts b/src/posts/paging.ts new file mode 100644 index 0000000..dd717eb --- /dev/null +++ b/src/posts/paging.ts @@ -0,0 +1,4 @@ +export type Paging = { + totalPages: number; + currentPage: number; +}; diff --git a/src/posts/post.ts b/src/posts/post.ts new file mode 100644 index 0000000..5b337d4 --- /dev/null +++ b/src/posts/post.ts @@ -0,0 +1,39 @@ +import { DateTime } from 'luxon'; +import { User } from '../user/user'; + +export type Post = { + createdAt: DateTime; + createdBy: User; + title: string; + preview: Preview; + tags: Tag[]; + postBody: PostBody; +}; + +export type Preview = { + readTime?: number; + headerMedia?: MediaElement; +}; + +export type Tag = { + text: string; +}; + +export type PostBody = { + elements: Element[]; +}; + +type Paragraph = { + key: 'Paragraph'; + text: string; +}; + +type Image = { + key: 'Image'; + url: string; + alt: string; +}; + +type MediaElement = Image; + +type Element = Paragraph | MediaElement; diff --git a/src/user/user.ts b/src/user/user.ts new file mode 100644 index 0000000..7065e90 --- /dev/null +++ b/src/user/user.ts @@ -0,0 +1,4 @@ +export type User = { + name: string; + avatar: string; +}; diff --git a/src/util/types.ts b/src/util/types.ts new file mode 100644 index 0000000..60d12d7 --- /dev/null +++ b/src/util/types.ts @@ -0,0 +1,3 @@ +export function isDefined(t: T | undefined | null): t is T { + return t != null && typeof t !== undefined; +} diff --git a/story-static/avatar.jpg b/story-static/avatar.jpg new file mode 100644 index 0000000..b79976a Binary files /dev/null and b/story-static/avatar.jpg differ diff --git a/story-static/favicon.ico b/story-static/favicon.ico new file mode 100644 index 0000000..a4b3e7f Binary files /dev/null and b/story-static/favicon.ico differ diff --git a/story-static/pattern.png b/story-static/pattern.png new file mode 100644 index 0000000..e20f33a Binary files /dev/null and b/story-static/pattern.png differ diff --git a/yarn.lock b/yarn.lock index e46b1b4..49c3380 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2334,6 +2334,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== +"@types/luxon@^1.26.5": + version "1.26.5" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.26.5.tgz#843fb705e16e4d2a90847a351b799ea9d879859e" + integrity sha512-XeQxxRMyJi1znfzHw4CGDLyup/raj84SnjjkI2fDootZPGlB0yqtvlvEIAmzHDa5wiEI5JJevZOWxpcofsaV+A== + "@types/markdown-to-jsx@^6.11.3": version "6.11.3" resolved "https://registry.yarnpkg.com/@types/markdown-to-jsx/-/markdown-to-jsx-6.11.3.tgz#cdd1619308fecbc8be7e6a26f3751260249b020e" @@ -6237,6 +6242,11 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +install@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/install/-/install-0.13.0.tgz#6af6e9da9dd0987de2ab420f78e60d9c17260776" + integrity sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA== + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -7174,6 +7184,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +luxon@^1.26.0: + version "1.26.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.26.0.tgz#d3692361fda51473948252061d0f8561df02b578" + integrity sha512-+V5QIQ5f6CDXQpWNICELwjwuHdqeJM1UenlZWx5ujcRMc9venvluCjFb4t5NYLhb6IhkbMVOxzVuOqkgMxee2A== + make-dir@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"