Skip to content

Commit

Permalink
feat: slight redesign of landing page
Browse files Browse the repository at this point in the history
  • Loading branch information
corp-0 committed Oct 12, 2024
1 parent 0e2a740 commit 3e97d8b
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 57 deletions.
73 changes: 73 additions & 0 deletions app/(home)/HomeBannerClient.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
'use client';

import layoutChildren from "../../types/layoutChildren";
import {useEffect, useState} from "react";

const images: string[] = [
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/bar-engine.png",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/clowns.png",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/conveyor.jpg",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/df.jpg",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/go-outsid.png",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/honk.jpg",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/hugger.png",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/lemons.png",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/shuttlecrash.png",
"https://unitystationfile.b-cdn.net/Website-Statics/heroImages/chairs.jpg",
];

let currentIndex = 0;

const shuffleImages = () => {
for (let i = images.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[images[i], images[j]] = [images[j], images[i]];
}
};

const getNextImage = () => {
currentIndex = (currentIndex + 1) % images.length;
return images[currentIndex];
};

const HomeBannerClient = (props: layoutChildren) => {
const {children} = props;

const [image1, setImage1] = useState<string>(getNextImage());
const [image2, setImage2] = useState<string>(getNextImage());
const [showImage1, setShowImage1] = useState<boolean>(true);

useEffect(() => {
const intervalId = setInterval(() => {
setShowImage1(!showImage1);
if (showImage1) {
setImage2(getNextImage());
} else {
setImage1(getNextImage());
}
}, 10000);

return () => clearInterval(intervalId);
}, [showImage1]);


return (
<div className="relative w-full h-full p-32">
<div className="absolute inset-0 z-0 overflow-hidden">
<div
className={`absolute inset-0 bg-cover bg-center bg-no-repeat filter blur-xs transition-opacity duration-1000 ease-in-out ${showImage1 ? 'opacity-100' : 'opacity-0'}`}
style={{backgroundImage: `url(${image1})`, backgroundPosition: `center`}}></div>
<div
className={`absolute inset-0 bg-cover bg-center bg-no-repeat filter blur-xs transition-opacity duration-1000 ease-in-out ${showImage1 ? 'opacity-0' : 'opacity-100'}`}
style={{backgroundImage: `url(${image2})`, backgroundPosition: `center`}}></div>
<div className="absolute inset-0 bg-black opacity-50 "></div>
</div>
<div className="relative z-10">
{children}
</div>
</div>
)

}

export default HomeBannerClient;
128 changes: 86 additions & 42 deletions app/(home)/latestNews.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,122 @@
import {BlogPost} from "../../types/blogPost";
import classNames from "classnames";
import Container from "../common/uiLibrary/container";
import {toAgoTime} from "../../utils/timeUtils";
import PageSectionTitle from "../common/uiLibrary/pageSectionTitle";
import Button from "../common/uiLibrary/Button";

