Add new home page

This commit is contained in:
DanieII 2024-09-14 20:25:54 +03:00
parent 9b090d212a
commit d668093240
21 changed files with 949 additions and 907 deletions

View File

@ -7,7 +7,7 @@
"contact": "Контакти"
},
"main": {
"date": "2-ри 3-ти",
"date": "2 3",
"monthYear": "Ноември 2024",
"titleLocation": "Иновативен форум \"Джон Атанасов\" София Тех Парк",
"countdownTimer": {
@ -26,6 +26,11 @@
"volunteers": "Присъединете се като доброволец",
"partners": "Подкрепете събитието като партньор"
},
"news": {
"title": "Новини",
"cardButton": "Прочети",
"button": "Виж всички"
},
"partners": {
"sponsors": "Sponsors",
"media": "Media partners"
@ -39,4 +44,4 @@
"contactDirections": "Ако имате въпроси, предложения или желаете да се включите в OpenFest 2024, пишете ни:",
"copyright": "Някои права запазени."
}
}
}

View File

@ -8,24 +8,29 @@
},
"main": {
"date": "2 - 3",
"monthYear": "November 2024",
"monthYear": "November, 2024",
"titleLocation": "Innovation forum \"John Atanasoff\" Sofia Tech Park",
"countdownTimer": {
"title": "Until OpenFest remain:",
"title": "OpenFest starts in:",
"days": "Days",
"hours": "Hours",
"minutes": "Minutes"
},
"description": {
"title": "What is OpenFest?",
"title": "What is OpenFest...",
"text": "OpenFest is the biggest Bulgarian conference dedicated to the free culture, free knowledge sharing, free and open-source software. The event is organized by volunteers and is free to attend. OpenFest is held annually in Sofia, Bulgaria."
},
"cfp": {
"title": "How to participate in OpenFest 2024",
"title": "How to participate in OpenFest 2024?",
"lecture": "Take part with a lecture, a workshop or a booth",
"volunteers": "Join us as a volunteer",
"partners": "Support the event as a partner"
},
"news": {
"title": "News",
"cardButton": "Read",
"button": "See all"
},
"partners": {
"sponsors": "Sponsors",
"media": "Media partners"
@ -39,4 +44,4 @@
"contactDirections": "If you have any questions and suggestions or if you would like to participate in OpenFest 2024, get in touch with us:",
"copyright": "Some rights reserved."
}
}
}

