Skip to content

Commit eb9a6ad

Browse files
authored
Feat: Add congrats modal when making event live (#1031)
1 parent dc0cff6 commit eb9a6ad

File tree

36 files changed

+1416
-659
lines changed

36 files changed

+1416
-659
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ prompts/
1717

1818
/playground/**
1919
/playground/
20+
21+
/plans/**
22+
/plans

frontend/src/components/layouts/Event/index.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {confirmationDialog} from "../../../utilites/confirmationDialog.tsx";
3838
import {useUpdateEventStatus} from "../../../mutations/useUpdateEventStatus.ts";
3939
import {showError, showSuccess} from "../../../utilites/notifications.tsx";
4040
import {ShareModal} from "../../modals/ShareModal";
41+
import {EventLiveCelebrationModal} from "../../modals/EventLiveCelebrationModal";
4142
import {useDisclosure} from "@mantine/hooks";
4243
import {TopBarButton} from "../../common/TopBarButton";
4344
import {useWindowWidth} from "../../../hooks/useWindowWidth.ts";
@@ -52,6 +53,7 @@ const EventLayout = () => {
5253
const {eventId} = useParams();
5354

5455
const [opened, {open, close}] = useDisclosure(false);
56+
const [celebrationOpened, {open: openCelebration, close: closeCelebration}] = useDisclosure(false);
5557

5658
const statusToggleMutation = useUpdateEventStatus();
5759

@@ -145,6 +147,7 @@ const EventLayout = () => {
145147
];
146148

147149
const handleStatusToggle = () => {
150+
const isGoingLive = event?.status !== 'LIVE';
148151
const message = event?.status === 'LIVE'
149152
? t`Are you sure you want to make this event draft? This will make the event invisible to the public`
150153
: t`Are you sure you want to make this event public? This will make the event visible to the public`;
@@ -155,7 +158,11 @@ const EventLayout = () => {
155158
status: event?.status === 'LIVE' ? 'DRAFT' : 'LIVE'
156159
}, {
157160
onSuccess: () => {
158-
showSuccess(t`Event status updated`);
161+
if (isGoingLive) {
162+
openCelebration();
163+
} else {
164+
showSuccess(t`Event status updated`);
165+
}
159166
},
160167
onError: (error: any) => {
161168
showError(error?.response?.data?.message || t`Event status update failed. Please try again later`);
@@ -200,13 +207,21 @@ const EventLayout = () => {
200207
{t`Share Event`}
201208
</Button>
202209

203-
{event && <ShareModal
210+
<ShareModal
204211
url={eventHomepageUrl(event)}
205212
title={event.title}
206213
modalTitle={t`Share Event`}
207214
opened={opened}
208215
onClose={close}
209-
/>}
216+
/>
217+
218+
<EventLiveCelebrationModal
219+
opened={celebrationOpened}
220+
onClose={closeCelebration}
221+
url={eventHomepageUrl(event)}
222+
eventTitle={event.title}
223+
eventId={String(event.id)}
224+
/>
210225
</>
211226
)}
212227
</div>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
.modal {
2+
:global(.mantine-Modal-body) {
3+
padding: 0;
4+
}
5+
}
6+
7+
.content {
8+
display: flex;
9+
flex-direction: column;
10+
align-items: center;
11+
padding: 2rem;
12+
text-align: center;
13+
}
14+
15+
.celebrationEmoji {
16+
font-size: 4rem;
17+
line-height: 1;
18+
margin-bottom: 1rem;
19+
animation: celebrate 0.6s ease-out;
20+
}
21+
22+
@keyframes celebrate {
23+
0% {
24+
transform: scale(0);
25+
opacity: 0;
26+
}
27+
50% {
28+
transform: scale(1.2);
29+
}
30+
70% {
31+
transform: scale(0.9);
32+
}
33+
100% {
34+
transform: scale(1);
35+
opacity: 1;
36+
}
37+
}
38+
39+
.title {
40+
font-size: 1.5rem;
41+
font-weight: 700;
42+
color: var(--mantine-color-dark-7);
43+
margin-bottom: 0.5rem;
44+
}
45+
46+
.subtitle {
47+
color: var(--mantine-color-dimmed);
48+
font-size: 0.95rem;
49+
margin-bottom: 1.5rem;
50+
}
51+
52+
.urlSection {
53+
width: 100%;
54+
margin-bottom: 1.5rem;
55+
}
56+
57+
.urlInput {
58+
padding-right: 110px;
59+
font-size: 0.875rem;
60+
background: var(--mantine-color-gray-0);
61+
}
62+
63+
.actions {
64+
display: flex;
65+
flex-direction: column;
66+
gap: 0.5rem;
67+
width: 100%;
68+
margin-bottom: 1rem;
69+
}
70+
71+
.actionButton {
72+
width: 100%;
73+
}
74+
75+
.doneButton {
76+
width: 100%;
77+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import {Button, CopyButton, Modal, Text, TextInput, Tooltip} from '@mantine/core';
2+
import {useDisclosure} from '@mantine/hooks';
3+
import {
4+
IconCheck,
5+
IconCode,
6+
IconCopy,
7+
IconExternalLink,
8+
IconShare
9+
} from '@tabler/icons-react';
10+
import {t} from "@lingui/macro";
11+
import {NavLink} from "react-router";
12+
import {ShareModal} from "../ShareModal";
13+
import classes from './EventLiveCelebrationModal.module.scss';
14+
15+
interface EventLiveCelebrationModalProps {
16+
opened: boolean;
17+
onClose: () => void;
18+
url: string;
19+
eventTitle: string;
20+
eventId: string;
21+
}
22+
23+
export const EventLiveCelebrationModal = ({
24+
opened,
25+
onClose,
26+
url,
27+
eventTitle,
28+
eventId
29+
}: EventLiveCelebrationModalProps) => {
30+
const [shareModalOpened, {open: openShareModal, close: closeShareModal}] = useDisclosure(false);
31+
32+
return (
33+
<>
34+
<Modal
35+
opened={opened}
36+
onClose={onClose}
37+
centered
38+
size="md"
39+
withCloseButton={false}
40+
className={classes.modal}
41+
>
42+
<div className={classes.content}>
43+
<div className={classes.celebrationEmoji}>
44+
🎉
45+
</div>
46+
47+
<Text className={classes.title}>
48+
{t`Your event is live!`}
49+
</Text>
50+
51+
<Text className={classes.subtitle}>
52+
{t`Congratulations! Your event is now visible to the public.`}
53+
</Text>
54+
55+
<div className={classes.urlSection}>
56+
<TextInput
57+
value={url}
58+
readOnly
59+
size="md"
60+
classNames={{
61+
input: classes.urlInput
62+
}}
63+
rightSectionWidth={100}
64+
rightSection={
65+
<CopyButton value={url} timeout={2000}>
66+
{({copied, copy}) => (
67+
<Tooltip label={copied ? t`Copied!` : t`Copy link`}>
68+
<Button
69+
variant="light"
70+
color={copied ? 'teal' : 'gray'}
71+
onClick={copy}
72+
size="sm"
73+
leftSection={copied ? <IconCheck size={14}/> : <IconCopy size={14}/>}
74+
>
75+
{copied ? t`Copied` : t`Copy`}
76+
</Button>
77+
</Tooltip>
78+
)}
79+
</CopyButton>
80+
}
81+
/>
82+
</div>
83+
84+
<div className={classes.actions}>
85+
<Button
86+
component="a"
87+
href={url}
88+
target="_blank"
89+
variant="light"
90+
leftSection={<IconExternalLink size={16}/>}
91+
className={classes.actionButton}
92+
>
93+
{t`View Event Page`}
94+
</Button>
95+
96+
<Button
97+
variant="light"
98+
leftSection={<IconShare size={16}/>}
99+
onClick={openShareModal}
100+
className={classes.actionButton}
101+
>
102+
{t`Share Event`}
103+
</Button>
104+
105+
<Button
106+
component={NavLink}
107+
to={`/manage/event/${eventId}/widget`}
108+
variant="light"
109+
leftSection={<IconCode size={16}/>}
110+
onClick={onClose}
111+
className={classes.actionButton}
112+
>
113+
{t`Embed Widget`}
114+
</Button>
115+
</div>
116+
117+
<Button
118+
onClick={onClose}
119+
variant="filled"
120+
size="md"
121+
className={classes.doneButton}
122+
>
123+
{t`Done`}
124+
</Button>
125+
</div>
126+
</Modal>
127+
128+
<ShareModal
129+
url={url}
130+
title={eventTitle}
131+
modalTitle={t`Share Event`}
132+
opened={shareModalOpened}
133+
onClose={closeShareModal}
134+
/>
135+
</>
136+
);
137+
};

frontend/src/locales/de.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)