Skip to content

Commit

Permalink
Added events component
Browse files Browse the repository at this point in the history
  • Loading branch information
gxjansen committed Nov 2, 2024
1 parent ef386b9 commit 539ed65
Show file tree
Hide file tree
Showing 9 changed files with 634 additions and 284 deletions.
497 changes: 245 additions & 252 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@preline/tabs": "^2.4.1",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.0",
"astro": "^4.16.7",
"astro": "^4.16.8",
"astro-compressor": "^0.4.1",
"astro-icon": "^1.1.1",
"clipboard": "^2.0.11",
Expand All @@ -49,6 +49,7 @@
"@iconify-json/mdi": "^1.2.1",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.14",
"@types/node-fetch": "^2.6.11",
"astro-vtbot": "^1.10.5",
"prettier": "^3.3.2",
"prettier-plugin-astro": "^0.14.1",
Expand Down
5 changes: 5 additions & 0 deletions src/components/VanillaEvents.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
import VanillaEventsComponent from './VanillaEvents';
---

<VanillaEventsComponent client:load />
189 changes: 189 additions & 0 deletions src/components/VanillaEvents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { useState, useEffect } from 'react';
import { getUpcomingEvents, getPastEvents } from '../utils/vanillaApi';
import type { FormattedEvent } from '../utils/vanillaApi';

const EventCard = ({ event, isUpcoming }: { event: FormattedEvent, isUpcoming: boolean }) => {
const formatDate = (date: Date) => {
return date.toLocaleDateString('en-US', {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
};

const formatCalendarDate = (date: Date) => {
const month = date.toLocaleString('en-US', { month: 'short' });
const day = date.getDate();
return { month, day };
};

const calculateDuration = (startDate: Date, endDate: Date) => {
const diffMs = endDate.getTime() - startDate.getTime();
const diffMins = Math.round(diffMs / (1000 * 60));
const diffHours = Math.round(diffMs / (1000 * 60 * 60));
const diffDays = Math.round(diffMs / (1000 * 60 * 60 * 24));

if (diffDays > 1) {
return `${diffDays} days`;
} else if (diffDays === 1) {
return '1 day';
} else if (diffHours > 1) {
return `${diffHours} hours`;
} else if (diffHours === 1) {
return '1 hour';
} else if (diffMins > 1) {
return `${diffMins} minutes`;
} else {
return '1 minute';
}
};

const startDateFormatted = formatCalendarDate(event.startDate);
const duration = calculateDuration(event.startDate, event.endDate);

// Determine the link for RSVP/More Info
const rsvpLink = event.ctaUrl || event.url;

return (
<div className="mb-8 pb-8 border-b border-gray-700/20 last:border-b-0 last:mb-0 last:pb-0">
<div className="flex gap-4">
<div className="flex-shrink-0 w-16">
<div className="text-center bg-neutral-200 dark:bg-[#1A2942] rounded-lg overflow-hidden">
<div className="bg-blue-500 dark:bg-blue-600 text-white text-xs uppercase py-1">
{startDateFormatted.month}
</div>
<div className="text-xl font-bold py-2 text-gray-900 dark:text-white">
{startDateFormatted.day}
</div>
</div>
</div>
<div className="flex-grow min-w-0">
<h3 className="text-xl font-semibold text-gray-900 dark:text-white leading-tight">
<a href={event.url} className="hover:underline">{event.name}</a>
</h3>

<div className="flex flex-wrap items-center gap-x-4 gap-y-2 mt-3 text-sm text-gray-500 dark:text-gray-400">
<span>{formatDate(event.startDate)}</span>
<span className="text-gray-300 dark:text-gray-600"></span>
<span>{duration}</span>
</div>

{/* RSVP/More Info Button for Upcoming Events */}
{isUpcoming && (
<div className="mt-4">
<a href={rsvpLink} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
RSVP / More Info
</a>
</div>
)}
</div>
</div>
</div>
);
};

const VanillaEvents = () => {
const [upcomingEvents, setUpcomingEvents] = useState<FormattedEvent[]>([]);
const [pastEvents, setPastEvents] = useState<FormattedEvent[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const fetchData = async () => {
try {
console.log('Fetching events data...');
const [upcoming, past] = await Promise.all([
getUpcomingEvents(),
getPastEvents()
]);
console.log('Upcoming events:', upcoming);
console.log('Past events:', past);

setUpcomingEvents(upcoming);
setPastEvents(past);
setIsLoading(false);
} catch (err) {
console.error('Error fetching events:', err);
setError('Failed to fetch events');
setIsLoading(false);
}
};

fetchData();
}, []);

return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Past Events */}
<div className="bg-neutral-100 dark:bg-[#0A1628] rounded-xl shadow-md overflow-hidden mb-10 p-8">
<h3 className="text-2xl font-bold text-neutral-800 dark:text-neutral-200 sm:text-3xl mb-5">
<span className="text-pink-500 dark:text-pink-400">Past</span> Events
</h3>

{isLoading && (
<div className="flex justify-center items-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 dark:border-gray-400"></div>
</div>
)}

{error && (
<div className="text-red-500 font-bold p-4 rounded bg-red-100">
<p>Error: {error}</p>
</div>
)}

{!isLoading && !error && pastEvents.length === 0 && (
<p className="text-gray-600 dark:text-gray-400">No past events found</p>
)}

{!isLoading && !error && pastEvents.map((event) => (
<EventCard key={event.id} event={event} isUpcoming={false} />
))}

{/* Follow-up Options */}
<div className="mt-8">
<div className="flex space-x-4">
<a href="/event-recap" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Event Recaps
</a>
<a href="https://www.youtube.com/@SprykerSystems/videos" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Watch Recordings
</a>
</div>
</div>
</div>

{/* Upcoming Events */}
<div className="bg-neutral-100 dark:bg-[#0A1628] rounded-xl shadow-md overflow-hidden mb-10 p-8">
<h3 className="text-2xl font-bold text-neutral-800 dark:text-neutral-200 sm:text-3xl mb-5">
<span className="text-blue-500 dark:text-blue-400">Upcoming</span> Events
</h3>

{isLoading && (
<div className="flex justify-center items-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 dark:border-gray-400"></div>
</div>
)}

{error && (
<div className="text-red-500 font-bold p-4 rounded bg-red-100">
<p>Error: {error}</p>
</div>
)}

{!isLoading && !error && upcomingEvents.length === 0 && (
<p className="text-gray-600 dark:text-gray-400">No upcoming events scheduled</p>
)}

{!isLoading && !error && upcomingEvents.map((event) => (
<EventCard key={event.id} event={event} isUpcoming={true} />
))}
</div>
</div>
);
};

