feat: display unread
This commit is contained in:
parent
70849f321d
commit
df1bff6ddf
|
|
@ -6,26 +6,20 @@ import { useState } from 'react'
|
||||||
export function FeedList({ type }: { type: string }) {
|
export function FeedList({ type }: { type: string }) {
|
||||||
const feeds = useFeeds()
|
const feeds = useFeeds()
|
||||||
|
|
||||||
const categories = {}
|
|
||||||
feeds.data?.forEach((feed) => {
|
|
||||||
if (!categories[feed.category.title]) {
|
|
||||||
categories[feed.category.title] = []
|
|
||||||
}
|
|
||||||
categories[feed.category.title].push(feed)
|
|
||||||
})
|
|
||||||
console.log('categories', categories)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-64 px-5">
|
<div className="w-64 px-5">
|
||||||
<div className="font-bold my-2">{type}</div>
|
<div className='flex items-center justify-between mt-2 mb-3'>
|
||||||
{Object.keys(categories).map((category) => (
|
<div className="font-bold">{type}</div>
|
||||||
<FeedCategory key={category} name={category} list={categories[category]} />
|
<div className='text-sm text-zinc-500 ml-2'>{feeds.data?.unread}</div>
|
||||||
|
</div>
|
||||||
|
{Object.keys(feeds.data?.list || {}).map((category) => (
|
||||||
|
<FeedCategory key={category} name={category} data={feeds.data?.list[category]} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function FeedCategory({ name, list }: { name: string; list: any[] }) {
|
function FeedCategory({ name, data }: { name: string; data: any }) {
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -33,9 +27,12 @@ function FeedCategory({ name, list }: { name: string; list: any[] }) {
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={(o) => setOpen(o)}
|
onOpenChange={(o) => setOpen(o)}
|
||||||
>
|
>
|
||||||
<CollapsibleTrigger className="flex items-center text-sm font-medium leading-loose py-[2px] w-full [&>i]:data-[state=open]:rotate-90">
|
<CollapsibleTrigger className="flex items-center justify-between font-medium text-sm leading-loose py-[2px] w-full [&_.i-mingcute-right-fill]:data-[state=open]:rotate-90">
|
||||||
<i className="i-mingcute-right-fill mr-2 transition-transform" />
|
<div className='flex items-center min-w-0'>
|
||||||
<span className='truncate'>{name}</span>
|
<i className="i-mingcute-right-fill mr-2 transition-transform" />
|
||||||
|
<span className='truncate'>{name}</span>
|
||||||
|
</div>
|
||||||
|
{!!data.unread && <div className='text-xs text-zinc-500 ml-2'>{data.unread}</div>}
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{open && (
|
{open && (
|
||||||
|
|
@ -60,16 +57,19 @@ function FeedCategory({ name, list }: { name: string; list: any[] }) {
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{list.map((feed) => (
|
{data.list.map((feed) => (
|
||||||
<div
|
<div
|
||||||
key={feed.id}
|
key={feed.id}
|
||||||
className="flex items-center my-2 text-sm font-medium leading-loose w-full pl-6"
|
className="flex items-center justify-between my-2 text-sm font-medium leading-loose w-full pl-6"
|
||||||
>
|
>
|
||||||
<img
|
<div className='flex items-center min-w-0'>
|
||||||
src={`https://icons.duckduckgo.com/ip3/${new URL(feed.site_url).host}.ico`}
|
<img
|
||||||
className="w-4 h-4 mr-2 rounded-sm"
|
src={`https://icons.duckduckgo.com/ip3/${new URL(feed.site_url).host}.ico`}
|
||||||
/>
|
className="w-4 h-4 mr-2 rounded-sm"
|
||||||
<div className='truncate'>{feed.title}</div>
|
/>
|
||||||
|
<div className='truncate'>{feed.title}</div>
|
||||||
|
</div>
|
||||||
|
{!!feed.unread && <div className='text-xs text-zinc-500 ml-2'>{feed.unread}</div>}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</m.div>
|
</m.div>
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,34 @@ export const useFeeds = () =>
|
||||||
useQuery({
|
useQuery({
|
||||||
queryKey: ['feeds'],
|
queryKey: ['feeds'],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
return (await fetch(`${import.meta.env.VITE_MINIFLUX_ENDPOINT}/v1/feeds`, {
|
const feeds = await (await fetch(`${import.meta.env.VITE_MINIFLUX_ENDPOINT}/v1/feeds`, {
|
||||||
headers: {
|
headers: {
|
||||||
'X-Auth-Token': import.meta.env.VITE_MINIFLUX_TOKEN
|
'X-Auth-Token': import.meta.env.VITE_MINIFLUX_TOKEN
|
||||||
}
|
}
|
||||||
})).json()
|
})).json()
|
||||||
|
const counters = await (await fetch(`${import.meta.env.VITE_MINIFLUX_ENDPOINT}/v1/feeds/counters`, {
|
||||||
|
headers: {
|
||||||
|
'X-Auth-Token': import.meta.env.VITE_MINIFLUX_TOKEN
|
||||||
|
}
|
||||||
|
})).json()
|
||||||
|
|
||||||
|
const categories = {
|
||||||
|
list: {},
|
||||||
|
unread: 0,
|
||||||
|
}
|
||||||
|
feeds?.forEach((feed) => {
|
||||||
|
if (!categories.list[feed.category.title]) {
|
||||||
|
categories.list[feed.category.title] = {
|
||||||
|
list: [],
|
||||||
|
unread: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const unread = counters.unreads[feed.id] || 0
|
||||||
|
feed.unread = unread
|
||||||
|
categories.list[feed.category.title].list.push(feed)
|
||||||
|
categories.list[feed.category.title].unread += unread
|
||||||
|
categories.unread += unread
|
||||||
|
})
|
||||||
|
return categories
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue