Skip to content

Commit ade40e5

Browse files
inform attendees about schedule update when a speaker withdrawls (#475)
Co-authored-by: Yoann Fleury <yoann.fleury@yahoo.com>
1 parent 0f3bf34 commit ade40e5

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

src/components/Schedule/CardConference.astro

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
---
22
import { type CollectionEntry, getEntries, getEntry } from "astro:content";
3-
import { IoLanguageSharp } from "react-icons/io5";
3+
import { IoLanguageSharp, IoSparklesSharp } from "react-icons/io5";
44
import SpeakerForCard from "./SpeakerForCard.astro";
55
import { lunalink } from "@bearstudio/lunalink";
66
import { ROUTES } from "@/routes.gen";
77
import { LuSquarePlay } from "react-icons/lu";
8+
import { FiXCircle } from "react-icons/fi";
9+
import { cn } from "@/lib/utils-client";
810
911
interface Props {
1012
activity: NonNullable<
@@ -27,6 +29,9 @@ const speakers = (
2729
},
2830
}));
2931
const people = [...hosts, ...speakers];
32+
const scheduleItem = (event.data.schedule?.items ?? []).find(
33+
(conference) => conference.slug?.id === talk?.id,
34+
);
3035
---
3136

3237
{
@@ -36,13 +41,45 @@ const people = [...hosts, ...speakers];
3641
id: event.id,
3742
talkId: talk.id,
3843
})}
39-
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"
44+
class={cn(
45+
"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",
46+
scheduleItem?.status === "cancelled" && "opacity-60",
47+
)}
4048
>
41-
<p class="text-balance font-heading text-base font-medium leading-tight tracking-wider text-white transition group-hover:text-primary">
42-
{talk.data.title}
43-
</p>
49+
<div class="flex justify-between">
50+
<p
51+
class={cn(
52+
"text-balance font-heading text-base font-medium leading-tight tracking-wider text-white transition group-hover:text-primary",
53+
scheduleItem?.status === "cancelled" ? "line-through" : "",
54+
)}
55+
>
56+
{talk.data.title}
57+
</p>
58+
{scheduleItem?.status === "cancelled" && (
59+
<div class="h-full w-fit rounded-full bg-white/10 px-2 py-1 text-white">
60+
<div class="flex items-center gap-1">
61+
<FiXCircle className="h-3 w-3" />
62+
<span class="text-xs font-medium">Cancelled</span>
63+
</div>
64+
</div>
65+
)}
66+
{scheduleItem?.status === "replacement" && (
67+
<div class="isolate h-full w-fit justify-center rounded-full bg-white from-accent px-2 py-1 text-background">
68+
<div class="flex items-center gap-1">
69+
<IoSparklesSharp className="h-3 w-3" />
70+
<span class="text-xs font-medium">New</span>
71+
</div>
72+
</div>
73+
)}
74+
</div>
75+
4476
{!!people.length && (
45-
<div class="grid grid-cols-2 gap-3 md:grid-cols-3">
77+
<div
78+
class={cn(
79+
"grid grid-cols-2 gap-3 md:grid-cols-3",
80+
scheduleItem?.status === "cancelled" ? "grayscale" : "",
81+
)}
82+
>
4683
{speakers.map((speaker) => (
4784
<SpeakerForCard
4885
name={speaker.data.name}
@@ -53,8 +90,13 @@ const people = [...hosts, ...speakers];
5390
</div>
5491
)}
5592

56-
<div class="flex flex-row gap-2">
57-
<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">
93+
<div
94+
class={cn(
95+
"flex flex-row gap-2",
96+
scheduleItem?.status === "cancelled" ? "grayscale" : "",
97+
)}
98+
>
99+
<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">
58100
<IoLanguageSharp className="text-base" />
59101
<span>Talk in {talk.data.language}</span>
60102
</span>

src/lib/events.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ export async function eventWithComputed<
6969
(talk) =>
7070
talk.data.speakers?.map(async (speaker) => {
7171
if (!speaker) return;
72+
const scheduleTalk = event.data.schedule?.items?.find(
73+
(item) => item.slug?.id === talk.id,
74+
);
75+
const isSpeakerTalkCanceled = scheduleTalk?.status === "cancelled";
76+
if (isSpeakerTalkCanceled) {
77+
return;
78+
}
7279
const person = await getEntry("people", speaker.id.id);
7380

7481
if (!person) {

src/pages/events/[id].html.md/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,18 @@ ${event.data.location?.name}, ${event.data.location?.address}`;
6767

6868
const displaySchedule = async (event: EventWithComputed) => {
6969
if (isEmpty(event.data._computed.talks)) return "";
70-
70+
const talks = event.data._computed.talks.filter((talk) => {
71+
const scheduleTalk = event.data.schedule?.items?.find(
72+
(item) => item.slug?.id === talk.id,
73+
);
74+
return scheduleTalk?.status !== "cancelled";
75+
});
7176
const itemsWithTime =
7277
event.data.schedule?.items?.filter(
7378
(item) =>
7479
(item.type === "conference" || item.type === "roundtable") &&
75-
item.startTime,
80+
item.startTime &&
81+
item.status !== "cancelled",
7682
) ?? [];
7783

7884
const formattedItems = itemsWithTime.map((item) =>
@@ -83,7 +89,7 @@ const displaySchedule = async (event: EventWithComputed) => {
8389
8490
${(
8591
await Promise.all(
86-
event.data._computed.talks.map(async (item, index) => {
92+
talks.map(async (item, index) => {
8793
const timeStart = formattedItems[index];
8894
return `- [${item.data.title}](${lunalink(
8995
ROUTES.events[":id"].talks[":talkId"].__path,

src/pages/events/[id]/assets/_utils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ export const getEventAssetsSources = (event: CollectionEntry<"events">) => {
4545
const sponsors = event.data.sponsors?.map((s) => s.slug) ?? [];
4646
const partners = event.data.partners ?? [];
4747
const coOrganizers = event.data.coOrganizers ?? [];
48-
48+
const talks = event.data.schedule?.items?.filter(
49+
(talk) => talk.status !== "cancelled",
50+
);
4951
return [
5052
eventFilesNames.map(
5153
(fileName) => `/events/${event.id}/assets/${fileName}.jpg`,
5254
),
53-
event.data.schedule?.items?.flatMap((talk) =>
55+
talks?.flatMap((talk) =>
5456
talkFilesNames.map((fileName) =>
5557
!talk.slug
5658
? null

src/schemas/events.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ const zEventBase = ({ image }: SchemaContext) =>
152152
startTime: z.date().optional(),
153153
duration: z.number().optional().describe("Number of minutes"),
154154
location: z.string().optional(),
155+
status: z
156+
.enum(["cancelled", "replacement", "published"])
157+
.default("published"),
155158
}),
156159
)
157160
.optional(),

0 commit comments

Comments
 (0)