export default VanillaEvents;
8 changes: 4 additions & 4 deletions src/components/VanillaForumPosts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const VanillaForumPosts = () => {
</div>
)}

{!isLoading && !error && recentDiscussions.slice(0, 5).map((discussion) => (
{!isLoading && !error && recentDiscussions.slice(0, 3).map((discussion) => (
<DiscussionCard key={discussion.id} discussion={discussion} />
))}
</div>
Expand All @@ -106,9 +106,9 @@ const VanillaForumPosts = () => {
</div>
)}

{!isLoading && !error && popularDiscussions.map((discussion) => (
<DiscussionCard key={discussion.id} discussion={discussion} />
))}
{!isLoading && !error && popularDiscussions.slice(0, 3).map((discussion) => (
<DiscussionCard key={discussion.id} discussion={discussion} />
))}
</div>
</div>
);
Expand Down
9 changes: 7 additions & 2 deletions src/pages/api/forum/discussions.json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ import type { APIRoute } from 'astro';

export const GET: APIRoute = async () => {
try {
const response = await fetch('https://forum.commercequest.space/api/v2/discussions');
const response = await fetch('https://forum.commercequest.space/api/v2/discussions', {
headers: {
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Failed to fetch discussions: ${response.status}`);
}
const data = await response.json();
return new Response(JSON.stringify(data), {
status: 200,
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'Cache-Control': 'no-cache'
}
});
} catch (error) {
Expand Down
30 changes: 30 additions & 0 deletions src/pages/api/forum/events.json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { APIRoute } from 'astro';

export const GET: APIRoute = async () => {
try {
const response = await fetch('https://forum.commercequest.space/api/v2/events', {
headers: {
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Failed to fetch events: ${response.status}`);
}
const data = await response.json();
return new Response(JSON.stringify(data), {
status: 200,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache'
}
});
} catch (error) {
console.error('Error in events endpoint:', error);
return new Response(JSON.stringify({ error: 'Failed to fetch events' }), {
status: 500,
headers: {
'Content-Type': 'application/json'
}
});
}
}
12 changes: 11 additions & 1 deletion src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import customerday from "@images/community-1.jpg";
import cteam from "@images/community-2.jpg";
import maher from "@images/blog/maher.jpg";
import VanillaForumPosts from '../components/VanillaForumPosts.astro';
import VanillaEvents from '../components/VanillaEvents.astro';
---
<MainLayout>

Expand Down Expand Up @@ -47,10 +48,19 @@ import VanillaForumPosts from '../components/VanillaForumPosts.astro';
subTitle="Join engineers, architects and commerce experts from all over the world."
/>

<div class="mx-auto mt-10 mb-6 w-full space-y-1 text-center sm:w-1/2 lg:w-1/2">
<h2
class="text-balance text-2xl font-bold leading-tight text-neutral-800 dark:text-neutral-200 sm:text-3xl"
>Community activity dashboard</h2></div>

<section>
<VanillaForumPosts />
</section>

<section>
<VanillaEvents />
</section>

<FeaturesGeneral
title="Igniting Community. Celebrating Contributors."
subTitle="We’re excited to kickstart a new era of collaborative development with our wider community! Follow our contributions process, send in your PRs and you'll get a fast reply from our core team."
Expand Down Expand Up @@ -133,4 +143,4 @@ import VanillaForumPosts from '../components/VanillaForumPosts.astro';
subTitle="Help crafting an open commerce ecosystem."
url="https://github.com/spryker-community"
/>
</MainLayout>
</MainLayout>
Loading

0 comments on commit 539ed65

Please sign in to comment.