Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events #27

Merged
merged 12 commits into from
Oct 25, 2024
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,7 @@ yarn-error.log*
next-env.d.ts

## Directory-based project format:
.idea/
.idea/

# env files
.env
262 changes: 262 additions & 0 deletions app/[lang]/events/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
import { sponsors } from '@/config/sponsor';
import { getDictionary } from '@/get-dictionary';
import { Locale } from '@/i18n-config';
import { cn } from '@/lib/utils';
import { Issue, IssueLabel, Paginated } from '@/types/events';
import Image from 'next/image';
import Link from 'next/link';

interface IssuesQueryResponse {
data: {
repository: {
issues: Paginated<Issue>;
};
};
}

const issueQuery = `
query {
repository(name: "trobades", owner: "gironajs") {
name
description
issues(first: 10, states: OPEN) {
edges {
node {
id
title
url
publishedAt
labels(first: 10, orderBy: { field: CREATED_AT, direction: DESC }) {
edges {
node {
id
name
}
}
}
}
}
}
}
}
`;

const images = [
{ src: '/assets/events/P1080125.jpg', type: 'vertical' },
{ src: '/assets/events/P1080128.jpg', type: 'horizontal' },
{ src: '/assets/events/20231108_200715.jpg', type: 'horizontal' },
{ src: '/assets/events/20231108_171727.jpg', type: 'vertical' },
{ src: '/assets/events/20231108_190921.jpg', type: 'vertical' },
{ src: '/assets/events/P1080106.jpg', type: 'horizontal' },
{ src: '/assets/events/P1080123.jpg', type: 'horizontal' },
{ src: '/assets/events/20231108_191042.jpg', type: 'vertical' },
{ src: '/assets/events/20231108_192226.jpg', type: 'vertical' },
{ src: '/assets/events/P1080186.jpg', type: 'horizontal' },
{ src: '/assets/events/20231108_200742.jpg', type: 'vertical' },
{ src: '/assets/events/P1080173.jpg', type: 'vertical' },
{ src: '/assets/events/20231108_205607.jpg', type: 'vertical' },
];

async function EventsPage({ params: { lang } }: { params: { lang: Locale } }) {
const response = await fetch('https://api.github.com/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
},
body: JSON.stringify({ query: issueQuery }),
});
const { data }: IssuesQueryResponse = await response.json();

const hasEvents = (data?.repository.issues.edges.length ?? 0) > 0;

const dictionary = await getDictionary(lang);

