Add temporary website

This commit is contained in:
DanieII 2024-08-06 14:06:40 +03:00
parent 6337858ff4
commit a5d20bc436
28 changed files with 2469 additions and 174 deletions

View File

@ -1,4 +1,19 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
async redirects() {
return [
{
source: '/news',
destination: '/news/1',
permanent: true,
},
{
source: '/news/post',
destination: '/news/1',
permanent: true,
},
]
},
}
export default nextConfig;
export default nextConfig

1271
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,10 +10,15 @@
},
"dependencies": {
"@formatjs/intl-localematcher": "^0.5.4",
"gray-matter": "^4.0.3",
"negotiator": "^0.6.3",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"remark": "^15.0.1",
"remark-html": "^16.0.1",
"remark-parse": "^11.0.0",
"strip-markdown": "^6.0.0"
},
"devDependencies": {
"@types/negotiator": "^0.6.3",

View File

@ -1,33 +1,8 @@
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css');
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}
body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
.container {
@apply mx-auto px-6;
}

View File

@ -1,29 +1,37 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { i18n, type Locale } from "../../../i18n-config";
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import { i18n, type Locale } from '../../../i18n-config'
import NavBar from '../../components/NavBar'
import Footer from '../../components/Footer'
export async function generateStaticParams() {
return i18n.locales.map((locale) => ({ lang: locale }));
return i18n.locales.map((locale) => ({ lang: locale }))
}
const inter = Inter({ subsets: ["latin"] });
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
params
params,
}: Readonly<{
children: React.ReactNode;
params: { lang: Locale };
children: React.ReactNode
params: { lang: Locale }
}>) {
return (
<html lang={params.lang}>
<body className={inter.className}>{children}</body>
<body
className={`${inter.className}, flex flex-col text-white md:text-lg lg:text-xl min-h-screen`}
>
<NavBar lang={params.lang} />
{children}
<Footer />
</body>
</html>
);
)
}

View File

@ -0,0 +1,49 @@
import { getSortedPostsData, getAllPosts } from '../../../../lib/posts'
import News from '../../../../components/News'
import Social from '../../../../components/Social'
import Pagination from '../../../../components/Pagination'
const POSTS_PER_PAGE = 4
export default async function AllNews({ params }) {
const { lang } = params
const { posts } = await getSortedPostsData(lang)
const totalPages = Math.max(1, Math.floor(posts.length / POSTS_PER_PAGE))
const page = parseInt(params.page)
const startPost = (page - 1) * POSTS_PER_PAGE
const endPost = page * POSTS_PER_PAGE
const paginatedPosts = posts.slice(startPost, endPost)
return (
<>
<div className='bg-deep-blue py-16 text-center'>
<div className='container'>
<h1 className='text-4xl font-extrabold'>Новини от OpenFest</h1>
</div>
</div>
<div className='container py-10 text-black'>
<News posts={paginatedPosts} />
<Pagination baseUrl='/news' page={page} totalPages={totalPages} />
</div>
<Social />
</>
)
}
export async function generateStaticParams() {
const paths = []
const allPosts = await getAllPosts()
for (const [locale, currentPosts] of Object.entries(allPosts)) {
const totalPages = Math.max(
1,
Math.floor(currentPosts.length / POSTS_PER_PAGE)
)
Array.from({ length: totalPages }, (_, i) => {
paths.push({ params: { page: (i + 1).toString() }, locale })
})
}
return paths
}

View File

@ -0,0 +1,35 @@
import Social from '../../../../../components/Social'
import { getSortedPostsData, getAllPosts } from '../../../../../lib/posts'
import { notFound } from 'next/navigation'
export default async function NewsDetails({ params }) {
const { id, lang } = params
const { posts } = await getSortedPostsData(lang)
const post = posts.filter((post) => post.id === id).pop()
if (!post) notFound()
return (
<>
<div className='flex flex-col gap-4 container py-6 text-black'>
<p className='text-4xl font-extrabold'>{post.title}</p>
<p>{post.date}</p>
<div dangerouslySetInnerHTML={{ __html: post.content }}></div>
</div>
<Social />
</>
)
}
export async function generateStaticParams() {
const paths = []
const allPosts = await getAllPosts()
for (const [locale, currentPosts] of Object.entries(allPosts)) {
currentPosts.forEach((post) => {
paths.push({ id: post.id, lang: locale })
})
}
return paths
}

View File

@ -0,0 +1,3 @@
export default function NotFound() {
return <h1 className='text-black text-3xl text-center py-6'>404 Not Found</h1>
}

View File

@ -1,119 +1,36 @@
import Image from "next/image";
import Header from '../../components/Header'
import Info from '../../components/Info'
import JoinUs from '../../components/JoinUs'
import Social from '../../components/Social'
import News from '../../components/News'
import { getSortedPostsData } from '../../lib/posts'
import { getDictionary } from '../../../dictionaries'
import { Locale } from "../../../i18n-config";
import { Locale } from '../../../i18n-config'
export default async function Home({ params: { lang }, }: { params: { lang: Locale }; }) {
const dictionary = await getDictionary(lang);
export default async function Home({
params: { lang },
}: {
params: { lang: Locale }
}) {
const dictionary = await getDictionary(lang)
const { posts } = await getSortedPostsData(lang)
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
{dictionary.main.hello},
Get started by editing&nbsp;
<code className="font-mono font-bold">src/app/page.tsx</code>
</p>
<div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:size-auto lg:bg-none">
<a
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
By{" "}
<Image
src="/vercel.svg"
alt="Vercel Logo"
className="dark:invert"
width={100}
height={24}
priority
/>
</a>
<>
<Header />
<main>
<Info />
<JoinUs />
<div className='container flex flex-col py-8 lg:py-16 gap-8 lg:gap-16 text-black'>
<div className='flex flex-col'>
<h2 className='text-xl lg:text-3xl font-extrabold text-center mb-6 lg:mb-10'>
Новини
</h2>
<News posts={posts} />
</div>
</div>
</div>
<div className="relative z-[-1] flex place-items-center before:absolute before:h-[300px] before:w-full before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-full after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700 before:dark:opacity-10 after:dark:from-sky-900 after:dark:via-[#0141ff] after:dark:opacity-40 sm:before:w-[480px] sm:after:w-[240px] before:lg:h-[360px]">
<Image
className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
</div>
<div className="mb-32 grid text-center lg:mb-0 lg:w-full lg:max-w-5xl lg:grid-cols-4 lg:text-left">
<a
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className="mb-3 text-2xl font-semibold">
Docs{" "}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className="m-0 max-w-[30ch] text-sm opacity-50">
Find in-depth information about Next.js features and API.
</p>
</a>
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className="mb-3 text-2xl font-semibold">
Learn{" "}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className="m-0 max-w-[30ch] text-sm opacity-50">
Learn about Next.js in an interactive course with&nbsp;quizzes!
</p>
</a>
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className="mb-3 text-2xl font-semibold">
Templates{" "}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className="m-0 max-w-[30ch] text-sm opacity-50">
Explore starter templates for Next.js.
</p>
</a>
<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className="mb-3 text-2xl font-semibold">
Deploy{" "}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className="m-0 max-w-[30ch] text-balance text-sm opacity-50">
Instantly deploy your Next.js site to a shareable URL with Vercel.
</p>
</a>
</div>
</main>
);
<Social />
</main>
</>
)
}