1167
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@
"@types/react": "^18.3.5",
"@types/react-dom": "^18",
"autoprefixer": "^10.4.20",
"eslint": "^8.57.0",
"eslint": "^9.10.0",
"eslint-config-next": "^14.2.8",
"install": "^0.13.0",
"npm": "^10.8.3",
@ -39,4 +39,4 @@
"tailwindcss": "^3.4.10",
"typescript": "^5.5.4"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
public/posts/post-1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/posts/post-2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/posts/post-3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -1,7 +1,6 @@
import { Inter } from 'next/font/google';
import { i18n } from '../../../i18n-config';
import NavBar from '@/components/NavBar';
import NavBar from '../../components/NavBar';
import Footer from '@/components/Footer';
import '@/styles/globals.css';
@ -10,8 +9,6 @@ export async function generateStaticParams() {
return i18n.locales.map((locale) => ({ lang: locale }));
}
const inter = Inter({ subsets: ['latin'] });
export const metadata = {
title: 'OpenFest 2024',
description: 'Да се видим на OpenFest 2024!',
@ -21,12 +18,12 @@ export default function RootLayout({ children, params }) {
return (
<html lang={params.lang}>
<body
className={`${inter.className} flex min-h-screen flex-col text-white md:text-lg lg:text-xl`}
className={`flex min-h-screen flex-col font-openSans text-white md:text-lg lg:text-xl`}
>
<header>
<NavBar lang={params.lang} />
</header>
{children}
<main>{children}</main>
<Footer lang={params.lang} />
</body>
</html>

View File

@ -1,104 +1,88 @@
import CountDownTimer from '@/components/CountDownTimer';
import NewsFeed from '@/components/NewsFeed';
import Partners from '@/components/Partners';
// import { getSortedPostsData } from '../../lib/posts';
import Image from 'next/image';
import { getDictionary } from '@/dictionaries';
export default async function Home({ params }) {
const { lang } = params;
const dictionary = await getDictionary(lang);
// const { posts } = await getSortedPostsData(lang);
return (
<>
<section>
<div className='bg-gradient-to-r from-sky-500 to-indigo-500'>
<div className='mx-auto max-w-2xl py-32 sm:py-48 lg:py-56'>
<div className='text-center'>
<h1 className='text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl'>
{dictionary.main.date}
</h1>
<h2 className='text-gray-900'>{dictionary.main.monthYear}</h2>
<p className='mt-6 text-lg leading-8 text-gray-600'>
{dictionary.main.titleLocation}
</p>
{/* <div className='mt-10 flex items-center justify-center gap-x-6'>
<a
href='#'
className='rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'
>
Get started
</a>
<a
href='#'
className='text-sm font-semibold leading-6 text-gray-900'
>
Learn more <span aria-hidden='true'></span>
</a>
</div> */}
<section className='h-[65vh] bg-home-bg bg-cover sm:h-[75vh]'>
<div className='container flex h-full flex-col justify-center gap-10 text-black sm:gap-16'>
<div className='text-center'>
<p className='text-xl sm:text-3xl'>{dictionary.main.monthYear}</p>
<h1 className='text-8xl font-semibold leading-none sm:text-[9rem]'>
{dictionary.main.date}
</h1>
</div>
<div className='text-center'>
<p className='pb-2 text-2xl font-semibold sm:pb-4 sm:text-5xl'>
Lets share the freedom!
</p>
<p className='text-xl sm:text-3xl'>
{dictionary.main.titleLocation}
</p>
</div>
</div>
</section>
<CountDownTimer props={dictionary.main.countdownTimer} />
<section className='bg-blue-8'>
<div className='container flex flex-col gap-4 sm:gap-8'>
<h2 className='text-center text-2xl text-blue-2 sm:text-4xl'>
{dictionary.main.description.title}
</h2>
<div className='flex flex-col gap-6 sm:flex-row'>
<div className='flex-1'>
<p> {dictionary.main.description.text}</p>
</div>
<div className='flex-1'>
<Image
src='/images/openfest-2.webp'
width='620'
height='380'
></Image>
</div>
</div>
</div>
</section>
<CountDownTimer props={dictionary.main.countdownTimer} />
<section className='bg-[#E2EFFE] px-24 py-12'>
<h2 className='pb-16 text-center text-[2.2rem] text-[#004394]'>
{dictionary.main.description.title}
</h2>
<div className='flex-col md:flex md:flex-row'>
<div className='mx-2 text-center text-[#004394]'>
{dictionary.main.description.text}
</div>
<div className='mx-2 text-center text-[#004394]'>
{dictionary.main.description.text}
<section>
<div className='container'>
<h2 className='pb-4 text-center text-2xl text-blue-2 sm:pb-8 sm:text-4xl'>
{dictionary.main.cfp.title}
</h2>
<div className='flex flex-col gap-4 sm:flex-row sm:gap-8'>
<div className='flex basis-1/3 flex-col items-center justify-center gap-3 rounded-xl bg-blue-2 p-6 sm:gap-6'>
<div className='flex h-20 w-20 items-center justify-center rounded-full bg-blue-8 text-4xl text-blue-2 sm:h-24 sm:w-24 sm:text-5xl'>
<i className='fa-solid fa-lightbulb'></i>
</div>
<p className='text-center text-white'>
{dictionary.main.cfp.lecture}
</p>
</div>
<div className='flex basis-1/3 flex-col items-center justify-center gap-3 rounded-xl bg-blue-2 p-6 sm:gap-6'>
<div className='flex h-20 w-20 items-center justify-center rounded-full bg-blue-8 text-4xl text-blue-2 sm:h-24 sm:w-24 sm:text-5xl'>
<i className='fa-solid fa-helmet-safety'></i>
</div>
<p className='text-center text-white'>
{dictionary.main.cfp.volunteers}
</p>
</div>
<div className='flex basis-1/3 flex-col items-center justify-center gap-3 rounded-xl bg-blue-2 p-6 sm:gap-6'>
<div className='flex h-20 w-20 items-center justify-center rounded-full bg-blue-8 text-4xl text-blue-2 sm:h-24 sm:w-24 sm:text-5xl'>
<i className='fa-solid fa-handshake-angle'></i>
</div>
<p className='text-center text-white'>
{dictionary.main.cfp.partners}
</p>
</div>
</div>
</div>
</section>
<section>
<h2 className='pb-16 text-center text-[2.2rem] text-[#004394]'>
{dictionary.main.cfp.title}
</h2>
{/* <dl className='mt-5 grid grid-cols-1 gap-5 sm:grid-cols-3'> */}
<dl className='mt-5 grid grid-cols-1 place-items-center gap-1 sm:grid-cols-3'>
<div className='max-w-[350px] overflow-hidden rounded-lg bg-[#004394] px-4 py-5 text-center shadow sm:p-6'>
<dt className='truncate text-sm font-medium text-[#004394]'>
<div className='m-auto mb-2 flex h-20 w-20 items-center justify-center rounded-full bg-[#C8E0FC] text-[2.3rem]'>
<i className='fa-solid fa-lightbulb'></i>
</div>
</dt>
<dd className='mt-1 text-[22px] font-semibold text-[#F2F5F9]'>
{dictionary.main.cfp.lecture}
</dd>
</div>
<div className='max-w-[350px] overflow-hidden rounded-lg bg-[#004394] px-4 py-5 text-center shadow sm:p-6'>
<dt className='truncate text-sm font-medium text-[#004394]'>
<div className='m-auto mb-2 flex h-20 w-20 items-center justify-center rounded-full bg-[#C8E0FC] text-[2.3rem]'>
<i className='fa-solid fa-helmet-safety'></i>
</div>
</dt>
<dd className='mt-1 text-[22px] font-semibold text-[#F2F5F9]'>
{dictionary.main.cfp.volunteers}
</dd>
</div>
<div className='max-w-[350px] overflow-hidden rounded-lg bg-[#004394] px-4 py-6 text-center shadow sm:p-6'>
<dt className='truncate text-sm font-medium text-[#004394]'>
<div className='m-auto mb-2 flex h-20 w-20 items-center justify-center rounded-full bg-[#C8E0FC] text-[2.3rem]'>
<i className='fa-solid fa-handshake-angle'></i>
</div>
</dt>
<dd className='mt-1 text-[22px] font-semibold text-[#F2F5F9]'>
{dictionary.main.cfp.partners}
</dd>
</div>
</dl>
</section>
<main>
<NewsFeed />
<Partners props={lang} />
</main>
<NewsFeed lang={lang} />
<Partners lang={lang} />
</>
);
}

View File

@ -8,8 +8,9 @@ const CountDownTimer = ({ props }) => {
useEffect(() => {
const targetDate = new Date('2024-11-02T09:30:00+03:00');
const countDownIntervalTime = 1000;
const interval = setInterval(() => {
const updateCountDown = () => {
const now = new Date();
const diff = targetDate.getTime() - now.getTime();
@ -22,51 +23,66 @@ const CountDownTimer = ({ props }) => {
const m = Math.floor((diff / (1000 * 60)) % 60);
setMinutes(m);
}, 1000);
};
// Set time
updateCountDown();
// Set interval
const interval = setInterval(updateCountDown, countDownIntervalTime);
return () => clearInterval(interval);
}, []);
return (
<section className='m-12 mb-20 pt-6'>
{/* <span className='mb-12 mt-4 block text-3xl text-black'>
{props.title}
</span> */}
<div className='flex justify-evenly'>
<div className='relative h-[256px] w-[256px]'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-1/2'></div>
<div className='absolute left-0 top-0 h-full w-1/2 bg-[#C8E0FC]'></div>
<section>
<div className='container flex flex-col gap-4 sm:gap-8'>
<h2 className='text-center text-2xl text-blue-2 sm:text-start sm:text-4xl'>
{props.title}
</h2>
<div className='flex flex-col items-center justify-evenly gap-8 lg:flex-row'>
<div className='relative h-40 w-40 lg:h-64 lg:w-64'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-1/2'></div>
<div className='absolute left-0 top-0 h-full w-1/2 bg-[#C8E0FC]'></div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold text-gray-800'>
<p className='pb-1 pt-2 text-5xl lg:pb-3 lg:pt-4 lg:text-8xl'>
{days}
</p>
<p className='text-xl font-light lg:text-5xl'> {props.days}</p>
</span>
</div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold text-gray-800'>
<p className='pb-[38px] pt-[14px] text-[85px]'>{days}</p>
<p className='text-[36px] font-light'> {props.days}</p>
</span>
<div className='relative h-40 w-40 lg:h-64 lg:w-64'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-full'></div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold text-gray-800'>
<p className='pb-1 pt-2 text-5xl lg:pb-3 lg:pt-4 lg:text-8xl'>
{hours}
</p>
<p className='text-xl font-light lg:text-5xl'> {props.hours}</p>
</span>
</div>
</div>
</div>
<div className='relative h-[256px] w-[256px]'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-1/2'></div>
<div className='absolute left-0 top-0 h-full w-1/2 bg-[#C8E0FC]'></div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold text-gray-800'>
<p className='pb-[38px] pt-[14px] text-[85px]'>{hours}</p>
<p className='text-[36px] font-light'> {props.hours}</p>
</span>
</div>
</div>
<div className='relative h-[256px] w-[256px]'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-1/2'></div>
<div className='absolute left-0 top-0 h-full w-1/2 bg-[#C8E0FC]'></div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold text-gray-800'>
<p className='pb-[38px] pt-[14px] text-[85px]'>{minutes}</p>
<p className='text-[36px] font-light'> {props.minutes}</p>
</span>
<div className='relative h-40 w-40 lg:h-64 lg:w-64'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-1/2'></div>
<div className='absolute right-0 top-0 h-full w-1/2 bg-[#C8E0FC]'></div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold text-gray-800'>
<p className='pb-1 pt-2 text-5xl lg:pb-3 lg:pt-4 lg:text-8xl'>
{minutes}
</p>
<p className='text-xl font-light lg:text-5xl'>
{props.minutes}
</p>
</span>
</div>
</div>
</div>
</div>

View File

@ -35,71 +35,53 @@ const Navbar = async ({ lang }) => {
return (
<>
<nav className='my-6 bg-white'>
<div className='mx-auto flex max-w-screen-xl flex-wrap items-center justify-between p-4'>
<a
href='https://openfest.org/'
className='flex items-center space-x-3 rtl:space-x-reverse'
>
<nav className='container flex flex-col items-center justify-between gap-4 bg-white text-black sm:flex-row'>
<div>
<a href='https://openfest.org/' className='flex items-center'>
<Image src={OpenFestLogo} alt='OpenFest Logo' width={256} />
</a>
{/* <button
data-collapse-toggle='navbar-default'
type='button'
class='inline-flex h-10 w-10 items-center justify-center rounded-lg p-2 text-sm text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 md:hidden dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600'
aria-controls='navbar-default'
aria-expanded='false'
>
<span class='sr-only'>Open main menu</span>
<svg
class='h-5 w-5'
aria-hidden='true'
xmlns='http://www.w3.org/2000/svg'
fill='none'
viewBox='0 0 17 14'
>
<path
stroke='currentColor'
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='2'
d='M1 1h15M1 7h15M1 13h15'
/>
</svg>
</button> */}
<div className='hidden w-full md:block md:w-auto' id='navbar-default'>
<ul className='mt-4 flex flex-col font-medium text-[#0B1C30] md:mt-0 md:flex-row md:space-x-8 md:border-0 md:bg-white md:p-0 rtl:space-x-reverse'>
<li>
<a href='#' className='' aria-current='page'>
{dictionary.nav.home}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.about}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.partners}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.archive}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.contact}
</a>
</li>
<li>
<LanguageSwitcher lang={lang} />
</li>
</ul>
</div>
</div>
<div className='flex items-center justify-center'>
<ul className='flex flex-wrap items-center justify-center gap-4 sm:gap-8'>
<li>
<a href='#' className='' aria-current='page'>
{dictionary.nav.home}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.about}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.partners}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.archive}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.contact}
</a>
</li>
<li>
<LanguageSwitcher lang={lang} />
</li>
</ul>
</div>
{
//<div className='mx-auto flex max-w-screen-xl flex-wrap items-center justify-between p-4'>
// <div
// className='hidden w-full md:block md:w-auto'
// id='navbar-default'
// >
// // </div>
//</div>
}
</nav>
</>
);