return (
<div className="bg-stone-900 min-h-screen px-4">
<section className="pt-24 pb-12">
<div className="container px-4 mx-auto flex flex-wrap">
<div className="w-full text-center max-w-2xl mx-auto md:mt-20">
<h1 className="text-4xl md:text-7xl font-bold text-center bg-clip-text text-transparent bg-gradient-to-b from-neutral-50 to-neutral-400 bg-opacity-50">
{dictionary.events.title}
</h1>
<p className="text-xl text-gray-400 mt-4">
{dictionary.events.subtitle}
</p>
<div className="flex flex-wrap justify-center mt-8 md:flex-row flex-col">
<div className="shadow border border-neutral-200 rounded-md mt-2 sm:mt-0">
<a
href="https://github.com/gironajs/trobades/issues/new?assignees=&labels=&projects=&template=peticions.md&title="
className="flex items-center justify-center w-full px-8 py-3 text-base font-medium text-black bg-white border border-transparent leading-6 rounded-md hover:bg-slate-50 hover:text-black focus:outline-none focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
>
<span className="mr-2"> {dictionary.events.propose}</span>
</a>
</div>
<div className="shadow border border-neutral-200 rounded-md md:ml-3 mt-2 sm:mt-0">
<a
href="https://github.com/gironajs/trobades/issues/new?assignees=&labels=&projects=&template=xerrades.md&title="
className="flex items-center justify-center w-full px-8 py-3 text-base font-medium text-black bg-white border border-transparent leading-6 rounded-md hover:bg-slate-50 hover:text-black focus:outline-none focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
>
<span className="mr-2">{dictionary.events.organize}</span>
</a>
</div>
</div>
</div>
</div>
</section>

<div className="w-full text-center max-w-2xl mx-auto mt-12">
<h2 className="text-3xl font-bold text-slate-200 mb-5 text-center">
{dictionary.events.list.title}
</h2>
<p className="text-xl text-gray-400 mt-4 text-center">
{dictionary.events.list.subtitle}
</p>
</div>

{hasEvents && (
<section className="py-12 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 max-w-6xl mx-auto">
{data.repository.issues.edges.map((issue: { node: Issue }) => (
<div
className="bg-stone-800 shadow-md rounded-md p-6 flex flex-col"
key={issue.node.id}
>
<div className="flex flex-wrap">
{issue.node.labels.edges.map((label: { node: IssueLabel }) => (
<span
className="inline-block bg-slate-200 rounded-full text-xs font-semibold text-slate-900 mr-2 mb-2 px-3 py-1"
key={label.node.id}
>
{label.node.name}
</span>
))}
</div>
<a
href={issue.node.url}
target="_blank"
rel="noopener noreferrer"
className="text-slate-200 hover:text-slate-100"
>
<h2 className="text-3xl font-bold mb-5">{issue.node.title}</h2>
</a>
<div className="flex-1" />
<span className="text-sm font-bold text-gray-400">
{issue.node.publishedAt}
</span>
</div>
))}
</section>
)}

{!hasEvents && (
<div className="w-full text-center max-w-2xl mx-auto mt-12">
<p className="text-xl text-gray-400 mt-4 text-center">
{dictionary.events.list.empty}
</p>
</div>
)}

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 items-start max-w-5xl mx-auto gap-10 py-20">
{images.map((el, i) => (
<Image
key={'grid' + i}
src={el.src}
className={cn(
el.type === 'horizontal' && 'col-span-1 md:col-span-2',
'h-80 w-full object-cover object-center-center rounded-lg gap-10 !m-0 !p-0'
)}
height="400"
width="400"
alt="thumbnail"
/>
))}
</div>

<div className="w-full max-w-2xl mx-auto mt-12 flex gap-8 md:flex-row flex-col">
<div className="flex-1">
<h2 className="text-3xl font-bold text-white mb-5 text-left">
{dictionary.events.cta.message}
</h2>
</div>
<div className="flex-1 flex flex-col">
<div className="">
<h3 className="text-xl font-bold text-slate-200 mb-5 text-left">
{dictionary.events.cta.one.title}
</h3>
<p className="text-md text-gray-400 mt-4 text-left">
{dictionary.events.cta.one.subtitle}{' '}
<a
className="text-slate-200 hover:text-slate-100"
href="https://github.com/gironajs/trobades/issues/new?assignees=&labels=&projects=&template=peticions.md&title="
>
link
</a>
.
</p>
</div>
<div className="mt-12 mb-12">
<h3 className="text-xl font-bold text-slate-200 mb-5 text-left">
{dictionary.events.cta.two.title}
</h3>
<p className="text-md text-gray-400 mt-4 text-left">
{dictionary.events.cta.two.subtitle}{' '}
<a
className="text-slate-200 hover:text-slate-100"
href="https://github.com/gironajs/trobades/issues/new?assignees=&labels=&projects=&template=xerrades.md&title="
>
link
</a>
.
</p>
</div>
</div>
</div>

<section className="py-12 grid grid-cols-1 gap-4 max-w-6xl mx-auto justify-items-center">
<h3 className="text-2xl font-bold text-center bg-clip-text text-transparent bg-gradient-to-b from-neutral-50 to-neutral-400 bg-opacity-50">
{dictionary.events.sponsors.title}
</h3>

<a
href="mailto:[email protected]"
className="m-8 shadow border border-neutral-200 rounded-md mt-2 sm:mt-0"
>
<p className="flex items-center justify-center w-full px-8 py-3 text-base font-medium text-black bg-white border border-transparent leading-6 rounded-md hover:bg-slate-50 hover:text-black focus:outline-none focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10">
{dictionary.events.sponsors.contact}
</p>
</a>

<div className="w-full inline-flex flex-nowrap overflow-hidden [mask-image:_linear-gradient(to_right,transparent_0,_black_128px,_black_calc(100%-128px),transparent_100%)]">
{Array.from({ length: 2 }).map((_, i) => (
<div
aria-hidden={i === 1}
key={`sponsors-${i}`}
className="flex items-center justify-center md:justify-start [&_li]:mx-8 [&_img]:max-w-none animate-infinite-scroll"
>
{...sponsors.map((sponsor, index) => (
<Link
key={index}
href={sponsor.url}
target="_blank"
className="flex items-center m-10"
>
<div className="bg-white rounded-md shadow-md p-4">
<Image
className="object-cover w-[249px]"
src={sponsor.image.url}
width={sponsor.image.width}
height={sponsor.image.height}
alt={`${sponsor.name} sponsor image`}
/>
</div>
</Link>
))}
</div>
))}
</div>
</section>
</div>
);
}