155
src/components/Footer.jsx Normal file
View File

@ -0,0 +1,155 @@
import Link from 'next/link'
const Footer = () => {
return (
<footer className='mt-auto'>
<div className='bg-dark-blue pt-8 lg:pt-16 pb-6'>
<div className='container'>
<div className='flex items-center gap-4 mb-3'>
<div className='bg-blue w-14 h-14 lg:w-16 lg:h-16 p-1 rounded-full'>
<svg
className='fill-deep-blue'
width='100%'
height='100%'
viewBox='0 0 293 182'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M0 86.1918L18.5717 65.0594L66.4078 111.895C70.0214 108.957 74.1682 105.87 78.7001 102.753L48.1916 61.7055L65.8746 49.4475L93.4804 93.6119C101.863 89.0114 111.163 84.7374 121.353 81.4429L98.1307 8.48858L133.29 0L147.833 75.4772C153.401 74.8539 159 74.5274 164.627 74.5571L177.601 13.1484L203.104 19.0845L184.917 76.4566C204.2 79.9886 220.283 88.2397 233.168 98.5982L282.663 37.9315L293 47.7557L241.876 106.256C252.095 116.317 259.796 127.566 264.98 138.221L233.257 156.594C233.257 156.594 220.402 126.349 196.202 108.126C198.986 114.537 200.497 121.63 200.497 129.05C200.497 158.196 176.772 182 147.714 182C117.117 182 92.888 155.703 95.0206 125.34L122.004 128.605C118.361 142.05 128.55 155.941 142.916 155.941C154.764 155.941 164.598 146.205 164.598 134.215C164.598 102.308 128.402 94.5023 102.544 105.484C86.4605 112.34 73.5166 122.402 55.8039 136.084C37.7061 119.107 18.8679 102.783 0 86.1918Z'
/>
</svg>
</div>
<div>
<p className='text-xl lg:text-3xl font-extrabold uppercase'>
OpenFest
</p>
<p>2024</p>
</div>
</div>
<div className='flex flex-col lg:flex-row gap-6'>
<div className='basis-1/2'>
<p>
OpenFest е конференция, посветена на свободната култура,
свободния софтуер и софтуера с отворен код, свободното споделяне
на знания.
</p>
<div className='flex flex-col gap-4 my-4'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-calendar-days'></i>
</div>
2 и 3 ноември 2024 (събота и неделя)
</div>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-location-dot'></i>
</div>
Sofia Tech Park
</div>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-ticket'></i>
</div>
Вход свободен, без предварителна регистрация
</div>
</div>
</div>
<div className='basis-1/4'>
<p className='font-extrabold'>Свържете се</p>
<p>
Ако имате въпроси, предложения или желаете да се включите в
OpenFest 2024, пишете ни:
</p>
<div className='flex flex-col'>
<div className='flex items-center my-4'>
<div className='w-10 h-10 bg-neon-green text-black flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-envelope'></i>
</div>
<Link href='mailto:info@openfest.org'>info@openfest.org</Link>
</div>
</div>
</div>
<div className='flex flex-col gap-4 basis-1/4'>
<Link href='https://cfp.openfest.org/'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-neon-green text-black flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-lightbulb'></i>
</div>
Call for Participation
</div>
</Link>
<Link href='https://cfp.openfest.org/'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-neon-green text-black flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-helmet-safety'></i>
</div>
Call for Volunteers
</div>
</Link>
<Link href='https://cfp.openfest.org/'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-neon-green text-black flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-handshake-angle'></i>
</div>
Партньорство и спонсорство
</div>
</Link>
</div>
</div>
<div className='flex justify-center gap-4 mt-4'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a
href='https://www.youtube.com/@openfestbulgaria'
target='_blank'
>
<i className='fa-brands fa-youtube'></i>
</a>
</div>
<div className='text-blue text-4xl flex items-center justify-center rounded-full'>
<a
href='https://www.facebook.com/groups/6360369433'
target='_blank'
>
<i className='fa-brands fa-facebook'></i>
</a>
</div>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a href='https://twitter.com/openfestbg' target='_blank'>
<i className='fa-brands fa-x-twitter'></i>
</a>
</div>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a href='https://mastodon.social/@openfest' target='_blank'>
<i className='fa-brands fa-mastodon'></i>
</a>
</div>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a
href='https://www.instagram.com/openfestbulgaria'
target='_blank'
>
<i className='fa-brands fa-instagram'></i>
</a>
</div>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a
href='https://www.linkedin.com/company/openfest-bulgaria/'
target='_blank'
>
<i className='fa-brands fa-linkedin-in'></i>
</a>
</div>
</div>
<p className='text-center mt-5'>
&copy; 2024 OpenFest. Някои права са запазени.
</p>
</div>
</div>
</footer>
)
}
export default Footer

18
src/components/Header.jsx Normal file
View File

