Skip to content

Commit

Permalink
add other components
Browse files Browse the repository at this point in the history
  • Loading branch information
anshgoyalevil committed Mar 4, 2024
1 parent f56b729 commit 1c545fa
Show file tree
Hide file tree
Showing 6 changed files with 390 additions and 0 deletions.
133 changes: 133 additions & 0 deletions components/newsroom/FeaturedBlogPost.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import moment from 'moment';
import Link from 'next/link';
import TextTruncate from 'react-text-truncate';

import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading';
import { ParagraphTypeStyle } from '@/types/typography/Paragraph';

import AuthorAvatars from '../AuthorAvatars';
import Heading from '../typography/Heading';
import Paragraph from '../typography/Paragraph';

interface Author {
name: string;
photo: string;
link?: string;
}

interface FeaturedBlogPostProps {
post: {
type: string;
slug: string;
cover: string;
title: string;
excerpt: string;
authors: Author[];
date: string;
readingTime: number;
};
className?: string;
}

/**
* React component for rendering a featured blog post.
* @param {FeaturedBlogPostProps} props - The component props.
* @returns {JSX.Element} JSX element representing the featured blog post.
*/
export default function FeaturedBlogPost({ post, className = '' }: FeaturedBlogPostProps) {
let typeColors = ['bg-indigo-100', 'text-indigo-800'];

switch (post.type.toLowerCase()) {
case 'video':
typeColors = ['bg-pink-100', 'text-pink-800'];
break;
case 'marketing':
typeColors = ['bg-orange-100', 'text-orange-800'];
break;
case 'strategy':
typeColors = ['bg-green-100', 'text-green-800'];
break;
case 'communication':
typeColors = ['bg-teal-100', 'text-teal-800'];
break;
default:
}

return (
<div className={`rounded-lg ${className}`}>
<article className='h-full rounded-lg'>
<Link href={post.slug} passHref>
<a
className={'flex h-full cursor-pointer flex-col divide-y divide-gray-200 overflow-hidden rounded-lg border border-gray-200 shadow-md transition-all duration-300 ease-in-out hover:shadow-lg md:max-w-164 md:flex-row'}
data-testid='FeaturedBlogPostItem-Link'
>
<img
className='w-full object-cover md:w-56'
src={post.cover}
alt=''
data-testid='FeaturedBlogPostItem-Img'
/>
<div className='flex flex-1 flex-col justify-between border-none bg-white p-6 text-left'>
<div className='flex-1'>
<Paragraph typeStyle={ParagraphTypeStyle.sm} textColor='text-indigo-500'>
<span
className={`inline-flex items-center rounded-full px-3 py-0.5 ${typeColors[0]} ${typeColors[1]}`}
data-testid='FeaturedBlogPost-type'
>
{post.type}
</span>
</Paragraph>
<Link href={post.slug}>
<a className='block' data-testid='FeaturedBlog-title'>
<Heading level={HeadingLevel.h3} typeStyle={HeadingTypeStyle.smSemibold} className='mt-2'>
{post.title}
</Heading>
<Paragraph typeStyle={ParagraphTypeStyle.sm} className='mt-3'>
<TextTruncate element='span' line={2} text={post.excerpt} />
</Paragraph>
</a>
</Link>
</div>
<div className='mt-6 flex items-center'>
<div className='relative shrink-0' data-testid='FeaturedBlog-Authorimg'>
<AuthorAvatars authors={post.authors} />
</div>
<div className='ml-3'>
<Heading level={HeadingLevel.h3} typeStyle={HeadingTypeStyle.xsSemibold} textColor='text-gray-900'>
<span className='hover:underline' data-testid='FeaturedBlogPost-AuthorName'>
{post.authors
.map((author, index) => author.link ? (
<a
key={index}
data-alt={author.name}
href={author.link}
onClick={(e) => {
e.stopPropagation();
}}
target='_blank'
rel='noreferrer'
>
{author.name}
</a>
) : (
author.name
))
.reduce((prev, curr) => [prev, ' & ', curr].join(''))}
</span>
</Heading>
<Paragraph typeStyle={ParagraphTypeStyle.sm} className='flex'>
<time dateTime={post.date} data-testid='FeaturedBlogPost-date'>
{moment(post.date).format('MMMM D, YYYY')}
</time>
<span className='mx-1'>&middot;</span>
<span data-testid='FeaturedBlogPost-RT'>{post.readingTime} min read</span>
</Paragraph>
</div>
</div>
</div>
</a>
</Link>
</article>
</div>
);
}
117 changes: 117 additions & 0 deletions components/newsroom/Newsroom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { TwitterTimelineEmbed } from 'react-twitter-embed';

import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading';
import { ParagraphTypeStyle } from '@/types/typography/Paragraph';

