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

View File

@ -8,24 +8,29 @@
}, },
"main": { "main": {
"date": "2 - 3", "date": "2 - 3",
"monthYear": "November 2024", "monthYear": "November, 2024",
"titleLocation": "Innovation forum \"John Atanasoff\" Sofia Tech Park", "titleLocation": "Innovation forum \"John Atanasoff\" Sofia Tech Park",
"countdownTimer": { "countdownTimer": {
"title": "Until OpenFest remain:", "title": "OpenFest starts in:",
"days": "Days", "days": "Days",
"hours": "Hours", "hours": "Hours",
"minutes": "Minutes" "minutes": "Minutes"
}, },
"description": { "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." "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": { "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", "lecture": "Take part with a lecture, a workshop or a booth",
"volunteers": "Join us as a volunteer", "volunteers": "Join us as a volunteer",
"partners": "Support the event as a partner" "partners": "Support the event as a partner"
}, },
"news": {
"title": "News",
"cardButton": "Read",
"button": "See all"
},
"partners": { "partners": {
"sponsors": "Sponsors", "sponsors": "Sponsors",
"media": "Media partners" "media": "Media partners"

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": "^18.3.5",
"@types/react-dom": "^18", "@types/react-dom": "^18",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"eslint": "^8.57.0", "eslint": "^9.10.0",
"eslint-config-next": "^14.2.8", "eslint-config-next": "^14.2.8",
"install": "^0.13.0", "install": "^0.13.0",
"npm": "^10.8.3", "npm": "^10.8.3",

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 { i18n } from '../../../i18n-config';
import NavBar from '@/components/NavBar'; import NavBar from '../../components/NavBar';
import Footer from '@/components/Footer'; import Footer from '@/components/Footer';
import '@/styles/globals.css'; import '@/styles/globals.css';
@ -10,8 +9,6 @@ export async function generateStaticParams() {
return i18n.locales.map((locale) => ({ lang: locale })); return i18n.locales.map((locale) => ({ lang: locale }));
} }
const inter = Inter({ subsets: ['latin'] });
export const metadata = { export const metadata = {
title: 'OpenFest 2024', title: 'OpenFest 2024',
description: 'Да се видим на OpenFest 2024!', description: 'Да се видим на OpenFest 2024!',
@ -21,12 +18,12 @@ export default function RootLayout({ children, params }) {
return ( return (
<html lang={params.lang}> <html lang={params.lang}>
<body <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> <header>
<NavBar lang={params.lang} /> <NavBar lang={params.lang} />
</header> </header>
{children} <main>{children}</main>
<Footer lang={params.lang} /> <Footer lang={params.lang} />
</body> </body>
</html> </html>

View File

@ -1,104 +1,88 @@
import CountDownTimer from '@/components/CountDownTimer'; import CountDownTimer from '@/components/CountDownTimer';
import NewsFeed from '@/components/NewsFeed'; import NewsFeed from '@/components/NewsFeed';
import Partners from '@/components/Partners'; import Partners from '@/components/Partners';
// import { getSortedPostsData } from '../../lib/posts'; import Image from 'next/image';
import { getDictionary } from '@/dictionaries'; import { getDictionary } from '@/dictionaries';
export default async function Home({ params }) { export default async function Home({ params }) {
const { lang } = params; const { lang } = params;
const dictionary = await getDictionary(lang); const dictionary = await getDictionary(lang);
// const { posts } = await getSortedPostsData(lang);
return ( return (
<> <>
<section> <section className='h-[65vh] bg-home-bg bg-cover sm:h-[75vh]'>
<div className='bg-gradient-to-r from-sky-500 to-indigo-500'> <div className='container flex h-full flex-col justify-center gap-10 text-black sm:gap-16'>
<div className='mx-auto max-w-2xl py-32 sm:py-48 lg:py-56'>
<div className='text-center'> <div className='text-center'>
<h1 className='text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl'> <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} {dictionary.main.date}
</h1> </h1>
<h2 className='text-gray-900'>{dictionary.main.monthYear}</h2> </div>
<p className='mt-6 text-lg leading-8 text-gray-600'> <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} {dictionary.main.titleLocation}
</p> </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> */}
</div>
</div> </div>
</div> </div>
</section> </section>
<CountDownTimer props={dictionary.main.countdownTimer} /> <CountDownTimer props={dictionary.main.countdownTimer} />
<section className='bg-blue-8'>
<section className='bg-[#E2EFFE] px-24 py-12'> <div className='container flex flex-col gap-4 sm:gap-8'>
<h2 className='pb-16 text-center text-[2.2rem] text-[#004394]'> <h2 className='text-center text-2xl text-blue-2 sm:text-4xl'>
{dictionary.main.description.title} {dictionary.main.description.title}
</h2> </h2>
<div className='flex-col md:flex md:flex-row'> <div className='flex flex-col gap-6 sm:flex-row'>
<div className='mx-2 text-center text-[#004394]'> <div className='flex-1'>
{dictionary.main.description.text} <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 className='mx-2 text-center text-[#004394]'>
{dictionary.main.description.text}
</div> </div>
</div> </div>
</section> </section>
<section> <section>
<h2 className='pb-16 text-center text-[2.2rem] text-[#004394]'> <div className='container'>
<h2 className='pb-4 text-center text-2xl text-blue-2 sm:pb-8 sm:text-4xl'>
{dictionary.main.cfp.title} {dictionary.main.cfp.title}
</h2> </h2>
{/* <dl className='mt-5 grid grid-cols-1 gap-5 sm:grid-cols-3'> */} <div className='flex flex-col gap-4 sm:flex-row sm:gap-8'>
<dl className='mt-5 grid grid-cols-1 place-items-center gap-1 sm:grid-cols-3'> <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='max-w-[350px] overflow-hidden rounded-lg bg-[#004394] px-4 py-5 text-center shadow sm:p-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'>
<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> <i className='fa-solid fa-lightbulb'></i>
</div> </div>
</dt> <p className='text-center text-white'>
<dd className='mt-1 text-[22px] font-semibold text-[#F2F5F9]'>
{dictionary.main.cfp.lecture} {dictionary.main.cfp.lecture}
</dd> </p>
</div> </div>
<div className='max-w-[350px] overflow-hidden rounded-lg bg-[#004394] px-4 py-5 text-center shadow sm:p-6'> <div className='flex basis-1/3 flex-col items-center justify-center gap-3 rounded-xl bg-blue-2 p-6 sm:gap-6'>
<dt className='truncate text-sm font-medium text-[#004394]'> <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'>
<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> <i className='fa-solid fa-helmet-safety'></i>
</div> </div>
</dt> <p className='text-center text-white'>
<dd className='mt-1 text-[22px] font-semibold text-[#F2F5F9]'>
{dictionary.main.cfp.volunteers} {dictionary.main.cfp.volunteers}
</dd> </p>
</div> </div>
<div className='max-w-[350px] overflow-hidden rounded-lg bg-[#004394] px-4 py-6 text-center shadow sm:p-6'> <div className='flex basis-1/3 flex-col items-center justify-center gap-3 rounded-xl bg-blue-2 p-6 sm:gap-6'>
<dt className='truncate text-sm font-medium text-[#004394]'> <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'>
<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> <i className='fa-solid fa-handshake-angle'></i>
</div> </div>
</dt> <p className='text-center text-white'>
<dd className='mt-1 text-[22px] font-semibold text-[#F2F5F9]'>
{dictionary.main.cfp.partners} {dictionary.main.cfp.partners}
</dd> </p>
</div>
</div>
</div> </div>
</dl>
</section> </section>
<main> <NewsFeed lang={lang} />
<NewsFeed /> <Partners lang={lang} />
<Partners props={lang} />
</main>
</> </>
); );
} }

View File

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

View File

@ -35,40 +35,14 @@ const Navbar = async ({ lang }) => {
return ( return (
<> <>
<nav className='my-6 bg-white'> <nav className='container flex flex-col items-center justify-between gap-4 bg-white text-black sm:flex-row'>
<div className='mx-auto flex max-w-screen-xl flex-wrap items-center justify-between p-4'> <div>
<a <a href='https://openfest.org/' className='flex items-center'>
href='https://openfest.org/'
className='flex items-center space-x-3 rtl:space-x-reverse'
>
<Image src={OpenFestLogo} alt='OpenFest Logo' width={256} /> <Image src={OpenFestLogo} alt='OpenFest Logo' width={256} />
</a> </a>
{/* <button </div>
data-collapse-toggle='navbar-default' <div className='flex items-center justify-center'>
type='button' <ul className='flex flex-wrap items-center justify-center gap-4 sm:gap-8'>
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> <li>
<a href='#' className='' aria-current='page'> <a href='#' className='' aria-current='page'>
{dictionary.nav.home} {dictionary.nav.home}
@ -99,7 +73,15 @@ const Navbar = async ({ lang }) => {
</li> </li>
</ul> </ul>
</div> </div>
</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> </nav>
</> </>
); );

View File

@ -1,137 +1,50 @@
import Image from 'next/image'; import Image from 'next/image';
import { getDictionary } from '@/dictionaries';
import { getSortedPostsData } from '@/lib/posts';
const posts = [ const NewsFeed = async ({ lang }) => {
{ const dictionary = await getDictionary(lang);
title: 'Boost your conversion rate', const posts = await getSortedPostsData(lang);
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 = () => {
return ( 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'> <section className='bg-blue-8'>
<div className='absolute inset-0'> <div className='container flex flex-col gap-4 sm:gap-8'>
<div className='h-1/3 bg-white sm:h-2/3' /> <h2 className='text-center text-2xl text-blue-2 sm:text-start sm:text-4xl'>
</div> {dictionary.main.news.title}
<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> </h2>
<p className='mx-auto mt-3 max-w-2xl text-xl text-gray-500 sm:mt-4'> <div className='flex flex-col gap-4 sm:flex-row sm:gap-8'>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Ipsa {posts.map((post) => {
libero labore natus atque, ducimus sed. return (
</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 <div
key={post.title} key={post.title}
className='flex flex-col overflow-hidden rounded-lg shadow-lg' className='flex basis-1/3 flex-col overflow-hidden rounded-xl shadow-xl'
> >
<div className='flex-shrink-0'> <div>
<Image <Image src={post.imageUrl} width='400' height='190'></Image>
className='h-48 w-full object-cover'
src={post.imageUrl}
alt=''
/>
</div> </div>
<div className='flex flex-1 flex-col justify-between bg-white p-6'> <div className='flex h-full flex-1 flex-col gap-2 bg-white p-6 text-center sm:gap-4'>
<div className='flex-1'> <p className='text-blue-2'>{post.title}</p>
<p className='text-sm font-medium text-indigo-600'> <p className='text-sm opacity-50'>{post.date}</p>
<a href={post.category.href} className='hover:underline'> <a
{post.category.name} href='#'
</a> className='mx-auto mt-auto self-baseline rounded-3xl bg-blue-2 px-12 py-2'
</p> >
<a href={post.href} className='mt-2 block'> {dictionary.main.news.cardButton}
<p className='text-xl font-semibold text-gray-900'>
{post.title}
</p>
<p className='mt-3 text-base text-gray-500'>
{post.description}
</p>
</a> </a>
</div> </div>
<div className='mt-6 flex items-center'> </div>
<div className='flex-shrink-0'> );
<a href={post.author.href}> })}
<span className='sr-only'>{post.author.name}</span> </div>
<Image <a
className='h-10 w-10 rounded-full' href='#'
src={post.author.imageUrl} className='mt-4 flex items-center justify-center gap-4 self-center rounded-3xl bg-blue-2 px-12 py-2 sm:self-baseline'
alt='' >
/> {dictionary.main.news.button}
<i className='fa-solid fa-arrow-right'></i>
</a> </a>
</div> </div>
<div className='ml-3'> </section>
<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>
</div>
</div>
); );
}; };

View File

@ -4,61 +4,57 @@ import { getDictionary } from '@/dictionaries';
const Partners = async ({ lang }) => { const Partners = async ({ lang }) => {
const dictionary = await getDictionary(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 ( return (
<div className='my-14'> <section>
<div className='lg:py-22 mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8'> <div className='container flex flex-col gap-8 sm:gap-12'>
<p className='text-center text-base font-semibold uppercase tracking-wider text-gray-600'> <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>
<div>
<h2 className='pb-4 text-center text-2xl text-blue-2 sm:pb-8 sm:text-4xl'>
{dictionary.main.partners.media} {dictionary.main.partners.media}
</p> </h2>
<div className='mt-6 grid grid-cols-2 gap-0.5 md:grid-cols-3 lg:mt-12'> <div className='flex flex-wrap justify-evenly gap-6'>
<div className='col-span-1 flex justify-center bg-gray-50 px-8 py-8'> {getShuffledLogos(mediaPartnerLogos).map((logo) => {
<Image return (
className='max-h-12' <div
src='https://tailwindui.com/img/logos/transistor-logo-gray-400.svg' key={logo}
alt='Workcation' className='cursor-pointer opacity-50 hover:opacity-100'
/> >
</div> <p>{logo}</p>
<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>
);
})}
</div> </div>
</div> </div>
</div> </div>
</section>
); );
}; };

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
--- ---
title: 'English' title: 'English'
date: '08-06-2024' date: '08-06-2024'
imageUrl: '/posts/post-1.webp'
--- ---
**Some** description **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://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 base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
.container {
@apply mx-auto w-full max-w-screen-xl px-6 py-8 sm:px-12 sm:py-10;
}
@layer base { @layer base {
p { p {
@apply text-black; @apply text-black;

View File

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