@ -0,0 +1,18 @@
import Chicken from './icons/Chicken'
const Header = () => {
return (
<header className='relative overflow-hidden pt-10 pb-16 sm:pt-16 sm:pb-24 lg:pt-16 lg:pb-44 bg-deep-blue'>
<div className='container flex flex-col gap-2 lg:gap-4 text-center'>
<p className='uppercase tracking-widest lg:tracking-max text-xl lg:text3xl z-10'>
2 - 3 Ноември 2024
</p>
<p className='font-extrabold text-4xl lg:text-8xl z-10'>OpenFest</p>
<p className='font-extrabold text-4xl lg:text-8xl z-10'>2024</p>
</div>
<Chicken className='fill-blue absolute inset-0 scale-1.3 -translate-y-10 sm:scale-125 lg:-translate-y-16' />
</header>
)
}
export default Header

59
src/components/Info.jsx Normal file
View File

@ -0,0 +1,59 @@
import Circle from './icons/Circle'
import Eye from './icons/Eye'
const Info = () => {
return (
<div className='bg-deep-blue'>
<div className='container'>
<div className='flex flex-col-reverse lg:flex-row gap-6 items-center py-8 lg:py-16'>
<div className='flex justify-center relative flex-1'>
<Circle className='w-2/5 md:w-1/2' />
<Eye className='absolute inset-0 translate-x-full w-2/5 md:translate-x-3/4 md:w-1/2' />
</div>
<div className='flex-1'>
<h2 className='font-extrabold text-xl lg:text-3xl'>
{' '}
Повече за OpenFest
</h2>
<p className='mt-4 mb-2'>
OpenFest e най-голямата българска конференция, посветена на
свободната култура, свободния софтуер и софтуера с отворен код,
свободното споделяне на знания фестивал на свободното
творчество.
</p>
<p>
Организаторите всякога се стараят да дадат поле за изява и на
свободното изкуство и свободното разпространение на знания.
</p>
</div>
</div>
</div>
<div className='bg-blue'>
<div className='container flex flex-col gap-2 items-center lg:gap-0 lg:flex-row lg:justify-between p-2'>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
1500+ посетители годишно
</p>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
40+ Лектора
</p>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
20+ Лекции
</p>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
20+ Работилници
</p>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
70+ Доброволеца
</p>
</div>
</div>
</div>
)
}
export default Info

155
src/components/JoinUs.jsx Normal file
View File

