All checks were successful
Docker Deploy / build-and-push (push) Successful in 5m47s
159 lines
6.9 KiB
Plaintext
159 lines
6.9 KiB
Plaintext
---
|
|
import Layout from "../layouts/Layout.astro";
|
|
import { Icon } from "astro-icon/components";
|
|
import { config } from "../config";
|
|
|
|
// Sort talks by date, newest first
|
|
const sortedTalks = [...config.talks].sort((a, b) => {
|
|
if (!a.date || !b.date) return 0;
|
|
return new Date(b.date).valueOf() - new Date(a.date).valueOf();
|
|
});
|
|
|
|
function formatDate(dateStr: string): string {
|
|
return new Date(dateStr).toLocaleDateString("en-us", {
|
|
month: "short",
|
|
day: "numeric",
|
|
year: "numeric",
|
|
});
|
|
}
|
|
---
|
|
|
|
<Layout>
|
|
<div class="w-full p-4 sm:p-8">
|
|
<h1
|
|
class="text-3xl sm:text-4xl font-bold text-primary mb-6 sm:mb-8 text-center"
|
|
>
|
|
Talks
|
|
</h1>
|
|
|
|
{/* Single talk: Simple centered card without timeline */}
|
|
{sortedTalks.length === 1 && (
|
|
<div class="max-w-xl mx-auto px-4">
|
|
<div class="border border-base-content/20 rounded-box p-6 bg-base-200 hover:border-primary transition-colors">
|
|
{sortedTalks[0].date && (
|
|
<time class="font-mono text-sm opacity-60">
|
|
{formatDate(sortedTalks[0].date)}
|
|
</time>
|
|
)}
|
|
|
|
<a
|
|
href={sortedTalks[0].link}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
class="block group"
|
|
>
|
|
<h3 class="text-xl font-bold text-primary group-hover:text-accent transition-colors">
|
|
{sortedTalks[0].name}
|
|
</h3>
|
|
|
|
<p class="opacity-80 mt-2">
|
|
{sortedTalks[0].description}
|
|
</p>
|
|
|
|
<span class="inline-flex items-center gap-1 text-sm text-primary mt-3 group-hover:text-accent transition-colors">
|
|
<Icon name="mdi:open-in-new" class="w-4 h-4" />
|
|
View talk
|
|
</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Multiple talks: Mobile one-sided compact timeline */}
|
|
{sortedTalks.length > 1 && (
|
|
<ul class="timeline timeline-vertical timeline-compact timeline-snap-icon max-w-3xl mx-auto px-4 md:hidden">
|
|
{
|
|
sortedTalks.map((talk, index) => (
|
|
<li>
|
|
{index > 0 && <hr class="bg-primary" />}
|
|
|
|
<div class="timeline-middle">
|
|
<Icon name="mdi:circle" class="w-4 h-4 text-primary" />
|
|
</div>
|
|
|
|
<div class="timeline-end mb-8 ml-4">
|
|
<div class="border border-base-content/20 rounded-box p-4 bg-base-200 hover:border-primary transition-colors">
|
|
{talk.date && (
|
|
<time class="font-mono text-sm opacity-60">
|
|
{formatDate(talk.date)}
|
|
</time>
|
|
)}
|
|
|
|
<a
|
|
href={talk.link}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
class="block group"
|
|
>
|
|
<h3 class="text-lg font-bold text-primary group-hover:text-accent transition-colors">
|
|
{talk.name}
|
|
</h3>
|
|
|
|
<p class="text-sm opacity-80 mt-1">
|
|
{talk.description}
|
|
</p>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{index < sortedTalks.length - 1 && <hr class="bg-primary" />}
|
|
</li>
|
|
))
|
|
}
|
|
</ul>
|
|
)}
|
|
|
|
{/* Multiple talks: Desktop dual-sided alternating timeline */}
|
|
{sortedTalks.length > 1 && (
|
|
<ul class="timeline timeline-vertical timeline-snap-icon max-w-3xl mx-auto px-4 hidden md:block">
|
|
{
|
|
sortedTalks.map((talk, index) => (
|
|
<li>
|
|
{index > 0 && <hr class="bg-primary" />}
|
|
|
|
<div class="timeline-middle">
|
|
<Icon name="mdi:circle" class="w-4 h-4 text-primary" />
|
|
</div>
|
|
|
|
<div class={`timeline-${index % 2 === 0 ? 'start' : 'end'} text-${index % 2 === 0 ? 'end' : 'start'} mb-8 mx-4`}>
|
|
<div class="border border-base-content/20 rounded-box p-4 bg-base-200 hover:border-primary transition-colors">
|
|
{talk.date && (
|
|
<time class="font-mono text-sm opacity-60">
|
|
{formatDate(talk.date)}
|
|
</time>
|
|
)}
|
|
|
|
<a
|
|
href={talk.link}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
class="block group"
|
|
>
|
|
<h3 class="text-lg font-bold text-primary group-hover:text-accent transition-colors">
|
|
{talk.name}
|
|
</h3>
|
|
|
|
<p class="text-sm opacity-80 mt-1">
|
|
{talk.description}
|
|
</p>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{index < sortedTalks.length - 1 && <hr class="bg-primary" />}
|
|
</li>
|
|
))
|
|
}
|
|
</ul>
|
|
)}
|
|
|
|
{
|
|
sortedTalks.length === 0 && (
|
|
<p class="text-center text-gray-500 mt-12">
|
|
No talks available yet. Check back soon!
|
|
</p>
|
|
)
|
|
}
|
|
</div>
|
|
</Layout>
|