-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(notifications): added notifications #176
Changes from all commits
549cb30
ab69324
44c3bf1
208d390
0282bf0
e83988c
581cd37
db8dcf3
cb46980
004c6e2
4932520
9e8e554
5dd9343
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export { default } from './InsightCard.svelte'; | ||
export { default } from './InsightCard.svelte' | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import { Query } from '$lib/api/executor.js' | ||
import { useStripeCtx } from '$lib/ctx/stripe/index.js' | ||
import { notifcation as notification } from '$ui/core/Notifications/index.js' | ||
import { notification } from '$ui/core/Notifications/index.js' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed typo in |
||
import type { ConfirmCardSetupData, SetupIntent, Stripe, Token } from '@stripe/stripe-js' | ||
import { mutateSubscribe } from './api.js' | ||
import { usePaymentFormCtx } from './state.js' | ||
|
@@ -160,7 +160,7 @@ export function usePaymentFlow() { | |
|
||
if (error) { | ||
notification.error(`Error during the payment`, { | ||
description: error.message || 'Please try again or contact our support', | ||
content: error.message || 'Please try again or contact our support', | ||
duration: 10000, | ||
}) | ||
trackEvent('payment_fail', { ...analytics, error_code: error.code || '3ds_error' }) | ||
|
@@ -212,7 +212,7 @@ export function usePaymentFlow() { | |
}) | ||
.catch((error) => { | ||
notification.error(`Error during the payment`, { | ||
description: 'Please try again or contact our support', | ||
content: 'Please try again or contact our support', | ||
}) | ||
trackEvent('payment_fail', { ...analytics, error_code: 'api_error' }) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<script lang="ts"> | ||
import { createEventDispatcher, type Snippet } from 'svelte' | ||
import Button from '$ui/core/Button/index.js' | ||
import Svg from '$ui/core/Svg/index.js' | ||
import { cn } from '$ui/utils/index.js' | ||
|
||
type Props = { | ||
icon: 'info' | 'checkmark-circle' | 'warning' | 'error' | ||
message: string | ||
content?: string | Snippet | ||
action?: { label: string; onClick: (event: MouseEvent) => void } | ||
class?: string | ||
} | ||
|
||
const { icon, message, content, action, class: className }: Props = $props() | ||
|
||
const dispatch = createEventDispatcher() | ||
|
||
const ICONS = { | ||
info: { class: 'fill-waterloo' }, | ||
'checkmark-circle': { class: 'fill-green' }, | ||
warning: { class: 'fill-orange', h: 14 }, | ||
error: { class: 'fill-red' }, | ||
} | ||
</script> | ||
|
||
<section | ||
role="alert" | ||
class={cn( | ||
'flex w-[460px] max-w-full gap-4 rounded-lg border bg-white pl-6 pr-2.5 pt-5 shadow', | ||
content && !action ? 'pb-6' : 'pb-5', | ||
className, | ||
)} | ||
> | ||
<figure class="flex h-6 w-4 center"> | ||
<Svg id={icon} {...ICONS[icon]} /> | ||
</figure> | ||
|
||
<div class="flex-1 items-start gap-2 column"> | ||
<h4 class="text-base font-medium text-rhino">{message}</h4> | ||
|
||
{#if content} | ||
<p class="text-base text-fiord"> | ||
{#if typeof content === 'function'} | ||
{@render content()} | ||
{:else} | ||
{content} | ||
{/if} | ||
</p> | ||
{/if} | ||
|
||
{#if action} | ||
<Button variant="fill" class="mt-1" onclick={action.onClick}> | ||
{action.label} | ||
</Button> | ||
{/if} | ||
</div> | ||
|
||
<Button | ||
aria-label="Close notification" | ||
icon="close" | ||
iconSize={10} | ||
class="-ml-2 -mt-2.5 flex size-5 rounded !fill-waterloo center hover:bg-porcelain xs:size-8" | ||
onclick={() => dispatch('closeToast')} | ||
/> | ||
</section> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,14 @@ | ||
<script lang="ts"> | ||
import { BROWSER } from 'esm-env' | ||
import { Toaster } from 'svelte-sonner' | ||
import { useDeviceCtx } from '$lib/ctx/device/index.svelte.js' | ||
|
||
const { device } = useDeviceCtx() | ||
</script> | ||
|
||
{#if BROWSER} | ||
<Toaster | ||
position="bottom-left" | ||
toastOptions={{ | ||
unstyled: true, | ||
classes: { | ||
toast: 'border rounded shadow bg-white row p-4 gap-2', | ||
title: 'text-black font-medium', | ||
description: 'text-waterloo', | ||
success: 'fill-green', | ||
}, | ||
}} | ||
position={device.$.isMobile ? 'top-center' : 'bottom-left'} | ||
toastOptions={{ unstyled: true }} | ||
></Toaster> | ||
{/if} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,32 @@ | ||
import type { ComponentProps, ComponentType } from 'svelte' | ||
import { toast } from 'svelte-sonner' | ||
import Component from './Notification.svelte' | ||
|
||
export { default } from './Notifications.svelte' | ||
export { toast as notifcation } from 'svelte-sonner' | ||
|
||
type TOptions = Omit<ComponentProps<Component>, 'icon' | 'message'> & { duration?: number } | ||
type TIcon = ComponentProps<Component>['icon'] | ||
|
||
function createToast(icon: TIcon, message: string, { duration = 5000, ...options }: TOptions = {}) { | ||
return toast.custom(Component as unknown as ComponentType, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had to do this because of the different types of components in Svelte 4 and Svelte 5 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error I encountered when trying to pass a component without type conversion:
|
||
duration, | ||
componentProps: { ...options, icon, message }, | ||
}) | ||
} | ||
|
||
const createNotificationType = | ||
(icon: TIcon) => | ||
(...rest: [message: string, options?: TOptions]) => | ||
createToast(icon, ...rest) | ||
|
||
const notification: Record< | ||
'info' | 'error' | 'warning' | 'success', | ||
(message: string, options?: TOptions) => string | number | ||
> = { | ||
info: createNotificationType('info'), | ||
error: createNotificationType('error'), | ||
warning: createNotificationType('warning'), | ||
success: createNotificationType('checkmark-circle'), | ||
} | ||
|
||
export { notification } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was hanged automatically by
eslint --fix