View File

@ -1,137 +1,50 @@
import Image from 'next/image';
import { getDictionary } from '@/dictionaries';
import { getSortedPostsData } from '@/lib/posts';
const posts = [
{
title: 'Boost your conversion rate',
href: '#',
category: { name: 'Article', href: '#' },
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Architecto accusantium praesentium eius, ut atque fuga culpa, similique sequi cum eos quis dolorum.',
date: 'Mar 16, 2020',
datetime: '2020-03-16',
imageUrl:
'https://images.unsplash.com/photo-1496128858413-b36217c2ce36?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1679&q=80',
readingTime: '6 min',
author: {
name: 'Roel Aufderehar',
href: '#',
imageUrl:
'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
},
{
title: 'How to use search engine optimization to drive sales',
href: '#',
category: { name: 'Video', href: '#' },
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit facilis asperiores porro quaerat doloribus, eveniet dolore. Adipisci tempora aut inventore optio animi., tempore temporibus quo laudantium.',
date: 'Mar 10, 2020',
datetime: '2020-03-10',
imageUrl:
'https://images.unsplash.com/photo-1547586696-ea22b4d4235d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1679&q=80',
readingTime: '4 min',
author: {
name: 'Brenna Goyette',
href: '#',
imageUrl:
'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
},
{
title: 'Improve your customer experience',
href: '#',
category: { name: 'Case Study', href: '#' },
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint harum rerum voluptatem quo recusandae magni placeat saepe molestiae, sed excepturi cumque corporis perferendis hic.',
date: 'Feb 12, 2020',
datetime: '2020-02-12',
imageUrl:
'https://images.unsplash.com/photo-1492724441997-5dc865305da7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1679&q=80',
readingTime: '11 min',
author: {
name: 'Daniela Metz',
href: '#',
imageUrl:
'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
},
];
const NewsFeed = async ({ lang }) => {
const dictionary = await getDictionary(lang);
const posts = await getSortedPostsData(lang);
const NewsFeed = () => {
return (
<div className='relative bg-gray-50 px-4 pb-20 pt-16 sm:px-6 lg:px-8 lg:pb-28 lg:pt-24'>
<div className='absolute inset-0'>
<div className='h-1/3 bg-white sm:h-2/3' />
</div>
<div className='relative mx-auto max-w-7xl'>
<div className='text-center'>
<h2 className='text-3xl font-extrabold tracking-tight text-gray-900 sm:text-4xl'>
From the blog
</h2>
<p className='mx-auto mt-3 max-w-2xl text-xl text-gray-500 sm:mt-4'>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Ipsa
libero labore natus atque, ducimus sed.
</p>
</div>
<div className='mx-auto mt-12 grid max-w-lg gap-5 lg:max-w-none lg:grid-cols-3'>
{posts.map((post) => (
<div
key={post.title}
className='flex flex-col overflow-hidden rounded-lg shadow-lg'
>
<div className='flex-shrink-0'>
<Image
className='h-48 w-full object-cover'
src={post.imageUrl}
alt=''
/>
</div>
<div className='flex flex-1 flex-col justify-between bg-white p-6'>
<div className='flex-1'>
<p className='text-sm font-medium text-indigo-600'>
<a href={post.category.href} className='hover:underline'>
{post.category.name}
</a>
</p>
<a href={post.href} className='mt-2 block'>
<p className='text-xl font-semibold text-gray-900'>
{post.title}
</p>
<p className='mt-3 text-base text-gray-500'>
{post.description}
</p>
<section className='bg-blue-8'>
<div className='container flex flex-col gap-4 sm:gap-8'>
<h2 className='text-center text-2xl text-blue-2 sm:text-start sm:text-4xl'>
{dictionary.main.news.title}
</h2>
<div className='flex flex-col gap-4 sm:flex-row sm:gap-8'>
{posts.map((post) => {
return (
<div
key={post.title}
className='flex basis-1/3 flex-col overflow-hidden rounded-xl shadow-xl'
>
<div>
<Image src={post.imageUrl} width='400' height='190'></Image>
</div>
<div className='flex h-full flex-1 flex-col gap-2 bg-white p-6 text-center sm:gap-4'>
<p className='text-blue-2'>{post.title}</p>
<p className='text-sm opacity-50'>{post.date}</p>
<a
href='#'
className='mx-auto mt-auto self-baseline rounded-3xl bg-blue-2 px-12 py-2'
>
{dictionary.main.news.cardButton}
</a>
</div>
<div className='mt-6 flex items-center'>
<div className='flex-shrink-0'>
<a href={post.author.href}>
<span className='sr-only'>{post.author.name}</span>
<Image
className='h-10 w-10 rounded-full'
src={post.author.imageUrl}
alt=''
/>
</a>
</div>
<div className='ml-3'>
<p className='text-sm font-medium text-gray-900'>
<a href={post.author.href} className='hover:underline'>
{post.author.name}
</a>
</p>
<div className='flex space-x-1 text-sm text-gray-500'>
<time dateTime={post.datetime}>{post.date}</time>
<span aria-hidden='true'>&middot;</span>
<span>{post.readingTime} read</span>
</div>
</div>
</div>
</div>
</div>
))}
);
})}
</div>
<a
href='#'
className='mt-4 flex items-center justify-center gap-4 self-center rounded-3xl bg-blue-2 px-12 py-2 sm:self-baseline'
>
{dictionary.main.news.button}
<i className='fa-solid fa-arrow-right'></i>
</a>
</div>
</div>
</section>
);
};

View File

@ -4,61 +4,57 @@ import { getDictionary } from '@/dictionaries';
const Partners = async ({ lang }) => {
const dictionary = await getDictionary(lang);
const sponsorLogos = ['logo-1', 'logo-2', 'logo-3', 'logo-4', 'logo-5'];
const mediaPartnerLogos = ['logo-1', 'logo-2', 'logo-3', 'logo-4', 'logo-5'];
console.log(lang);
const getShuffledLogos = (logos) => {
for (let i = logos.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[logos[i], logos[j]] = [logos[j], logos[i]];
}
return logos;
};
return (
<div className='my-14'>
<div className='lg:py-22 mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8'>
<p className='text-center text-base font-semibold uppercase tracking-wider text-gray-600'>
{dictionary.main.partners.media}
</p>
<div className='mt-6 grid grid-cols-2 gap-0.5 md:grid-cols-3 lg:mt-12'>
<div className='col-span-1 flex justify-center bg-gray-50 px-8 py-8'>
<Image
className='max-h-12'
src='https://tailwindui.com/img/logos/transistor-logo-gray-400.svg'
alt='Workcation'
/>
<section>
<div className='container flex flex-col gap-8 sm:gap-12'>
<div>
<h2 className='pb-4 text-center text-2xl text-blue-2 sm:pb-8 sm:text-4xl'>
{dictionary.main.partners.sponsors}
</h2>
<div className='flex flex-wrap justify-evenly gap-6'>
{getShuffledLogos(sponsorLogos).map((logo) => {
return (
<div
key={logo}
className='cursor-pointer opacity-50 hover:opacity-100'
>
<p>{logo}</p>
</div>
);
})}
</div>
<div className='col-span-1 flex justify-center bg-gray-50 px-8 py-8'>
<Image
className='max-h-12'
src='https://tailwindui.com/img/logos/mirage-logo-gray-400.svg'
alt='Mirage'
/>
</div>
<div className='col-span-1 flex justify-center bg-gray-50 px-8 py-8'>
<Image
className='max-h-12'
src='https://tailwindui.com/img/logos/tuple-logo-gray-400.svg'
alt='Tuple'
/>
</div>
<div className='col-span-1 flex justify-center bg-gray-50 px-8 py-8'>
<Image
className='max-h-12'
src='https://tailwindui.com/img/logos/laravel-logo-gray-400.svg'
alt='Laravel'
/>
</div>
<div className='col-span-1 flex justify-center bg-gray-50 px-8 py-8'>
<Image
className='max-h-12'
src='https://tailwindui.com/img/logos/statickit-logo-gray-400.svg'
alt='StaticKit'
/>
</div>
<div className='col-span-1 flex justify-center bg-gray-50 px-8 py-8'>
<Image
className='max-h-12'
src='https://tailwindui.com/img/logos/statamic-logo-gray-400.svg'
alt='Statamic'
/>
</div>
<div>
<h2 className='pb-4 text-center text-2xl text-blue-2 sm:pb-8 sm:text-4xl'>
{dictionary.main.partners.media}
</h2>
<div className='flex flex-wrap justify-evenly gap-6'>
{getShuffledLogos(mediaPartnerLogos).map((logo) => {
return (
<div
key={logo}
className='cursor-pointer opacity-50 hover:opacity-100'
>
<p>{logo}</p>
</div>
);
})}
</div>
</div>
</div>
</div>
</section>
);
};

View File

@ -6,6 +6,7 @@ import { i18n } from '../../i18n-config';
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import process from 'process';
async function getTruncatedPostContent(content) {
const words = content.split(' ');
@ -51,9 +52,7 @@ export const getSortedPostsData = cache(async (locale) => {
}
});
return {
posts: sortedPostsData,
};
return sortedPostsData;
});
export const getAllPosts = cache(async () => {

View File

@ -28,15 +28,16 @@ export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
// `/_next/` and `/api/` are ignored by the watcher, but we need to ignore files in `public` manually.
// If you have one
if (
[
'/manifest.json',
'/favicon.ico',
'/next.svg',
'/vercel.svg',
// Your other files in `public`
].includes(pathname)
)
const paths = [
'/manifest.json',
'/favicon.ico',
'/next.svg',
'/vercel.svg',
// Your other files in `public`
];
const dirs = ['/images/', '/posts/'];
if (paths.includes(pathname) || dirs.some((dir) => pathname.startsWith(dir)))
return;
// Check if there is any supported locale in the pathname

View File

@ -1,6 +1,7 @@
---
title: 'Bulgarian'
date: '08-06-2024'
imageUrl: '/posts/post-1.webp'
---
**Some** description

View File

@ -1,6 +1,7 @@
---
title: 'English'
date: '08-06-2024'
imageUrl: '/posts/post-1.webp'
---
**Some** description

View File

@ -1,8 +1,13 @@
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css');
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
.container {
@apply mx-auto w-full max-w-screen-xl px-6 py-8 sm:px-12 sm:py-10;
}
@layer base {
p {
@apply text-black;

View File

@ -4,17 +4,23 @@ const config: Config = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
fontFamily: {
openSans: ['Open Sans', 'sans-serif'],
},
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
'home-bg': "url('/images/openfest-1.webp')",
},
colors: {
'dark-blue': '#09021B',
'deep-blue': '#0F0429',
blue: '#2F1B5D',
'neon-green': '#34EAD8',
'neon-pink': '#D92ACE',
'blue-2': '#004394',
'blue-8': '#E2EFFE',
//'dark-blue': '#09021B',
//'deep-blue': '#0F0429',
//blue: '#2F1B5D',
//'neon-green': '#34EAD8',
//'neon-pink': '#D92ACE',
},
letterSpacing: {
max: '0.3em',