B2B-88: add starter kit structure and elements
This commit is contained in:
2
packages/features/notifications/src/hooks/index.ts
Normal file
2
packages/features/notifications/src/hooks/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './use-fetch-notifications';
|
||||
export * from './use-dismiss-notification';
|
||||
@@ -0,0 +1,21 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useSupabase } from '@kit/supabase/hooks/use-supabase';
|
||||
|
||||
export function useDismissNotification() {
|
||||
const client = useSupabase();
|
||||
|
||||
return useCallback(
|
||||
async (notification: number) => {
|
||||
const { error } = await client
|
||||
.from('notifications')
|
||||
.update({ dismissed: true })
|
||||
.eq('id', notification);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
[client],
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { useSupabase } from '@kit/supabase/hooks/use-supabase';
|
||||
|
||||
import { useNotificationsStream } from './use-notifications-stream';
|
||||
|
||||
type Notification = {
|
||||
id: number;
|
||||
body: string;
|
||||
dismissed: boolean;
|
||||
type: 'info' | 'warning' | 'error';
|
||||
created_at: string;
|
||||
link: string | null;
|
||||
};
|
||||
|
||||
export function useFetchNotifications({
|
||||
onNotifications,
|
||||
accountIds,
|
||||
realtime,
|
||||
}: {
|
||||
onNotifications: (notifications: Notification[]) => unknown;
|
||||
accountIds: string[];
|
||||
realtime: boolean;
|
||||
}) {
|
||||
const { data: initialNotifications } = useFetchInitialNotifications({
|
||||
accountIds,
|
||||
});
|
||||
|
||||
useNotificationsStream({
|
||||
onNotifications,
|
||||
accountIds,
|
||||
enabled: realtime,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (initialNotifications) {
|
||||
onNotifications(initialNotifications);
|
||||
}
|
||||
}, [initialNotifications, onNotifications]);
|
||||
}
|
||||
|
||||
function useFetchInitialNotifications(props: { accountIds: string[] }) {
|
||||
const client = useSupabase();
|
||||
const now = new Date().toISOString();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['notifications', ...props.accountIds],
|
||||
queryFn: async () => {
|
||||
const { data } = await client
|
||||
.from('notifications')
|
||||
.select(
|
||||
`id,
|
||||
body,
|
||||
dismissed,
|
||||
type,
|
||||
created_at,
|
||||
link
|
||||
`,
|
||||
)
|
||||
.in('account_id', props.accountIds)
|
||||
.eq('dismissed', false)
|
||||
.gt('expires_at', now)
|
||||
.order('created_at', { ascending: false })
|
||||
.limit(10);
|
||||
|
||||
return data;
|
||||
},
|
||||
refetchOnMount: false,
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { useSupabase } from '@kit/supabase/hooks/use-supabase';
|
||||
|
||||
type Notification = {
|
||||
id: number;
|
||||
body: string;
|
||||
dismissed: boolean;
|
||||
type: 'info' | 'warning' | 'error';
|
||||
created_at: string;
|
||||
link: string | null;
|
||||
};
|
||||
|
||||
export function useNotificationsStream(params: {
|
||||
onNotifications: (notifications: Notification[]) => void;
|
||||
accountIds: string[];
|
||||
enabled: boolean;
|
||||
}) {
|
||||
const client = useSupabase();
|
||||
|
||||
const { data: subscription } = useQuery({
|
||||
enabled: params.enabled,
|
||||
queryKey: ['realtime-notifications', ...params.accountIds],
|
||||
queryFn: () => {
|
||||
const channel = client.channel('notifications-channel');
|
||||
|
||||
return channel
|
||||
.on(
|
||||
'postgres_changes',
|
||||
{
|
||||
event: 'INSERT',
|
||||
schema: 'public',
|
||||
filter: `account_id=in.(${params.accountIds.join(', ')})`,
|
||||
table: 'notifications',
|
||||
},
|
||||
(payload) => {
|
||||
params.onNotifications([payload.new as Notification]);
|
||||
},
|
||||
)
|
||||
.subscribe();
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
void subscription?.unsubscribe();
|
||||
};
|
||||
}, [subscription]);
|
||||
}
|
||||
Reference in New Issue
Block a user