import ArrowRight from '../icons/ArrowRight';
import Heading from '../typography/Heading';
import Paragraph from '../typography/Paragraph';
import TextLink from '../typography/TextLink';
import NewsroomArticle from './NewsroomArticle';
import NewsroomBlogPosts from './NewsroomBlogPosts';
import NewsroomYoutube from './NewsroomYoutube';

/**
* A component representing the newsroom section of AsyncAPI website.
* @returns {JSX.Element} The JSX element representing the newsroom section.
*/
export default function Newsroom() {
return (
<>
<div className='mt-12 text-center' data-testid='Newsroom-main'>
<Heading
level={HeadingLevel.h2}
typeStyle={HeadingTypeStyle.lg}
>
Latest Updates
</Heading>
<Paragraph typeStyle={ParagraphTypeStyle.md} className='mx-auto mt-5 max-w-2xl'>
Get a glimpse of latest news, events, and blog posts. Want to publish a blog post? We love community stories.
<TextLink href='https://github.com/asyncapi/website/issues/new?template=blog.md' target='_blank'>
Submit yours!
</TextLink>
</Paragraph>
</div>

<div className='my-20 -mr-2 flex-row lg:flex' data-testid='Newsroom-sub-div'>
<div className='pt-4 text-center lg:w-1/4 lg:text-left'>
<Heading level={HeadingLevel.h4} typeStyle={HeadingTypeStyle.mdSemibold}>
From the blog
</Heading>
<Paragraph typeStyle={ParagraphTypeStyle.md} className='mt-5'>
Check out these articles written by community members
</Paragraph>
<div className='my-5' data-testid='Newsroom-Blog-Link'>
<TextLink href='/blog' className='mt-5'>
Read all blog posts
<ArrowRight className='inline w-6' />
</TextLink>
</div>
</div>
<div className='lg:w-3/4' data-testid='Newsroom-Blog'>
<NewsroomBlogPosts />
</div>
</div>

<hr />

<div className='my-20 flex flex-col lg:flex-row'>
<div className='pt-4 text-center lg:w-1/4 lg:text-left'>
<Heading level={HeadingLevel.h4} typeStyle={HeadingTypeStyle.mdSemibold}>
Latest News
</Heading>
<Paragraph typeStyle={ParagraphTypeStyle.md} className='mt-5'>
Read about what people are <br /> saying about AsyncAPI
</Paragraph>
<div className='my-5' data-testid='Newsroom-Twitter-Link'>
<TextLink href='https://twitter.com/AsyncAPISpec' className='mt-4' target='_blank'>
Follow us on Twitter
<ArrowRight className='inline w-6' />
</TextLink>
</div>
</div>

<div className='w-full flex-row items-stretch justify-between md:flex lg:w-3/4'>
<div className='relative flex w-full flex-col overflow-y-auto md:w-1/2'>
<div className='min-h-0'>
<div className='md:t-0 md:b-0 md:l-0 md:r-0 size-full max-h-120 md:absolute'>
<NewsroomArticle />
</div>
</div>
</div>
<div className='w-full px-2 md:w-1/2 md:pl-4 md:pr-0'>
<div className='mx-auto mt-8 w-full rounded-xl shadow-md md:mt-0' data-testid='Newsroom-Twitter'>
<TwitterTimelineEmbed
sourceType='profile'
screenName='AsyncAPISpec'
options={{ tweetLimit: '2' }}
/>
</div>
</div>
</div>
</div>

<hr />

<div className='my-20 -mr-2 flex-row lg:flex'>
<div className='pt-4 text-center lg:w-1/4 lg:text-left'>
<Heading level={HeadingLevel.h4} typeStyle={HeadingTypeStyle.mdSemibold}>
Video & Live Streams
</Heading>
<Paragraph typeStyle={ParagraphTypeStyle.md} className='mt-5'>
Watch our latest videos and live streams on the AsyncAPI YouTube channel
</Paragraph>
<div className='my-5' data-testid='Newsroom-Youtube'>
<TextLink href='https://www.youtube.com/c/AsyncAPI' className='mt-4' target='_blank'>
Visit our YouTube channel
<ArrowRight className='inline w-6' />
</TextLink>
</div>
</div>
<div className='lg:w-3/4'>
<NewsroomYoutube />
</div>
</div>
</>
);
}
4 changes: 4 additions & 0 deletions components/newsroom/NewsroomArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ interface Article {
title: string;
}

