-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(dashboard,web): opt-in welcome modal (#6920)
- Loading branch information
Showing
12 changed files
with
223 additions
and
23 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { HTMLAttributes } from 'react'; | ||
|
||
export const CircleCheck = (props: HTMLAttributes<HTMLOrSVGElement>) => { | ||
return ( | ||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 17 16" fill="none" {...props}> | ||
<path | ||
d="M6.50004 7.99999L7.83337 9.33333L10.5 6.66666M15.1667 7.99999C15.1667 11.6819 12.1819 14.6667 8.50004 14.6667C4.81814 14.6667 1.83337 11.6819 1.83337 7.99999C1.83337 4.3181 4.81814 1.33333 8.50004 1.33333C12.1819 1.33333 15.1667 4.3181 15.1667 7.99999Z" | ||
stroke="#1FC16B" | ||
stroke-width="1.5" | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
/> | ||
</svg> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import type { HTMLAttributes } from 'react'; | ||
|
||
export const OptInArrow = (props: HTMLAttributes<HTMLOrSVGElement>) => { | ||
return ( | ||
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="84" viewBox="0 0 78 84" fill="none" {...props}> | ||
<path | ||
d="M7 65.7276C11.3062 66.8823 25.7351 69.45 26.0443 60.8367C26.1319 58.3972 23.3702 54.4428 20.443 55.822C16.5397 57.6612 20.5868 62.494 23.2437 63.0655C30.243 64.5709 36.5796 57.4272 38.336 51.4573C39.8111 46.444 38.6183 40.9473 36.8112 36.1965C35.9635 33.9679 34.2644 32.4464 33.326 30.3459C31.8742 27.0965 35.4308 30.6525 37.2158 31.4294C40.8631 33.0167 34.8603 30.6219 33.606 30.0673C31.5365 29.1524 30.6469 34.7193 29.9652 36.7537" | ||
stroke="#1FC16B" | ||
stroke-linecap="round" | ||
/> | ||
</svg> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { HTMLAttributes } from 'react'; | ||
|
||
export const PartyPopover = (props: HTMLAttributes<HTMLOrSVGElement>) => { | ||
return ( | ||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 21 20" fill="none" {...props}> | ||
<path | ||
d="M5.33329 9.4167L2.16663 18.3334L11.0833 15.175M3.83329 2.49999H3.84163M18.8333 6.66666H18.8416M13 1.66666H13.0083M18.8333 16.6667H18.8416M18.8333 1.66666L16.9666 2.29166C16.4353 2.46865 15.9819 2.82469 15.684 3.29893C15.3861 3.77316 15.2621 4.33615 15.3333 4.89166C15.4166 5.60832 14.8583 6.24999 14.125 6.24999H13.8083C13.0916 6.24999 12.475 6.74999 12.3416 7.44999L12.1666 8.33332M18.8333 10.8333L18.15 10.5583C17.4333 10.2749 16.6333 10.7249 16.5 11.4833C16.4083 12.0666 15.9 12.4999 15.3083 12.4999H14.6666M9.66663 1.66666L9.94163 2.34999C10.225 3.06666 9.77496 3.86666 9.01663 3.99999C8.43329 4.08332 7.99996 4.59999 7.99996 5.19166V5.83332M9.66664 10.8333C11.275 12.4417 12.025 14.3083 11.3333 15C10.6416 15.6917 8.77497 14.9417 7.16664 13.3333C5.55831 11.725 4.80831 9.85834 5.49997 9.16667C6.19164 8.475 8.05831 9.225 9.66664 10.8333Z" | ||
stroke="white" | ||
stroke-width="1.33" | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
/> | ||
</svg> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { CircleCheck } from '@/components/icons/circle-check'; | ||
import { PartyPopover } from '@/components/icons/party-popover'; | ||
import { OptInArrow } from '@/components/icons/opt-in-arrow'; | ||
import { Button } from '@/components/primitives/button'; | ||
import { | ||
Dialog, | ||
DialogClose, | ||
DialogDescription, | ||
DialogContent, | ||
DialogOverlay, | ||
DialogPortal, | ||
DialogTitle, | ||
} from '@/components/primitives/dialog'; | ||
import { RiCustomerService2Line } from 'react-icons/ri'; | ||
import { useNewDashboardOptIn } from '@/hooks/use-new-dashboard-opt-in'; | ||
import { NewDashboardOptInStatusEnum } from '@novu/shared'; | ||
|
||
export const OptInModal = () => { | ||
const { status, optIn } = useNewDashboardOptIn(); | ||
|
||
const isOptedIn = status === NewDashboardOptInStatusEnum.OPTED_IN; | ||
|
||
if (isOptedIn) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Dialog modal open={!isOptedIn} onOpenChange={optIn}> | ||
<DialogPortal> | ||
<DialogOverlay /> | ||
<DialogContent className="p-0"> | ||
<div className="flex items-start gap-4 self-stretch"> | ||
<Image /> | ||
<div className="flex w-[383px] flex-col items-start"> | ||
<Header /> | ||
<CheckBulletPoint | ||
content={ | ||
<span> | ||
We're still building and welcome your feedback — share your thoughts using{' '} | ||
<RiCustomerService2Line className="inline" /> in the top right. | ||
</span> | ||
} | ||
/> | ||
<CheckBulletPoint content="You can switch back to the legacy UI anytime from the user profile menu in the top right." /> | ||
<CheckBulletPoint content="Create workflows with in-app steps on the new dashboard; support for more steps is coming soon." /> | ||
<Footer /> | ||
</div> | ||
</div> | ||
</DialogContent> | ||
</DialogPortal> | ||
</Dialog> | ||
); | ||
}; | ||
|
||
const Image = () => ( | ||
<div className="relative"> | ||
<img src="/public/images/opt-in.png" alt="New Dashboard Preview" /> | ||
<div | ||
className="absolute inset-0 rounded-lg" | ||
style={{ background: 'linear-gradient(163deg, rgba(255, 255, 255, 0.00) 7.65%, #FFF 92.93%)' }} | ||
/> | ||
<div className="absolute bottom-[13px] left-[13px] flex w-[158.5px] flex-col items-start"> | ||
<span className="text-success text-[10px] font-normal italic">We're doing light mode for now!</span> | ||
<OptInArrow className="absolute bottom-[-11.505px] left-[152.5px]" /> | ||
</div> | ||
</div> | ||
); | ||
|
||
const Header = () => ( | ||
<div className="flex items-start justify-between gap-1 self-stretch p-3"> | ||
<div className="flex flex-1 flex-col items-start gap-1"> | ||
<DialogTitle className="text-lg font-medium">Thanks for opting-in! 🎉</DialogTitle> | ||
<DialogDescription className="text-foreground-400 text-xs font-normal"> | ||
Get an early look at our enhanced dashboard. | ||
</DialogDescription> | ||
</div> | ||
</div> | ||
); | ||
|
||
const CheckBulletPoint = ({ content }: { content: React.ReactNode }) => ( | ||
<div className="flex items-center gap-1 px-3 py-2"> | ||
<CircleCheck /> | ||
<div className="text-foreground-500 px-2 py-1 text-xs font-medium">{content}</div> | ||
</div> | ||
); | ||
|
||
const Footer = () => ( | ||
<div className="flex w-full justify-end p-3"> | ||
<DialogClose asChild aria-label="Close"> | ||
<Button type="button" size="sm" variant="primary" className="gap-2 p-2"> | ||
I'm in <PartyPopover /> | ||
</Button> | ||
</DialogClose> | ||
</div> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { useUser } from '@clerk/clerk-react'; | ||
import { NewDashboardOptInStatusEnum } from '@novu/shared'; | ||
|
||
export function useNewDashboardOptIn() { | ||
const { user } = useUser(); | ||
|
||
const updateUserOptInStatus = (status: NewDashboardOptInStatusEnum) => { | ||
if (!user) return; | ||
|
||
user.update({ | ||
unsafeMetadata: { | ||
...user.unsafeMetadata, | ||
newDashboardOptInStatus: status, | ||
}, | ||
}); | ||
}; | ||
|
||
const getCurrentOptInStatus = () => { | ||
if (!user) return null; | ||
|
||
return user.unsafeMetadata?.newDashboardOptInStatus || null; | ||
}; | ||
|
||
const redirectToNewDashboard = () => { | ||
const newDashboardUrl = process.env.NEW_DASHBOARD_URL; | ||
if (!newDashboardUrl) return; | ||
|
||
window.location.href = newDashboardUrl; | ||
}; | ||
|
||
const optIn = () => { | ||
updateUserOptInStatus(NewDashboardOptInStatusEnum.OPTED_IN); | ||
}; | ||
|
||
const optOut = () => { | ||
updateUserOptInStatus(NewDashboardOptInStatusEnum.OPTED_OUT); | ||
}; | ||
|
||
const dismiss = () => { | ||
updateUserOptInStatus(NewDashboardOptInStatusEnum.DISMISSED); | ||
}; | ||
|
||
return { | ||
optIn, | ||
optOut, | ||
dismiss, | ||
status: getCurrentOptInStatus(), | ||
redirectToNewDashboard, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.