export default EventsPage;
39 changes: 34 additions & 5 deletions components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from '@/lib/locale-pretty-urls-cache';
import { usePathname } from 'next/navigation';
import { LangDictionary } from '@/get-dictionary';
import { cn } from '@/lib/utils';

type Props = {
lang: Locale;
Expand All @@ -36,19 +37,47 @@ const Header = ({ lang, localePrettyUrlsCacheData, dictionary }: Props) => {
const pathName = usePathname();
const localePrettyUrls = getLocalePrettyUrls(pathName);

const eventsTheme = pathName.match(/\/.*\/events/);

return (
<header className="top-0 z-50 h-14 absolute right-0 left-0">
<div className="container flex h-14 items-center justify-between px-4 py-4 relative">
<div className="flex gap-6 md:gap-10 w-full justify-start">
<div className="container flex h-14 items-center justify-between px-4 py-4 relative flex-wrap">
<div className="flex gap-6 md:gap-10 justify-start">
<Link href="/" className="items-center space-x-2 flex">
<span className="font-bold text-xl hover:text-red-500">
<span
className={cn(
eventsTheme && 'text-slate-50',
'font-bold text-xl hover:text-red-500'
)}
>
{siteConfig.name}
</span>
</Link>
<Link href={`/${lang}/blog`} className="items-center space-x-2 flex">
<Link
href={`/${lang}/blog`}
className={cn(
eventsTheme && 'text-slate-50',
'items-center space-x-2 flex'
)}
>
<span className="font-bold text-lg hover:text-red-500">Blog</span>
</Link>
<Link href={`/${lang}/map`} className="items-center space-x-2 flex">
<Link
href={`/${lang}/events`}
className={cn(
eventsTheme && 'text-red-500',
'items-center space-x-2 flex'
)}
>
<span className="font-bold text-lg hover:text-red-500">Events</span>
</Link>
<Link
href={`/${lang}/map`}
className={cn(
eventsTheme && 'text-slate-50',
'items-center space-x-2 flex'
)}
>
<span className="font-bold text-lg hover:text-red-500">Map</span>
</Link>
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/locale-switcher/locale-switcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const LocaleSwitcher = ({ locale, localeUrls }: Props) => {

return (
<div className="locale-switcher absolute right-0 top-0 z-20">
<div className="flex gap-4 flex flex-col items-end p-4">
<div className="flex gap-4 flex flex-col items-end p-4 pt-6">
<div
className={clsx(
'locale-switcher-anchor relative cursor-pointer rounded-full border border-neutral-800 overflow-hidden transition-transform hover:scale-110',
Expand Down
26 changes: 26 additions & 0 deletions dictionaries/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,31 @@
},
"header": {
"meetup": "Ves al meetup"
},
"events": {
"title": "GironaJS Events",
"subtitle": "Aquí podeu trobar trobades, conferències, tallers, etc. organitzats per GironaJS o proposar un nou esdeveniment al qual us agradaria assistir o organitzar.",
"organize": "Organitzar un esdeveniment",
"propose": "Proposar un esdeveniment",
"list": {
"title": "Pròxims esdeveniments",
"subtitle": "Aquests són els propers esdeveniments que la comunitat està organitzant.",
"empty": "No s'ha trobat cap esdeveniment"
},
"cta": {
"message": "Com funcionen els esdeveniments?",
"one": {
"title": "1. Proposar un esdeveniment",
"subtitle": "Si voleu proposar un esdeveniment, si us plau, ompliu el formulari a continuació i ens posarem en contacte amb vosaltres el més aviat possible."
},
"two": {
"title": "2. Organitzar l'esdeveniment",
"subtitle": "Un cop l'esdeveniment estigui aprovat, podeu organitzar-lo i us ajudarem a promocionar-lo."
}
},
"sponsors": {
"title": "Alguns patrocinadors ens ajuden a fer possible aquests esdeveniments amb menjar, begudes, ubicació i molt més, gràcies a ells!",
"contact": "Si vols patrocinar un esdeveniment, posa't en contacte amb nosaltres"
}
}
}
Loading
Loading