interface NewsCardProps {
interface PostPreviewCardProps {
post: BlogPost,
isMain?: boolean,
className?: string
}

interface LatestNewsProps {
posts: BlogPost[]
className?: string
}

const NewsCard = (props: NewsCardProps) => {
const {title, summary, socials_image, date_created, slug} = props.post;
const {className: classes} = props;
const isMain = props.isMain ?? false;
const PostPreviewImage = ({post, isMain = false, className}: PostPreviewCardProps) => {
const outerContainerStyles = classNames(
{'flex-1 overflow-hidden': isMain},
{'w-full xl:w-1/3 overflow-hidden rounded-lg': !isMain},
)

const style = {
backgroundImage: `url(${socials_image})`,
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
backgroundBlendMode: 'multiply',
backgroundPosition: 'center',
}
const innerContainerStyles = classNames(
{'w-full h-32 lg:h-40': !isMain},
'overflow-hidden', 'rounded-lg',
{'h-full' : isMain}
)

return (
<div className={classNames(outerContainerStyles, {className})}>
<div className={innerContainerStyles}>
<img
src={post.socials_image}
alt={post.title}
className="w-full h-full object-cover transition-transform duration-300 ease-in-out transform group-hover:scale-105"
loading="lazy"
/>
</div>
</div>
)
}

const PostPreviewBody = ({post, isMain = false, className}: PostPreviewCardProps) => {
const truncateSummary = (text: string) => {
const maxChars = 100;

const truncateSummary = (summary: string, isMain: boolean) => {
if (isMain) {
return summary;
return text;
}
return text.length > maxChars ? text.slice(0, maxChars - 3) + '...' : text;
};

const styles = classNames(
'mt-4',
{'lg:mt-0 lg:ml-4 lg:flex-1': !isMain}

);

return summary.slice(0, 175) + '...';
}
const titleStyles = classNames(
{'text-xl': isMain},
{'text-l': !isMain},
'font-bold text-white-800 mb-2'
);

return (
<a href={`/blog/${slug}`} className={classNames('relative overflow-hidden', classes)}>
<div className="absolute inset-0 rounded-lg shadow-lg bg-gray-400" style={style}></div>
<div className="relative p-3 h-full flex flex-col justify-between">
<div>
<div
className={
classNames('text-2xl text-white leading-tight border-b hover:border-dashed hover:border-gray-500',
{'lg:text-5xl': isMain})}>{title}</div>
<div className="text-normal text-gray-300">
<span className=" pb-1">{toAgoTime(date_created)}</span>
</div>
</div>
<p className="">{truncateSummary(summary, isMain)}</p>
</div>
</a>
<div className={classNames(styles, {className})}>
<h3 className={titleStyles}>{post.title}</h3>
<p className="text-sm text-gray-600 mb-2">{new Date(post.date_created).toLocaleDateString()}</p>
<p className="text-gray-400">{truncateSummary(post.summary)}</p>
</div>
)
}

const PostPreviewCard = ({post, isMain}: PostPreviewCardProps) => {
const style = classNames(
'flex',
'flex-col',
'flex-1',
'hover:border-l hover:border-r hover:border-b hover:border-t hover:border-gray-700 hover:rounded-lg',
'group',
'mb-8 xl:mb-0',
{'xl:max-w-[600px]': isMain},
{'xl:max-w-[550px] xl:flex-row': !isMain},
);

return (
<a href={`/blog/${post.slug}`} className={style}>
<PostPreviewImage post={post} isMain={isMain} />
<PostPreviewBody post={post} isMain={isMain} />
</a>
);
};

const LatestNews = (props: LatestNewsProps) => {
const {posts} = props;
const {posts, className} = props;

return (
<>
<div className={className}>
<PageSectionTitle>Latest News</PageSectionTitle>
<Container>
<div className="flex flex-col sm:flex-col md:flex-col lg:flex-row gap-5">
<div className="w-full lg:w-1/2 flex flex-col">
<NewsCard post={posts[0]} isMain className="h-full" />
<div className="flex flex-col gap-6">
<div className="flex flex-col xl:flex-row gap-6 justify-center">
<PostPreviewCard post={posts[0]} isMain={true} className="flex flex-col"/>

<div className="flex flex-col justify-between gap-6 xl:gap-0">
{posts.slice(1).map((post) => (
<PostPreviewCard key={post.slug} post={post} isMain={false}/>
))}
</div>
</div>
<div className="w-full lg:w-1/2 flex flex-col gap-4">
{posts.slice(1).map((post, index) => (
<NewsCard key={index} post={post} className="h-auto flex-grow" />
))}
<div className="flex justify-end px-20">
<Button filled={false} >
Read More
</Button>
</div>
</div>
</Container>
</>
</div>
);
}

Expand Down
31 changes: 16 additions & 15 deletions app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,27 @@ const fetchLatestBlogPost = async (): Promise<BlogPost[]> => {
}

const HomePage = async () => {

const latestBlogPosts: BlogPost[] = await fetchLatestBlogPost();
const NoSsrHeroImageClient = dynamic(() => import('./HeroRandomImageClient'), {ssr: false});
const NoSsrHomebannerClient = dynamic(() => import('./HomeBannerClient'), { ssr: false });

return (
<>
<PageSection className="gap-16">
<NoSsrHeroImageClient>
<LandingText mainText={mainText} secondaryText={secondaryText}/>
<DownloadButtonClient/>
<LandingButtonsServer/>
</NoSsrHeroImageClient>
<FeaturesList features={features}/>
</PageSection>
<PageSection verticalCenter={false}>
<LatestNews posts={latestBlogPosts}/>
</PageSection>
<div className="flex flex-col justify-center gap-6">
<div className="flex-[1]">
<NoSsrHomebannerClient>
<LandingText mainText={mainText} secondaryText={secondaryText}/>
<DownloadButtonClient/>
<LandingButtonsServer/>
</NoSsrHomebannerClient>
</div>
<div className="flex-[1]">
<LatestNews posts={latestBlogPosts}/>
</div>
</div>

<ContactInformation/>
</>
)
}
);
};

export default HomePage;

0 comments on commit 3e97d8b

Please sign in to comment.