Skip to content

Commit 7729d52

Browse files
authored
Add Multiple Calendar Options to Add to Calendar Link on Events Page (#1320)
* Add Multiple Calendar Options to Add to Calendar Link on Events Page * applied suggested changes * Prettified Code! --------- Co-authored-by: fuyalasmit <[email protected]>
1 parent 01060f4 commit 7729d52

File tree

6 files changed

+226
-13
lines changed

6 files changed

+226
-13
lines changed

src/app/events/page.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { createMetaData } from '@/util/createMetaData.server';
55
import DisplayHtml from '@/components/DisplayHtml';
66
import { dateForDisplay } from '@/util/date';
77
import Link from 'next/link';
8+
import { Google } from '@/svg/calendar/Google';
9+
import { Outlook } from '@/svg/calendar/Outlook';
10+
import { Ics } from '@/svg/calendar/Ics';
811

912
export const metadata = createMetaData({
1013
title: 'Virtual Coffee Community Events',
@@ -121,10 +124,35 @@ export default async function Page() {
121124
<time dateTime={event.startDateLocalized}>
122125
{`${dateForDisplay(event.startDateLocalized, 'EEEE, LLLL d, yyyy')} - ${dateForDisplay(event.startDateLocalized, 't')} to ${dateForDisplay(event.endDateLocalized, 't ZZZZ')}`}
123126
</time>
124-
125-
<a href={event.eventCalendarLink} download>
126-
<small> Add to Calendar</small>
127-
</a>
127+
<div
128+
className="d-flex flex-row align-items-center"
129+
style={{ gap: '0.5rem' }}
130+
>
131+
<small className="text-muted">Add to Calendar:</small>
132+
<a
133+
href={event.eventCalendarLinks.google}
134+
target="_blank"
135+
rel="noreferrer"
136+
title="Google Calendar"
137+
>
138+
<Google />
139+
</a>
140+
<a
141+
href={event.eventCalendarLinks.outlook}
142+
target="_blank"
143+
rel="noreferrer"
144+
title="Outlook Calendar"
145+
>
146+
<Outlook />
147+
</a>
148+
<a
149+
href={event.eventCalendarLinks.ics}
150+
title="Download ICS"
151+
download
152+
>
153+
<Ics />
154+
</a>
155+
</div>
128156
</div>
129157
<div className="card-body">
130158
<h5 className="card-title">{event.title}</h5>

src/data/events.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { GraphQLClient, gql } from 'graphql-request';
44
import { DateTime } from 'luxon';
55
import { sanitizeHtml } from '@/util/sanitizeCmsData';
6-
import { ics } from 'calendar-link';
6+
import { ics, google, outlook } from 'calendar-link';
77

88
const calendarsQuery = gql`
99
query getCalendars {
@@ -39,7 +39,11 @@ interface SolspaceEventResponse {
3939
eventCalendarDescription: string;
4040
}
4141
export interface EventItem extends SolspaceEventResponse {
42-
eventCalendarLink: string;
42+
eventCalendarLinks: {
43+
google: string;
44+
outlook: string;
45+
ics: string;
46+
};
4347
}
4448
export interface EventsResponse extends Array<EventItem> {}
4549

@@ -112,16 +116,32 @@ export async function getEvents({
112116
const sanitizedDescription = await sanitizeHtml(
113117
event.eventCalendarDescription,
114118
);
115-
const calendarLink = ics({
119+
const calendarLinkGoogle = google({
116120
title: event.title,
117121
start: event.startDateLocalized,
118122
end: event.endDateLocalized,
119123
description: sanitizedDescription,
120-
});
124+
});
125+
const calendarLinkOutlook = outlook({
126+
title: event.title,
127+
start: event.startDateLocalized,
128+
end: event.endDateLocalized,
129+
description: sanitizedDescription,
130+
});
131+
const calendarLinkIcs = ics({
132+
title: event.title,
133+
start: event.startDateLocalized,
134+
end: event.endDateLocalized,
135+
description: sanitizedDescription,
136+
});
121137
return {
122138
...event,
123139
eventCalendarDescription: sanitizedDescription,
124-
eventCalendarLink: calendarLink,
140+
eventCalendarLinks: {
141+
google: calendarLinkGoogle,
142+
outlook: calendarLinkOutlook,
143+
ics: calendarLinkIcs,
144+
},
125145
};
126146
}),
127147
);

src/data/mocks/events.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { faker } from '@faker-js/faker';
22
import { DateTime } from 'luxon';
3-
import { ics } from 'calendar-link';
3+
import { ics, google, outlook } from 'calendar-link';
44

55
export function createEventsData({
66
limit = 15,
@@ -19,20 +19,36 @@ export function createEventsData({
1919

2020
return dates.map((date) => {
2121
const startDate = DateTime.fromJSDate(date);
22-
const calendarLink = ics({
22+
const calendarLinkGoogle = google({
2323
title: faker.lorem.sentence(7),
2424
start: startDate.toUTC().toString(),
2525
end: startDate.toUTC().plus({ hours: 1 }).toString(),
2626
description: faker.lorem.paragraph(),
27-
});
27+
});
28+
const calendarLinkOutlook = outlook({
29+
title: faker.lorem.sentence(7),
30+
start: startDate.toUTC().toString(),
31+
end: startDate.toUTC().plus({ hours: 1 }).toString(),
32+
description: faker.lorem.paragraph(),
33+
});
34+
const calendarLinkIcs = ics({
35+
title: faker.lorem.sentence(7),
36+
start: startDate.toUTC().toString(),
37+
end: startDate.toUTC().plus({ hours: 1 }).toString(),
38+
description: faker.lorem.paragraph(),
39+
});
2840

2941
return {
3042
id: faker.string.uuid(),
3143
title: faker.lorem.sentence(7),
3244
startDateLocalized: startDate.toUTC().toString(),
3345
endDateLocalized: startDate.toUTC().plus({ hours: 1 }).toString(),
3446
eventCalendarDescription: `<p>${faker.lorem.paragraph()}</p>`,
35-
eventCalendarLink: calendarLink,
47+
eventCalendarLinks: {
48+
google: calendarLinkGoogle,
49+
outlook: calendarLinkOutlook,
50+
ics: calendarLinkIcs,
51+
},
3652
};
3753
});
3854
}

src/svg/calendar/Google.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
export function Google({ title = 'Google Calendar' }: { title?: string }) {
2+
return (
3+
<svg
4+
xmlns="http://www.w3.org/2000/svg"
5+
x="0px"
6+
y="0px"
7+
width="20"
8+
height="20"
9+
viewBox="0 0 48 48"
10+
style={{
11+
fillRule: 'evenodd',
12+
clipRule: 'evenodd',
13+
strokeLinejoin: 'round',
14+
strokeMiterlimit: 2,
15+
}}
16+
role="img"
17+
aria-labelledby="GoogleSvgTitle"
18+
>
19+
<title id="GoogleSvgTitle">{title}</title>
20+
<rect width="22" height="22" x="13" y="13" fill="#fff" />
21+
<polygon
22+
fill="#1e88e5"
23+
points="25.68,20.92 26.688,22.36 28.272,21.208 28.272,29.56 30,29.56 30,18.616 28.56,18.616"
24+
/>
25+
<path
26+
fill="#1e88e5"
27+
d="M22.943,23.745c0.625-0.574,1.013-1.37,1.013-2.249c0-1.747-1.533-3.168-3.417-3.168
28+
c-1.602,0-2.972,1.009-3.33,2.453l1.657,0.421c0.165-0.664,0.868-1.146,1.673-1.146c0.942,0,1.709,0.646,1.709,1.44
29+
c0,0.794-0.767,1.44-1.709,1.44h-0.997v1.728h0.997c1.081,0,1.993,0.751,1.993,1.64c0,0.904-0.866,1.64-1.931,1.64
30+
c-0.962,0-1.784-0.61-1.914-1.418L17,26.802c0.262,1.636,1.81,2.87,3.6,2.87c2.007,0,3.64-1.511,3.64-3.368
31+
C24.24,25.281,23.736,24.363,22.943,23.745z"
32+
/>
33+
<polygon fill="#fbc02d" points="34,42 14,42 13,38 14,34 34,34 35,38" />
34+
<polygon fill="#4caf50" points="38,35 42,34 42,14 38,13 34,14 34,34" />
35+
<path
36+
fill="#1e88e5"
37+
d="M34,14l1-4l-1-4H9C7.343,6,6,7.343,6,9v25l4,1l4-1V14H34z"
38+
/>
39+
<polygon fill="#e53935" points="34,34 34,42 42,34" />
40+
<path fill="#1565c0" d="M39,6h-5v8h8V9C42,7.343,40.657,6,39,6z" />
41+
<path fill="#1565c0" d="M9,42h5v-8H6v5C6,40.657,7.343,42,9,42z" />
42+
</svg>
43+
);
44+
}

src/svg/calendar/Ics.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
export function Ics({ title = 'Download ICS' }: { title?: string }) {
2+
return (
3+
<svg
4+
xmlns="http://www.w3.org/2000/svg"
5+
x="0px"
6+
y="0px"
7+
width="20"
8+
height="20"
9+
viewBox="0 0 48 48"
10+
role="img"
11+
aria-labelledby="IcsSvgTitle"
12+
style={{
13+
fillRule: 'evenodd',
14+
clipRule: 'evenodd',
15+
strokeLinejoin: 'round',
16+
strokeMiterlimit: 2,
17+
}}
18+
>
19+
<title id="IcsSvgTitle">{title}</title>
20+
<path
21+
fill="#d6e5e5"
22+
d="M5.291,30.513c0.118-4.478,0.045-8.709-0.136-13.185c-0.078-1.934-0.175-3.888,0.171-5.792 S6.512,7.75,8.008,6.522c2.119-1.739,5.754-2.166,8.485-1.918C20.913,5.006,25.99,5.169,30.42,4.9 C32.789,4.757,35.196,4.493,37.515,5s4.593,1.96,5.346,4.211c0.348,1.04,0.347,2.159,0.344,3.255 c-0.022,6.618-0.045,13.235-0.067,19.853c-0.009,2.766-0.143,5.846-2.108,7.793c-1.707,1.692-4.318,2.02-6.721,2.051 c-5.231,0.066-10.477-0.835-15.676-0.255c-2.35,0.262-4.778,0.819-7.031,0.105c-0.993-0.315-1.894-0.862-2.784-1.405 c-0.787-0.48-1.597-0.981-2.131-1.733c-0.432-0.608-0.651-1.338-0.829-2.062C5.332,34.675,5.233,32.714,5.291,30.513z"
23+
/>
24+
<path
25+
fill="#ef4823"
26+
d="M43.2,12.47c0,1.43-0.01,2.86-0.01,4.29H5.13c-0.07-1.75-0.12-3.51,0.2-5.22 c0.34-1.91,1.18-3.79,2.68-5.02c2.12-1.74,5.75-2.16,8.48-1.92c4.42,0.41,9.5,0.57,13.93,0.3c2.37-0.14,4.78-0.41,7.09,0.1 c2.32,0.51,4.6,1.96,5.35,4.21C43.21,10.25,43.21,11.37,43.2,12.47z"
27+
/>
28+
<path
29+
fill="#010101"
30+
d="M43.488,9.604c-0.427-1.871-1.804-3.341-3.472-4.22c-2.002-1.055-4.279-1.24-6.505-1.166 c-2.44,0.081-4.865,0.301-7.308,0.313c-2.398,0.011-4.797-0.071-7.19-0.23c-2.063-0.137-4.086-0.389-6.15-0.121 c-1.848,0.24-3.746,0.783-5.207,1.988C6.088,7.46,5.203,9.44,4.844,11.403c-0.454,2.482-0.216,5.029-0.129,7.531 c0.089,2.549,0.139,5.1,0.133,7.65c-0.004,1.31-0.023,2.619-0.057,3.928c-0.056,2.352,0.065,4.755,0.743,7.023 c0.3,1.003,0.798,1.871,1.615,2.538c0.81,0.661,1.754,1.204,2.672,1.699c2.191,1.182,4.452,1.193,6.868,0.883 c2.528-0.325,5.015-0.497,7.566-0.415c2.618,0.084,5.229,0.319,7.848,0.398c2.127,0.064,4.362,0.113,6.417-0.526 c1.885-0.586,3.418-1.823,4.212-3.65c0.786-1.806,0.887-3.822,0.904-5.766c0.047-5.255,0.036-10.51,0.054-15.765 c0.004-1.282,0.009-2.564,0.013-3.847C43.706,11.926,43.748,10.744,43.488,9.604z M42.702,13.211 c-0.016,4.881-0.033,9.761-0.049,14.642c-0.007,2.219,0.071,4.459-0.078,6.674c-0.126,1.86-0.52,3.871-1.898,5.232 c-1.391,1.375-3.433,1.761-5.314,1.869c-2.309,0.132-4.636-0.031-6.941-0.169c-2.365-0.142-4.733-0.296-7.104-0.231 c-2.323,0.064-4.604,0.577-6.921,0.631c-1.159,0.027-2.307-0.122-3.373-0.599c-0.97-0.434-1.919-1.012-2.792-1.617 c-0.911-0.63-1.456-1.406-1.762-2.471c-0.316-1.099-0.507-2.238-0.605-3.376c-0.094-1.092-0.1-2.188-0.074-3.284 c0.123-4.804-0.023-9.595-0.183-14.396c-0.074-2.226-0.058-4.541,0.84-6.622c0.778-1.802,2.149-3.086,3.997-3.739 c1.709-0.604,3.56-0.785,5.364-0.7c2.129,0.1,4.249,0.331,6.382,0.408c2.234,0.081,4.473,0.095,6.707,0.01 c2.283-0.087,4.579-0.397,6.864-0.224c1.973,0.149,3.988,0.772,5.416,2.205C42.757,9.042,42.709,11.116,42.702,13.211z"
31+
/>
32+
<path
33+
fill="#010101"
34+
d="M5.466,17.153c2.599-0.219,5.233-0.115,7.838-0.079c2.536,0.035,5.072,0.094,7.608,0.157 c4.916,0.122,9.861,0.364,14.779,0.221c2.342-0.068,4.724-0.284,7.057,0.021c0.636,0.083,0.63-0.918,0-1 c-2.081-0.272-4.204-0.122-6.293-0.047c-2.388,0.086-4.779,0.034-7.167-0.007c-5.011-0.084-10.02-0.251-15.031-0.331 c-2.92-0.047-5.879-0.18-8.792,0.065C4.829,16.207,4.823,17.207,5.466,17.153L5.466,17.153z"
35+
/>
36+
<path
37+
fill="#010101"
38+
d="M19.548,21.837c0.011-0.221-0.164-0.422-0.367-0.482c-0.956-0.281-1.768,0.267-2.49,0.84 c-0.947,0.752-1.877,1.528-2.815,2.292c-0.499,0.407,0.212,1.11,0.707,0.707c0.72-0.587,1.441-1.174,2.161-1.761 c0.468-0.382,1.112-1.06,1.778-1.137c-0.267,5.011-0.633,10.026-0.436,15.047c0.025,0.641,1.025,0.645,1,0 C18.884,32.169,19.28,27.001,19.548,21.837z"
39+
/>
40+
<path
41+
fill="#010101"
42+
d="M33.574,21.289c-0.592-0.121-1.245-0.106-1.848-0.139c-2.617-0.145-5.241-0.103-7.853,0.11 c-0.637,0.052-0.643,1.052,0,1c1.592-0.13,3.187-0.199,4.785-0.197c0.778,0.001,1.556,0.018,2.333,0.051 c0.409,0.017,0.818,0.039,1.226,0.065c0.249,0.016,0.65-0.021,0.959,0.029c-0.09,0.21-0.274,0.496-0.332,0.61 c-0.171,0.334-0.346,0.666-0.522,0.997c-0.34,0.637-0.688,1.269-1.038,1.9c-0.722,1.3-1.457,2.593-2.159,3.904 c-1.296,2.423-2.519,4.938-3.146,7.628c-0.146,0.626,0.818,0.893,0.964,0.266c1.066-4.576,3.763-8.611,5.973-12.693 c0.269-0.496,0.533-0.995,0.791-1.497c0.192-0.375,0.573-0.886,0.547-1.332C34.23,21.585,33.945,21.365,33.574,21.289z"
43+
/>
44+
<path
45+
fill="#d6e5e5"
46+
d="M17.21,12.534c0.175,0.814,0.852,1.364,1.657,1.486c0.78,0.118,1.671-0.022,2.081-0.781 c0.366-0.678,0.24-1.545,0.19-2.281c-0.054-0.81-0.129-1.619-0.16-2.43c-0.024-0.641-1.025-0.645-1,0 c0.025,0.649,0.078,1.297,0.126,1.945c0.045,0.611,0.128,1.249,0.076,1.862c-0.018,0.212-0.068,0.451-0.244,0.589 c-0.17,0.133-0.417,0.147-0.623,0.142c-0.545-0.014-1.017-0.231-1.139-0.797C18.039,11.639,17.075,11.905,17.21,12.534 L17.21,12.534z"
47+
/>
48+
<path
49+
fill="#d6e5e5"
50+
d="M25.982,8.632c-0.044-0.635-1.017-0.65-1,0c0.054,0.784,0.075,1.57,0.058,2.356 c-0.012,0.585-0.012,1.308-0.404,1.786c-0.261,0.318-0.801,0.555-1.108,0.192c-0.341-0.402-0.302-1.102-0.333-1.595 c-0.058-0.91-0.115-1.819-0.173-2.729c-0.017-0.27-0.218-0.5-0.5-0.5c-0.257,0-0.517,0.229-0.5,0.5 c0.061,0.957,0.121,1.915,0.182,2.872c0.047,0.737,0.081,1.55,0.597,2.133c0.539,0.609,1.446,0.624,2.103,0.202 c0.732-0.471,1.007-1.282,1.096-2.11C26.11,10.716,26.052,9.656,25.982,8.632z"
51+
/>
52+
<path
53+
fill="#d6e5e5"
54+
d="M30.626,12.681c-0.801,0-1.597,0.067-2.39,0.168c-0.054-1.37-0.109-2.739-0.163-4.108 c-0.025-0.641-1.026-0.645-1,0c0.062,1.555,0.123,3.109,0.185,4.664c0.014,0.352,0.307,0.533,0.633,0.482 c0.905-0.142,1.819-0.205,2.735-0.205C31.27,13.681,31.271,12.681,30.626,12.681z"
55+
/>
56+
</svg>
57+
);
58+
}

src/svg/calendar/Outlook.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
export function Outlook({ title = 'Outlook Calendar' }: { title?: string }) {
2+
return (
3+
<svg
4+
xmlns="http://www.w3.org/2000/svg"
5+
x="0px"
6+
y="0px"
7+
width="20"
8+
height="20"
9+
viewBox="0 0 48 48"
10+
role="img"
11+
aria-labelledby="OutlookSvgTitle"
12+
style={{
13+
fillRule: 'evenodd',
14+
clipRule: 'evenodd',
15+
strokeLinejoin: 'round',
16+
strokeMiterlimit: 2,
17+
}}
18+
>
19+
<title id="OutlookSvgTitle">{title}</title>
20+
<path
21+
fill="#1976d2"
22+
d="M28,13h14.533C43.343,13,44,13.657,44,14.467v19.066C44,34.343,43.343,35,42.533,35H28V13z"
23+
/>
24+
<rect width="14" height="15.542" x="28" y="17.958" fill="#fff" />
25+
<polygon fill="#1976d2" points="27,44 4,39.5 4,8.5 27,4" />
26+
<path
27+
fill="#fff"
28+
d="M15.25,16.5c-3.176,0-5.75,3.358-5.75,7.5s2.574,7.5,5.75,7.5S21,28.142,21,24
29+
S18.426,16.5,15.25,16.5z M15,28.5c-1.657,0-3-2.015-3-4.5s1.343-4.5,3-4.5s3,2.015,3,4.5S16.657,28.5,15,28.5z"
30+
/>
31+
<rect width="2.7" height="2.9" x="28.047" y="29.737" fill="#1976d2" />
32+
<rect width="2.7" height="2.9" x="31.448" y="29.737" fill="#1976d2" />
33+
<rect width="2.7" height="2.9" x="34.849" y="29.737" fill="#1976d2" />
34+
<rect width="2.7" height="2.9" x="28.047" y="26.159" fill="#1976d2" />
35+
<rect width="2.7" height="2.9" x="31.448" y="26.159" fill="#1976d2" />
36+
<rect width="2.7" height="2.9" x="34.849" y="26.159" fill="#1976d2" />
37+
<rect width="2.7" height="2.9" x="38.25" y="26.159" fill="#1976d2" />
38+
<rect width="2.7" height="2.9" x="28.047" y="22.706" fill="#1976d2" />
39+
<rect width="2.7" height="2.9" x="31.448" y="22.706" fill="#1976d2" />
40+
<rect width="2.7" height="2.9" x="34.849" y="22.706" fill="#1976d2" />
41+
<rect width="2.7" height="2.9" x="38.25" y="22.706" fill="#1976d2" />
42+
<rect width="2.7" height="2.9" x="31.448" y="19.112" fill="#1976d2" />
43+
<rect width="2.7" height="2.9" x="34.849" y="19.112" fill="#1976d2" />
44+
<rect width="2.7" height="2.9" x="38.25" y="19.112" fill="#1976d2" />
45+
</svg>
46+
);
47+
}

0 commit comments

Comments
 (0)