/**
* Represents an article in the newsroom section.
* @returns {JSX.Element} The JSX element representing the newsroom article.
*/
const NewsroomArticle: React.FC = () => {
return (
<ul className='flex w-full flex-col gap-2 px-2 pb-4'>
Expand Down
62 changes: 62 additions & 0 deletions components/newsroom/NewsroomSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading';
import { ParagraphTypeStyle } from '@/types/typography/Paragraph';

import { getAllPosts } from '../../utils/api';
import { useTranslation } from '../../utils/i18n';
import Button from '../buttons/Button';
import Heading from '../typography/Heading';
import Paragraph from '../typography/Paragraph';
import FeaturedBlogPost from './FeaturedBlogPost';

/**
* Represents the Newsroom section component.
* @returns {JSX.Element} JSX representation of the component.
*/
export default function NewsroomSection() {
const { t } = useTranslation('common');

const posts = getAllPosts()
.blog.sort((i1, i2) => {
const i1Date = new Date(i1.date);
const i2Date = new Date(i2.date);

if (i1.featured && !i2.featured) return -1;
if (!i1.featured && i2.featured) return 1;

return i2Date.valueOf() - i1Date.valueOf();
})
.slice(0, 1);

return (
<div className='mt-12 justify-between lg:flex'>
<section className='relative mx-auto mt-10 w-fit lg:mt-4 lg:w-1/2' data-testid='NewsroomSection-Featured'>
<div className='absolute z-10 -mt-6'>
<Button
className='block border border-secondary-500 p-2 text-center text-secondary-500 shadow-md md:inline-block'
text={t('newsroomSection.newsroomFeaturedPost')}
bgClassName='bg-secondary-100'
/>
</div>
<FeaturedBlogPost post={posts[0]} />
</section>
<section
className='mt-5 lg:my-auto lg:ml-12 lg:w-1/2 lg:max-w-xl lg:text-left'
data-testid='NewsroomSection-main'
>
<Heading typeStyle={HeadingTypeStyle.mdSemibold} level={HeadingLevel.h3}>
{t('newsroomSection.title')}
</Heading>
<Paragraph typeStyle={ParagraphTypeStyle.lg} className='mt-5'>
{t('newsroomSection.description')}
</Paragraph>
<div className='mt-7'>
<Button
text={t('newsroomSection.newsroomBtn')}
href='/community/newsroom'
data-testid='NewsroomSection-Link'
/>
</div>
</section>
</div>
);
}
69 changes: 69 additions & 0 deletions components/newsroom/NewsroomYoutube.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { useState } from 'react';
import { A11y, Navigation } from 'swiper/modules';
import { Swiper, SwiperSlide } from 'swiper/react';

import videoData from '../../config/newsroom_videos.json';
import ArrowLeft from '../icons/ArrowLeft';
import ArrowRight from '../icons/ArrowRight';
import { checkLastSnapIndex, useSwiperRef } from './swiper';
import YouTubeCard from './YouTubeCard';

interface Props {
className?: string;
}

/**
* Newsroom Youtube component displays a Swiper carousel of YouTubeCard components.
* @param {Props} props - The props for the component.
* @returns {JSX.Element} - Rendered component.
*/
export default function NewsroomYoutube({ className = '' }: Props) {
const [nextEl, nextElRef] = useSwiperRef();
const [prevEl, prevElRef] = useSwiperRef();
const [current, setCurrent] = useState<number>(0);

const buttonClass = 'shadow-md rounded border mx-2 mb-2 focus:outline-none';

return (
<div className={`flex-col overflow-auto ${className}`} data-testid='NewsroomYoutube-main'>
<Swiper
modules={[Navigation, A11y]}
spaceBetween={8}
slidesPerView={1}
onSlideChange={(swiper) => setCurrent(swiper.snapIndex)}
navigation={{
prevEl,
nextEl
}}
breakpoints={{
640: {
slidesPerView: 2
}
}}
>
{videoData.map((video, index) => (
<SwiperSlide key={index}>
<YouTubeCard video={video} />
</SwiperSlide>
))}
</Swiper>

<div className='justify-content-center md:justify-content-start ml-2 flex flex-row'>
<button
ref={prevElRef}
className={`${buttonClass} ml-0 px-6 py-3 ${current === 0 ? 'cursor-not-allowed border-gray-200 bg-white text-gray-200' : 'border-secondary-500 bg-secondary-100 text-secondary-500 hover:bg-secondary-500 hover:text-white'}`}
data-testid='Youtube-Prev-button'
>
<ArrowLeft className='w-4' />
</button>
<button
ref={nextElRef}
className={`${buttonClass} px-4 py-1 ${checkLastSnapIndex(current) ? 'cursor-not-allowed border-gray-200 bg-white text-gray-200' : 'border-secondary-500 bg-secondary-100 text-secondary-500 hover:bg-secondary-500 hover:text-white'}`}
data-testid='Youtube-Next-button'
>
<ArrowRight className='w-8' />
</button>
</div>
</div>
);
}
Loading

0 comments on commit 1c545fa

Please sign in to comment.