portfolio/components/ui/Views.tsx

64 lines
1.8 KiB
TypeScript
Raw Normal View History

2023-07-29 22:40:36 +00:00
'use client'
import {createPagesBrowserClient} from '@supabase/auth-helpers-nextjs'
2023-04-10 22:58:18 +00:00
import {ElementType, useEffect} from 'react'
import useSWR, {useSWRConfig} from 'swr'
2023-01-17 21:24:16 +00:00
import fetcher from '@/lib/fetcher'
2023-01-26 22:07:11 +00:00
import {numberFormat} from '@/lib/numberFormat'
2023-01-26 23:29:39 +00:00
type ViewsProps = {
as?: ElementType
slug: string
className?: string
shouldUpdateViews?: boolean
2023-04-11 16:48:47 +00:00
shouldRender?: boolean
2023-01-26 23:29:39 +00:00
}
2023-04-11 16:48:47 +00:00
export function Views({as: Component = 'span', slug, className, shouldUpdateViews = true, shouldRender = true}: ViewsProps) {
2023-07-30 18:47:25 +00:00
const supabase = createPagesBrowserClient()
2023-04-10 22:58:18 +00:00
const {data} = useSWR(`/api/views/${slug}`, fetcher) as { data: { views: number } }
const {mutate} = useSWRConfig()
2023-01-17 21:24:16 +00:00
2023-04-10 00:08:52 +00:00
useEffect(() => {
2023-04-10 22:58:18 +00:00
if (shouldUpdateViews) {
// subscribe to analytics table and react to updates at row level
2023-07-29 22:40:36 +00:00
const sub = supabase
2023-04-10 22:58:18 +00:00
.channel('any')
.on('postgres_changes', {
event: 'UPDATE',
schema: 'public',
table: 'analytics',
filter: `slug=eq.${slug}`
}, () => {
mutate(`/api/views/${slug}`)
})
.subscribe();
return () => {
sub.unsubscribe()
}
2023-04-10 00:08:52 +00:00
}
}, [])
2023-01-17 21:24:16 +00:00
useEffect(() => {
if (shouldUpdateViews) {
2023-04-10 00:08:52 +00:00
const registerView = async () => {
2023-04-10 22:58:18 +00:00
await fetcher(`/api/views/${slug}`,
2023-04-10 00:08:52 +00:00
{
method: 'POST'
}
)
}
2023-04-10 00:08:52 +00:00
2023-04-13 16:36:52 +00:00
registerView().then(() => mutate(`/api/views/${slug}`))
2023-01-26 23:29:39 +00:00
}
2023-04-10 00:08:52 +00:00
}, [])
2023-01-17 21:24:16 +00:00
2023-04-11 16:48:47 +00:00
if (!shouldRender) return null
2023-01-17 21:24:16 +00:00
return (
2023-01-26 23:29:39 +00:00
<Component className={className}>
2023-04-10 22:58:18 +00:00
{` · ${data?.views > 0 ? numberFormat(data.views) : '—'} views`}
2023-01-17 21:24:16 +00:00
</Component>
)
}