@ -0,0 +1,155 @@
import Link from 'next/link'
import BackToTheSource from './icons/BackToTheSource'
export default function JoinUs() {
return (
<div className='container flex flex-col pt-8 lg:pt-16 gap-8 lg:gap-16'>
<div className='flex flex-col-reverse text-black lg:flex-row gap-6 items-center'>
<div className='flex-1'>
<h2 className='font-extrabold text-xl lg:text-3xl'>
Станете част от OpenFest 2024
</h2>
<p className='mt-4 mb-2'>
Фестът е оживен двудневен празник на всичко с отворен код, който
събира ентусиасти, разработчици и новатори. Независимо дали сте
опитен професионалист или начинаещ, OpenFest предлага уникална
възможност да се потопите в света на отворените технологии и
съвместното творчество във всички измерения.
</p>
<div className='flex flex-col gap-2 mt-4'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3 text-white min-w-10'>
<i className='fa-solid fa-calendar-days'></i>
</div>
2 и 3 ноември 2024 (събота и неделя)
</div>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3 text-white min-w-10'>
<i className='fa-solid fa-location-dot'></i>
</div>
Sofia Tech Park
</div>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3 min-w-10 text-blue'>
<i className='fa-solid fa-location-dot'></i>
</div>
Вход свободен, без предварителна регистрация
</div>
</div>
</div>
<div className='flex justify-center relative flex-1'>
<BackToTheSource />
</div>
</div>
<div className='flex flex-col text-black lg:flex-row gap-6 items-center'>
<div className='flex flex-col gap-4 items-center center relative flex-1'>
<div className='flex items-center justify-center bg-blue rounded-full p-4 text-5xl w-24 h-24 lg:text-7xl lg:w-36 lg:h-36'>
<i className='fa-regular fa-lightbulb text-neon-pink'></i>
</div>
<h2 className='font-extrabold text-3xl text-center'>
Предложете
<br />
идея
</h2>
</div>
<div className='flex-1'>
<p className='mb-2'>
Представете лекция, уъркшоп или щанд. Приемаме предложения до 1
септември 2024 г
</p>
<p>Тази година направленията са:</p>
<ul>
<li>
<strong>Advanced Technical</strong> За технически лекции с
по-голяма сложност.
</li>
<li>
<strong>Technical</strong> Това е мястото да разкажете какво
ново сте открили през годината, което би било полезно и разбираемо
и за начинаещи.
</li>
<li>
<strong>OpenArt</strong> Свободата да твориш под Creative
Commons и свободното изкуство във всичките му форми.
</li>
<li>
<strong>Общност и социален</strong> Отворени общности,
образование и управление, свободни лицензи, как човек може да се
изхранва с хобито си и др.
</li>
</ul>
<div className='flex justify-center mt-4'>
<Link
href='https://cfp.openfest.org/'
className='bg-neon-green px-16 py-4 rounded-md'
>
Предложете идея
</Link>
</div>
</div>
</div>
<div className='flex flex-col-reverse text-black lg:flex-row gap-6 items-center'>
<div className='flex-1'>
<p>
OpenFest се организира и провежда изцяло от доброволци. Тази година
отново се надяваме да срещнем нови съмишленици и приятели, да
създадем вълнуващо събитие. Можете да се включите в екипите: Мрежа;
Логистика; Аудио и видео; Медия, уебсайт и дизайн; Хералди;
Рецепция.
</p>
<p className='mt-4'>
Повече за тях можете да прочетете във формата за кандидатстване.
</p>
<div className='flex justify-center mt-4'>
<Link
href='https://cfp.openfest.org/'
className='bg-neon-green px-16 py-4 rounded-md'
>
Кандидатствайте
</Link>
</div>
</div>
<div className='flex flex-col gap-4 items-center center relative flex-1'>
<div className='flex items-center justify-center bg-blue rounded-full p-4 text-5xl w-24 h-24 lg:text-7xl lg:w-36 lg:h-36'>
<i className='fa-solid fa-helmet-safety text-neon-pink'></i>
</div>
<h2 className='font-extrabold text-3xl text-center'>
Станете
<br />
доброволец
</h2>
</div>
</div>
<div className='flex flex-col text-black lg:flex-row gap-6 items-center'>
<div className='flex flex-col gap-4 items-center center relative flex-1'>
<div className='flex items-center justify-center bg-blue rounded-full p-4 text-5xl w-24 h-24 lg:text-7xl lg:w-36 lg:h-36'>
<i className='fa-solid fa-handshake-angle text-neon-pink'></i>
</div>
<h2 className='font-extrabold text-3xl text-center'>
Подкрепете <br /> събитието като <br /> партньор
</h2>
</div>
<div className='flex-1'>
<p>
OpenFest се организира и провежда изцяло от доброволци. Тази година
отново се надяваме да срещнем нови съмишленици и приятели, да
създадем вълнуващо събитие. Можете да се включите в екипите: Мрежа;
Логистика; Аудио и видео; Медия, уебсайт и дизайн; Хералди;
Рецепция.
</p>
<p className='mt-4'>
Повече за тях можете да прочетете във формата за кандидатстване.
</p>
<div className='flex justify-center mt-4'>
<Link
href='https://cfp.openfest.org/'
className='bg-neon-green px-16 py-4 rounded-md'
>
Кандидатствайте
</Link>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,30 @@
'use client'
import Link from 'next/link'
import { i18n } from '../../i18n-config'
import { usePathname } from 'next/navigation'
export default function LocaleSwitcher({ lang }) {
const pathName = usePathname()
const { locales } = i18n
const otherLocale = locales?.find((cur) => cur !== lang)
function getRedirectPathName() {
if (!pathName) return '/'
const segments = pathName.split('/')
segments[1] = otherLocale
return segments.join('/')
}
return (
<Link
href={getRedirectPathName()}
locale={otherLocale}
className='flex justify-center items-center'
>
<i className='fa-solid fa-globe'></i>
</Link>
)
}

31
src/components/Navbar.jsx Normal file
View File

@ -0,0 +1,31 @@
import Logo from './icons/Logo'
import LanguageSwitcher from './LanguageSwitcher'
import Link from 'next/link'
const Navbar = ({ lang }) => {
return (
<nav className='bg-deep-blue'>
<div className='container flex flex-col items-center gap-6 lg:flex-row lg:justify-between py-6'>
<Link href='/' className='flex items-center gap-4'>
<div className='bg-blue w-14 h-14 lg:w-16 lg:h-16 p-1 rounded-full'>
<Logo className='fill-deep-blue' />
</div>
<div>
<p className='text-xl lg:text-3xl font-extrabold uppercase'>
OpenFest
</p>
<p>2024</p>
</div>
</Link>
<div className='flex w-full flex-wrap justify-center sm:justify-around lg:justify-end gap-6 gap-y-4 items-center font-semibold'>
<Link href='/news'>Новини</Link>
<Link href='https://cfp.openfest.org/'>Call for participation</Link>
<Link href='mailto:info@openfest.org'>Пишете ни</Link>
<LanguageSwitcher lang={lang} />
</div>
</div>
</nav>
)
}
export default Navbar

21
src/components/News.jsx Normal file
View File

@ -0,0 +1,21 @@
import Link from 'next/link'
export default function News({ posts }) {
return (
<div className='flex flex-wrap text-center gap-6 lg:text-left lg:gap-4 lg:gap-y-8'>
{posts.map((post) => (
<div key={post.id} className='flex flex-col gap-2 basis-24 flex-1'>
<p className='text-xl font-extrabold'>{post.title}</p>
<p>{post.date}</p>
<p>{post.truncatedContent}</p>
<Link href={`/news/post/${post.id}`}>
<p className='underline decoration-2 underline-offset-4 decoration-neon-green mt-auto'>
Прочетете
<i className='fa-solid fa-angle-right text-neon-green ml-1'></i>
</p>
</Link>
</div>
))}
</div>
)
}

View File

@ -0,0 +1,52 @@
import Link from 'next/link'
export default function Pagination({ baseUrl, page, totalPages }) {
return (
<div className='flex justify-center gap-6 text-black pt-6'>
<Link
href={`${baseUrl}/1`}
className='text-center border border-neon-green w-8 h-8 rounded-2xl hover:bg-neon-green'
>
<i className='fa-solid fa-angles-left'></i>
</Link>
{page > 1 ? (
<Link
href={`${baseUrl}/${page - 1}`}
className='text-center border border-neon-green w-8 h-8 rounded-2xl hover:bg-neon-green'
>
<i className='fa-solid fa-angle-left'></i>
</Link>
) : (
<></>
)}
{Array.from(Array(totalPages), (_, i) => {
const pageNumber = i + 1
return (
<Link
href={`${baseUrl}/${pageNumber}`}
key={pageNumber}
className={`text-center border border-neon-green w-8 h-8 rounded-2xl hover:bg-neon-green ${pageNumber === page ? 'bg-neon-green' : ''}`}
>
{pageNumber}
</Link>
)
})}
{page < totalPages ? (
<Link
href={`${baseUrl}/${page + 1}`}
className='text-center border border-neon-green w-8 h-8 rounded-2xl hover:bg-neon-green'
>
<i className='fa-solid fa-angle-right'></i>
</Link>
) : (
<></>
)}
<Link
href={`${baseUrl}/${totalPages}`}
className='text-center border border-neon-green w-8 h-8 rounded-2xl hover:bg-neon-green'
>
<i className='fa-solid fa-angles-right'></i>
</Link>
</div>
)
}

57
src/components/Social.jsx Normal file
View File

@ -0,0 +1,57 @@
const Social = () => {
return (
<div id='social' className='py-8 lg:pb-16 bg-deep-blue'>
<div className='container'>
<h2 className='font-extrabold text-center text-xl lg:text-3xl mb-6 lg:mb-12'>
Продължете разговора
</h2>
<div className='flex flex-wrap justify-center gap-10 md:gap-20 md:gap-y-12'>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-youtube'></i>
</div>
@openfestbulgaria
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-black w-12 h-12 md:w-16 md:h-16 rounded-full text-neon-green text-5xl md:text-6xl'>
<i className='fa-brands fa-facebook '></i>
</div>
@openfestbulgaria
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-x-twitter'></i>
</div>
OpenFestBG
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-instagram'></i>
</div>
openfestbulgaria
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-mastodon'></i>
</div>
@openfest
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-facebook-f'></i>
</div>
Facebook група: OpenFest
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-linkedin-in'></i>
</div>
openfest-bulgaria
</div>
</div>
</div>
</div>
)
}
export default Social

View File

@ -0,0 +1,196 @@
export default function BackToTheSource({ className }) {
return (
<svg
className={className}
width='100%'
fill='none'
viewBox='0 0 710 319'
xmlns='http://www.w3.org/2000/svg'
>
<path
d='M563.902 292.433C502.395 305.069 425.252 313.559 342.093 313.559C144.143 313.559 5.02502 265.455 5.02502 227.837'
stroke='#D92ACE'
strokeLinecap='round'
strokeWidth='10'
/>
<path
d='M703.912 227.837C703.912 241.271 683.012 256.043 647.124 269.484'
stroke='#D92ACE'
strokeLinecap='round'
strokeWidth='10'
/>
<path
d='M636.889 268.756L626.209 281.882C628.085 283.785 629.533 285.587 630.453 286.816C630.536 286.931 630.628 287.061 630.725 287.198C630.867 287.402 631.022 287.626 631.178 287.853C631.332 288.078 631.486 288.307 631.634 288.526C631.649 288.55 631.661 288.573 631.674 288.596C631.679 288.609 631.685 288.621 631.688 288.633C631.732 288.747 631.734 288.87 631.699 288.982C631.692 289.001 631.686 289.022 631.678 289.042C631.67 289.054 631.664 289.067 631.656 289.08C631.648 289.096 631.638 289.111 631.628 289.126C631.591 289.179 631.543 289.227 631.485 289.265L629.694 290.449L629.68 290.458L623.253 294.709C623.008 294.871 622.679 294.804 622.518 294.56L621.658 293.266C621.494 293.021 621.561 292.691 621.806 292.528L624.068 291.031C623.285 289.698 620.987 286.121 617.506 283.534C617.438 283.483 617.347 283.543 617.361 283.623C618.161 288.135 616.542 292.934 612.724 296.014C607.14 300.52 598.966 299.641 594.462 294.054C593.781 293.214 593.222 292.314 592.785 291.375C592.638 291.056 592.841 290.684 593.188 290.631L599.924 289.594C600.099 289.566 600.276 289.631 600.396 289.761C602.406 291.942 605.793 292.222 608.138 290.33C610.576 288.355 610.96 284.781 608.994 282.333C608.985 282.324 608.979 282.316 608.972 282.307C607.981 281.103 606.463 280.598 604.898 280.627C601.804 280.687 597.733 281.872 593.885 283.917C590.477 285.727 587.219 288.392 585.177 290.21C584.548 290.772 584.031 291.256 583.668 291.607C583.45 291.817 583.099 291.802 582.901 291.574L578.791 286.866L571.092 279.166C570.953 279.026 570.903 278.821 570.961 278.634L572.776 272.738C572.895 272.356 573.375 272.235 573.658 272.518L583.049 281.913C583.961 281.215 584.974 280.482 586.069 279.752L582.143 273.801C582.056 273.67 582.032 273.505 582.08 273.354L583.627 268.323C583.759 267.895 584.328 267.812 584.576 268.185L590.523 277.102C591.092 276.804 591.672 276.518 592.262 276.244C593.543 275.651 594.802 275.152 596.03 274.734L593.265 262.643C593.227 262.474 593.274 262.298 593.388 262.17L599.412 255.488C599.699 255.169 600.226 255.306 600.323 255.726L604.268 272.975C605.441 272.869 606.542 272.833 607.558 272.847L611.097 259.71C611.204 259.309 611.715 259.182 611.998 259.487L615.478 263.24C615.601 263.374 615.648 263.561 615.6 263.738L612.982 273.504C612.998 273.508 613.015 273.513 613.031 273.517C617.189 274.63 620.878 277.071 623.851 279.661L635.523 265.422C635.807 265.076 636.364 265.213 636.454 265.652C636.682 266.758 636.997 268.315 636.997 268.315C637.028 268.471 636.989 268.633 636.889 268.756Z'
fill='#D92ACE'
/>
<path
d='M631.634 288.526C631.486 288.307 631.332 288.078 631.178 287.853C631.023 287.626 630.867 287.401 630.725 287.198C630.735 287.209 630.743 287.22 630.751 287.232C631.029 287.63 631.347 288.098 631.634 288.526Z'
fill='#D92ACE'
/>
<path
d='M631.634 288.526C631.65 288.55 631.662 288.573 631.674 288.596C631.661 288.573 631.649 288.55 631.634 288.526Z'
fill='#D92ACE'
/>
<path
d='M631.7 288.981C631.734 288.869 631.732 288.747 631.689 288.633C631.734 288.747 631.736 288.869 631.7 288.981Z'
fill='#D92ACE'
/>
<path
d='M4.26318 179.068V173.831L40.1095 198.998V209.139L33.1999 207.054L40.1095 214.671V224.813L8.75892 202.802V182.225L4.26318 179.068ZM16.6344 192.806L26.2898 199.584L32.2339 200.586V198.705L16.6339 187.753L16.6344 192.806ZM16.6344 203.094L32.2345 214.047V212.166L26.2903 204.822L16.635 198.043L16.6344 203.094Z'
fill='#2F1B5D'
/>
<path
d='M44.8984 226.151L53.3013 208.784L49.0308 207.152V201.915L72.9646 211.059L83.4333 240.874L74.1351 237.321L71.5177 229.867L56.8481 224.263L54.2306 229.716L44.8984 226.151ZM58.983 219.843L69.3827 223.816L65.7323 213.534L62.6329 212.35L58.983 219.843Z'
fill='#2F1B5D'
/>
<path
d='M83.4746 220.236V214.999L125.788 226.289V235.804L116.492 231.995V229.045L98.0778 224.132V239.473L116.492 244.386V241.436L125.788 242.589V252.104L88.7817 242.229V221.652L83.4746 220.236Z'
fill='#2F1B5D'
/>
<path
d='M130.03 248.834V242.233L135.427 241.779V228.281L144.88 230.069V240.949L163.389 239.361V233.57L172.842 235.359V245.169L158.644 246.391L166.794 254.498L173.06 255.683V261.215L161.179 258.967L149.263 247.162L144.88 247.55V255.884L135.427 254.095V248.38L130.03 248.834Z'
fill='#2F1B5D'
/>
<path
d='M190.567 248.341V238.016L231.526 242.899V253.224L221.973 250.758V246.996L215.823 246.263V266.841L206.27 265.702V245.125L200.12 244.391V248.153L190.567 248.341Z'
fill='#2F1B5D'
/>
<path
d='M236.663 269.16V243.346L274.856 246.205V272.02L236.663 269.16ZM246.257 264.642L265.262 266.064V250.723L246.257 249.3V264.642Z'
fill='#2F1B5D'
/>
<path
d='M292.153 257.404V247.077L333.389 248.083V258.409L323.771 256.847V253.085L317.58 252.934V273.512L307.962 273.277V252.7L301.771 252.549V256.31L292.153 257.404Z'
fill='#2F1B5D'
/>
<path
d='M336.884 253.391V248.154L351.995 247.926V258.142L371.014 257.854V247.639L380.634 247.494V273.308L371.014 273.453V263.09L351.995 263.378V273.74L342.376 273.886V253.308L336.884 253.391Z'
fill='#2F1B5D'
/>
<path
d='M385.287 252.636V247.399L429.052 245.016V254.53L419.445 253.725V250.775L400.414 251.812V256.864L416.058 256.012V261.249L400.414 262.101V267.153L419.445 266.116V263.166L429.052 261.315V270.829L390.809 272.912V252.334L385.287 252.636Z'
fill='#2F1B5D'
/>
<path
d='M449.991 269.131V260.649L459.559 261.036V262.88L478.108 260.916V257.67L449.991 256.187V243.316L487.675 239.325V248.287L478.107 247.825V245.575L459.559 247.54V251.044L487.675 252.528V265.14L449.991 269.131Z'
fill='#2F1B5D'
/>
<path
d='M493.776 264.387V238.573L531.666 232.986V258.802L493.776 264.387ZM503.293 257.748L522.148 254.967V239.626L503.293 242.406V257.748Z'
fill='#2F1B5D'
/>
<path
d='M536.277 237.581V232.345L551.098 229.383V247.453L555.725 249.035L569.75 246.232V225.655L579.185 223.77V249.584L553.194 254.778L541.663 250.813V236.505L536.277 237.581Z'
fill='#2F1B5D'
/>
<path
d='M583.769 242.965V237.248L589.071 234.891V221.468L626.041 211.457V224.143L615.295 228.933L627.5 236.876L614.655 240.354L604.514 233.734L598.358 236.47V244.767L589.071 247.282V240.608L583.769 242.965ZM598.358 230.68L616.754 222.49V219.207L598.358 224.19V230.68Z'
fill='#2F1B5D'
/>
<path
d='M630.358 215.744V210.508L671.111 194.471V203.985L662.157 206.181V203.231L644.422 210.209V225.55L662.157 218.572V215.621L671.111 210.77V220.285L635.469 234.31V213.732L630.358 215.744Z'
fill='#2F1B5D'
/>
<path
d='M676.633 199.679V194.443L709.429 165.354V174.868L702.23 179.926V176.976L687.969 189.624V194.677L699.692 184.279V189.515L687.969 199.913V204.966L702.23 192.317V189.367L709.429 181.653V191.168L680.77 216.587V196.009L676.633 199.679Z'
fill='#2F1B5D'
/>
<path
d='M9.02502 88.5303V62.7158L41.509 42.4174V68.2319L9.02502 88.5303ZM17.1851 78.195L33.3485 68.0942V52.7533L17.1851 62.8535V78.195Z'
fill='#2F1B5D'
/>
<path
d='M46.16 61.7082V55.9184L51.3779 53.2808V39.2672L87.7623 27.3013V40.6512L60.5178 54.4421V62.0759L51.3779 65.0817V59.0706L46.16 61.7082ZM60.5178 48.6522L78.6224 39.4899V35.5441L60.5178 41.4979V48.6522Z'
fill='#2F1B5D'
/>
<path
d='M91.6941 31.5751V26.3386L134.507 16.9479V26.4623L125.109 27.1961V24.246L106.494 28.329V33.3815L121.796 30.025V35.2616L106.494 38.6185V43.6705L125.109 39.5875V36.6374L134.507 33.2484V42.7629L97.0955 50.9691V30.3912L91.6941 31.5751Z'
fill='#2F1B5D'
/>
<path
d='M140.397 41.7753V14.9285L168.735 26.5561V16.7833L165.639 17.2655V12.0289L178.242 10.0658V35.8803L170.192 37.1344L149.905 28.494V35.0583L153 34.5757V39.8122L140.397 41.7753Z'
fill='#2F1B5D'
/>
<path
d='M182.864 14.6865V9.44997L223.359 5.04932V14.3792L213.794 14.0909V11.3249L197.89 13.0534V19.9127L213.794 18.1842V23.4208L197.89 25.1493V33.6314L188.325 34.6704V14.093L182.864 14.6865Z'
fill='#2F1B5D'
/>
<path
d='M226.822 9.93122V4.69468L270.551 1.72705V11.2415L260.952 10.5655V7.61539L241.938 8.90557V13.958L257.569 12.8968V18.1333L241.938 19.194V24.2465L260.952 22.9563V20.0062L270.551 18.0271V27.5416L232.339 30.1348V9.55685L226.822 9.93122Z'
fill='#2F1B5D'
/>
<path
d='M276.363 27.2867V18.8052L285.978 19.8886V21.7326L304.62 21.1158V17.8708L276.363 14.3431V1.47275L314.237 0.220215V9.18137L304.621 8.02423V5.7744L285.979 6.39113V9.89453L314.237 13.4222V26.0342L276.363 27.2867Z'
fill='#2F1B5D'
/>
<path
d='M319.207 10.4932V0.167588L360.456 0V10.3256L350.834 9.03696V5.27521L344.642 5.30048V25.8784L335.02 25.9176V5.33967L328.827 5.36493V9.12669L319.207 10.4932Z'
fill='#2F1B5D'
/>
<path
d='M379.62 26.2487V13.747L408.609 10.3076V6.80416L389.234 6.04666V8.29597L379.62 9.39536V0.434204L418.223 1.94354V14.8139L389.234 18.2534V21.3881L408.609 22.1456V20.3016L418.223 19.2759V27.7581L379.62 26.2487Z'
fill='#2F1B5D'
/>
<path
d='M424.366 28.0948V2.28027L462.202 4.9612V30.7757L424.366 28.0948ZM433.963 19.5188L448.598 9.23448L433.963 8.19749V19.5188ZM437.971 23.822L452.606 24.859V13.5377L437.971 23.822Z'
fill='#2F1B5D'
/>
<path
d='M468.333 31.2975V18.7959L497.185 17.2582V13.7548L477.901 11.7261V13.9755L468.333 14.4442V5.48303L506.753 9.52478V22.3952L477.901 23.9324V27.0671L497.184 29.0957V27.2517L506.753 26.8567V35.3383L468.333 31.2975Z'
fill='#2F1B5D'
/>
<path
d='M511.534 32.4187V27.1451L546.994 13.6234V32.3203L552.612 33.1345V38.371L546.994 37.5568V41.0236L537.472 39.6437V36.1774L511.534 32.4187ZM523.791 28.9581L537.472 30.9409V23.7128L523.791 28.9581Z'
fill='#2F1B5D'
/>
<path
d='M10.4181 143.275V130.774L34.7318 142.034V138.531L18.4813 127.949V130.198L10.4176 126.423V117.461L42.7944 138.545V151.416L18.4807 140.156V143.29L34.7313 153.872V152.029L42.7944 155.878V164.36L10.4181 143.275Z'
fill='#2F1B5D'
/>
<path
d='M61.6609 161.07V155.833L85.6112 164.178V169.415L61.6609 161.07Z'
fill='#2F1B5D'
/>
<path
d='M104.358 185.272V176.311L113.724 179.986V182.235L132.241 186.585V184.703L125.207 179.88L116.989 177.95V172.713L125.207 174.644L132.241 173.124V171.244L113.724 166.894V169.143L104.358 168.419V159.458L141.608 168.206V178.348L133.39 179.183L141.608 183.879V194.02L104.358 185.272Z'
fill='#2F1B5D'
/>
<path
d='M162.992 198.026V171.179L191.346 191.526V181.754L188.248 181.284V176.048L200.858 177.962V203.777L192.804 202.553L172.504 187.671V194.235L175.602 194.705V199.942L162.992 198.026Z'
fill='#2F1B5D'
/>
<path
d='M207.132 204.55V178.736L245.229 182.681V208.495L207.132 204.55ZM216.702 200.304L235.659 202.267V186.926L216.702 184.963V200.304Z'
fill='#2F1B5D'
/>
<path
d='M249.683 188.319V183.083L262.194 183.841L272.643 201.55L283.019 185.104L293.138 185.718L277.242 210.569L267.897 210.001L255.166 188.652L249.683 188.319Z'
fill='#2F1B5D'
/>
<path
d='M326.036 212.885L334.629 200.477L335.095 199.804L334.524 199.216L323.852 188.271L328.549 187.878L339.79 199.409L330.734 212.493L326.036 212.885ZM324.031 214.051L331.283 213.443L341.072 199.302L328.931 186.848L321.925 187.435L321.81 187.601L333.812 199.911L324.025 214.046L324.031 214.051Z'
fill='#D92ACE'
/>
<path
d='M352.882 213.922L361.474 201.513L361.939 200.839L361.368 200.253L350.697 189.307L355.394 188.914L366.637 200.446L357.579 213.529L352.882 213.922ZM350.875 215.088L358.128 214.478L367.919 200.338L355.777 187.885L348.771 188.473L348.657 188.638L360.656 200.946L350.872 215.083L350.875 215.088Z'
fill='#D92ACE'
/>
<path
d='M378.256 214.32L386.847 201.911L387.313 201.238L386.742 200.651L376.07 189.704L380.767 189.312L392.01 200.843L382.953 213.925L378.256 214.32ZM376.248 215.485L383.502 214.877L393.292 200.736L381.15 188.284L374.144 188.87L374.03 189.035L386.031 201.345L376.244 215.481L376.248 215.485Z'
fill='#D92ACE'
/>
<path
d='M395.038 188.216L394.924 188.381L406.925 200.691L397.138 214.827L397.144 214.831L404.395 214.224L414.185 200.083L402.044 187.629L395.038 188.216Z'
fill='#D92ACE'
/>
<path
d='M414.462 186.724L414.347 186.89L426.348 199.199L416.561 213.336L416.566 213.34L423.817 212.732L433.607 198.591L421.466 186.139L414.462 186.724Z'
fill='#D92ACE'
/>
<path
d='M432.272 184.561L432.159 184.726L444.16 197.036L434.373 211.171L434.378 211.176L441.631 210.568L451.422 196.428L439.279 183.974L432.272 184.561Z'
fill='#D92ACE'
/>
</svg>
)
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,59 @@
export default function Circle({ className }) {
return (
<svg
className={className}
height='100%'
viewBox='0 0 473 472'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<g filter='url(#filter0_d_181_191)'>
<circle
cx='236.5'
cy='236'
r='166'
stroke='#2F1B5D'
strokeWidth='40'
shapeRendering='crispEdges'
/>
</g>
<defs>
<filter
id='filter0_d_181_191'
x='0.5'
y='0'
width='472'
height='472'
filterUnits='userSpaceOnUse'
colorInterpolationFilters='sRGB'
>
<feFlood floodOpacity='0' result='BackgroundImageFix' />
<feColorMatrix
in='SourceAlpha'
type='matrix'
values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'
result='hardAlpha'
/>
<feOffset />
<feGaussianBlur stdDeviation='25' />
<feComposite in2='hardAlpha' operator='out' />
<feColorMatrix
type='matrix'
values='0 0 0 0 0.773556 0 0 0 0 0.327778 0 0 0 0 0.983333 0 0 0 0.2 0'
/>
<feBlend
mode='normal'
in2='BackgroundImageFix'
result='effect1_dropShadow_181_191'
/>
<feBlend
mode='normal'
in='SourceGraphic'
in2='effect1_dropShadow_181_191'
result='shape'
/>
</filter>
</defs>
</svg>
)
}

View File

@ -0,0 +1,57 @@
export default function Eye({ className }) {
return (
<svg
className={className}
height='100%'
viewBox='0 0 485 337'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<g filter='url(#filter0_d_181_192)'>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M50.5 142.239L74.8397 114.72L137.533 175.709C142.269 171.883 147.703 167.864 153.643 163.805L113.659 110.353L136.834 94.3904L173.014 151.901C183.999 145.91 196.189 140.345 209.542 136.055L179.108 41.0538L225.187 30L244.247 128.286C251.545 127.475 258.882 127.049 266.257 127.088L283.26 47.1218L316.684 54.8518L292.849 129.562C318.12 134.161 339.199 144.906 356.085 158.394L420.952 79.3943L434.5 92.1874L367.498 168.366C380.891 181.468 390.984 196.116 397.777 209.992L356.202 233.916C356.202 233.916 339.354 194.532 307.639 170.801C311.288 179.149 313.267 188.387 313.267 198.049C313.267 236.003 282.173 267 244.092 267C203.991 267 172.237 232.756 175.032 193.218L210.396 197.469C205.622 214.978 218.976 233.066 237.803 233.066C253.331 233.066 266.219 220.388 266.219 204.774C266.219 163.226 218.781 153.061 184.892 167.361C163.813 176.289 146.849 189.391 123.635 207.209C99.9169 185.101 75.2279 163.844 50.5 142.239Z'
fill='#5C46B2'
/>
</g>
<defs>
<filter
id='filter0_d_181_192'
x='0.5'
y='0'
width='484'
height='337'
filterUnits='userSpaceOnUse'
colorInterpolationFilters='sRGB'
>
<feFlood floodOpacity='0' result='BackgroundImageFix' />
<feColorMatrix
in='SourceAlpha'
type='matrix'
values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'
result='hardAlpha'
/>
<feOffset dy='20' />
<feGaussianBlur stdDeviation='25' />
<feComposite in2='hardAlpha' operator='out' />
<feColorMatrix
type='matrix'
values='0 0 0 0 0.546065 0 0 0 0 0.5375 0 0 0 0 1 0 0 0 0.2 0'
/>
<feBlend
mode='normal'
in2='BackgroundImageFix'
result='effect1_dropShadow_181_192'
/>
<feBlend
mode='normal'
in='SourceGraphic'
in2='effect1_dropShadow_181_192'
result='shape'
/>
</filter>
</defs>
</svg>
)
}

View File

@ -0,0 +1,18 @@
export default function Logo({ className }) {
return (
<svg
className={className}
width='100%'
height='100%'
viewBox='0 0 293 182'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M0 86.1918L18.5717 65.0594L66.4078 111.895C70.0214 108.957 74.1682 105.87 78.7001 102.753L48.1916 61.7055L65.8746 49.4475L93.4804 93.6119C101.863 89.0114 111.163 84.7374 121.353 81.4429L98.1307 8.48858L133.29 0L147.833 75.4772C153.401 74.8539 159 74.5274 164.627 74.5571L177.601 13.1484L203.104 19.0845L184.917 76.4566C204.2 79.9886 220.283 88.2397 233.168 98.5982L282.663 37.9315L293 47.7557L241.876 106.256C252.095 116.317 259.796 127.566 264.98 138.221L233.257 156.594C233.257 156.594 220.402 126.349 196.202 108.126C198.986 114.537 200.497 121.63 200.497 129.05C200.497 158.196 176.772 182 147.714 182C117.117 182 92.888 155.703 95.0206 125.34L122.004 128.605C118.361 142.05 128.55 155.941 142.916 155.941C154.764 155.941 164.598 146.205 164.598 134.215C164.598 102.308 128.402 94.5023 102.544 105.484C86.4605 112.34 73.5166 122.402 55.8039 136.084C37.7061 119.107 18.8679 102.783 0 86.1918Z'
/>
</svg>
)
}

15
src/lib/markdown.js Normal file
View File

@ -0,0 +1,15 @@
import { remark } from 'remark'
import html from 'remark-html'
import strip from 'strip-markdown'
export async function markdownToHtml(markdown) {
const result = await remark().use(html).process(markdown)
return result.toString()
}
export async function markdownToText(markdown) {
const result = await remark().use(strip).process(markdown)
return result.toString()
}

66
src/lib/posts.js Normal file
View File

@ -0,0 +1,66 @@
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { markdownToHtml, markdownToText } from './markdown'
import { cache } from 'react'
import { i18n } from '../../i18n-config'
async function getTruncatedPostContent(content) {
const words = content.split(' ')
const truncatedWords = 9
const truncatedContent =
words.length > truncatedWords
? words.slice(0, truncatedWords).join(' ') + '...'
: content
const truncatedContentAsText = await markdownToText(truncatedContent)
return truncatedContentAsText
}
export const getSortedPostsData = cache(async (locale) => {
const postsDirectory = path.join(process.cwd(), `src/posts/${locale}`)
const fileNames = fs.readdirSync(postsDirectory)
const allPostsDataPromises = fileNames.map(async (fileName) => {
const id = fileName.replace(/\.md$/, '')
const fullPath = path.join(postsDirectory, fileName)
const fileContents = fs.readFileSync(fullPath, 'utf8')
const matterResult = matter(fileContents)
const content = matterResult.content
const truncatedContent = await getTruncatedPostContent(content)
const contentAsHtml = await markdownToHtml(content)
return {
id,
content: contentAsHtml,
truncatedContent,
...matterResult.data,
}
})
const allPostsData = await Promise.all(allPostsDataPromises)
const sortedPostsData = allPostsData.sort((a, b) => {
if (a.date < b.date) {
return -1
} else {
return 1
}
})
return {
posts: sortedPostsData,
}
})
export const getAllPosts = cache(async () => {
const allPosts = {}
for (const locale of i18n.locales) {
const { posts } = await getSortedPostsData(locale)
allPosts[locale] = posts
}
return allPosts
})

6
src/posts/bg/first.md Normal file
View File

@ -0,0 +1,6 @@
---
title: 'Bulgarian'
date: '08-06-2024'
---
**Some** description

6
src/posts/en/first.md Normal file
View File

@ -0,0 +1,6 @@
---
title: 'English'
date: '08-06-2024'
---
**Some** description

View File

@ -1,20 +1,36 @@
import type { Config } from "tailwindcss";
import type { Config } from 'tailwindcss'
const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
"gradient-conic":
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
},
colors: {
'dark-blue': '#09021B',
'deep-blue': '#0F0429',
blue: '#2F1B5D',
'neon-green': '#34EAD8',
'neon-pink': '#D92ACE',
},
letterSpacing: {
max: '0.3em',
},
scale: {
1.3: '1.3',
},
flexBasis: {
24: '24%',
},
},
},
plugins: [],
};
export default config;
}
export default config