Skip to content
51 changes: 45 additions & 6 deletions src/components/Schedule/CardConference.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import SpeakerForCard from "./SpeakerForCard.astro";
import { lunalink } from "@bearstudio/lunalink";
import { ROUTES } from "@/routes.gen";
import { LuSquarePlay } from "react-icons/lu";
import { FiPlus, FiXCircle } from "react-icons/fi";
import { cn } from "@/lib/utils-client";

interface Props {
activity: NonNullable<
Expand All @@ -27,6 +29,9 @@ const speakers = (
},
}));
const people = [...hosts, ...speakers];
const scheduleItem = (event.data.schedule?.items ?? []).find(
(conference) => conference.slug?.id === talk?.id,
);
---

{
Expand All @@ -38,11 +43,40 @@ const people = [...hosts, ...speakers];
})}
class="group flex w-full flex-col gap-4 rounded-lg bg-white/5 p-4 backdrop-blur-md transition hover:bg-white/10 sm:px-6 sm:py-5"
>
<p class="text-balance font-heading text-base font-medium leading-tight tracking-wider text-white transition group-hover:text-primary">
{talk.data.title}
</p>
<div class="flex justify-between">
<p
class={cn(
"text-balance font-heading text-base font-medium leading-tight tracking-wider text-white transition group-hover:text-primary",
scheduleItem?.status === "cancelled" ? "line-through" : "",
)}
>
{talk.data.title}
</p>
{scheduleItem?.status === "cancelled" && (
<div class="h-full w-fit rounded-full bg-gradient-to-r from-destructive to-destructive/80 px-2 py-1 text-destructive-foreground">
<div class="flex items-center gap-1">
<FiXCircle className="h-4 w-4" />
<span class="text-sm font-medium">Cancelled</span>
</div>
</div>
)}
{scheduleItem?.status === "replacement" && (
<div class="isolate h-full w-fit justify-center rounded-full bg-success from-accent px-2 py-1 text-accent-foreground text-white">
<div class="flex items-center gap-1">
<FiPlus className="h-4 w-4 text-white" />
<span class="text-sm font-medium text-white">New</span>
</div>
</div>
)}
</div>

{!!people.length && (
<div class="grid grid-cols-2 gap-3 md:grid-cols-3">
<div
class={cn(
"grid grid-cols-2 gap-3 md:grid-cols-3",
scheduleItem?.status === "cancelled" ? "grayscale" : "",
)}
>
{speakers.map((speaker) => (
<SpeakerForCard
name={speaker.data.name}
Expand All @@ -53,8 +87,13 @@ const people = [...hosts, ...speakers];
</div>
)}

<div class="flex flex-row gap-2">
<span class="flex w-fit items-center gap-1.5 rounded-full border border-black/60 bg-black/40 px-2 py-0.5 text-2xs font-bold uppercase leading-none opacity-60 transition group-hover:opacity-100">
<div
class={cn(
"flex flex-row gap-2",
scheduleItem?.status === "cancelled" ? "grayscale" : "",
)}
>
<span class="flex w-fit items-center gap-1.5 rounded-full border border-black/60 bg-black/40 px-2 py-0.5 text-2xs font-bold uppercase leading-none opacity-60 grayscale transition group-hover:opacity-100">
<IoLanguageSharp className="text-base" />
<span>Talk in {talk.data.language}</span>
</span>
Expand Down
6 changes: 6 additions & 0 deletions src/content/events/2025-malaysia-kuala-lumpur/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ schedule:
slug: designing-from-the-margins-building-ux-culture-across-borders
duration: 30
startTime: 2025-10-25T11:00:00.000Z
status: cancelled
- type: conference
slug: we-don-t-want-to-migrate-to-typescript-there-is-too-much-too-learn
duration: 30
startTime: 2025-10-25T11:00:00.000Z
status: replacement
- type: info
name: Morning info
description: Coffee time!
Expand Down
7 changes: 7 additions & 0 deletions src/lib/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ export async function eventWithComputed<
(talk) =>
talk.data.speakers?.map(async (speaker) => {
if (!speaker) return;
const scheduleTalk = event.data.schedule?.items?.find(
(item) => item.slug?.id === talk.id,
);
const isSpeakerTalkCanceled = scheduleTalk?.status === "cancelled";
if (isSpeakerTalkCanceled) {
return;
}
const person = await getEntry("people", speaker.id.id);

if (!person) {
Expand Down
12 changes: 9 additions & 3 deletions src/pages/events/[id].html.md/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,18 @@ ${event.data.location?.name}, ${event.data.location?.address}`;

const displaySchedule = async (event: EventWithComputed) => {
if (isEmpty(event.data._computed.talks)) return "";

const talks = event.data._computed.talks.filter((talk) => {
const scheduleTalk = event.data.schedule?.items?.find(
(item) => item.slug?.id === talk.id,
);
return scheduleTalk?.status !== "cancelled";
});
const itemsWithTime =
event.data.schedule?.items?.filter(
(item) =>
(item.type === "conference" || item.type === "roundtable") &&
item.startTime,
item.startTime &&
item.status !== "cancelled",
) ?? [];

const formattedItems = itemsWithTime.map((item) =>
Expand All @@ -83,7 +89,7 @@ const displaySchedule = async (event: EventWithComputed) => {

${(
await Promise.all(
event.data._computed.talks.map(async (item, index) => {
talks.map(async (item, index) => {
const timeStart = formattedItems[index];
return `- [${item.data.title}](${lunalink(
ROUTES.events[":id"].talks[":talkId"].__path,
Expand Down
6 changes: 4 additions & 2 deletions src/pages/events/[id]/assets/_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ export const getEventAssetsSources = (event: CollectionEntry<"events">) => {
const sponsors = event.data.sponsors?.map((s) => s.slug) ?? [];
const partners = event.data.partners ?? [];
const coOrganizers = event.data.coOrganizers ?? [];

const talks = event.data.schedule?.items?.filter(
(talk) => talk.status !== "cancelled",
);
return [
eventFilesNames.map(
(fileName) => `/events/${event.id}/assets/${fileName}.jpg`,
),
event.data.schedule?.items?.flatMap((talk) =>
talks?.flatMap((talk) =>
talkFilesNames.map((fileName) =>
!talk.slug
? null
Expand Down
3 changes: 3 additions & 0 deletions src/schemas/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ const zEventBase = ({ image }: SchemaContext) =>
startTime: z.date().optional(),
duration: z.number().optional().describe("Number of minutes"),
location: z.string().optional(),
status: z
.enum(["cancelled", "replacement", "published"])
.default("published"),
}),
)
.optional(),
Expand Down
2 changes: 2 additions & 0 deletions src/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
--warning: 45 84.2% 60.2%;
--warning-foreground: 45 0% 98%;

--success: 142, 76%, 36%;

--border: 0 0% 9%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
Expand Down
1 change: 1 addition & 0 deletions tailwind.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default {
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
success: "hsl(var(--success))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
Expand Down