Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions src/app/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import {User, Newspaper, MessageCircle, BookUser} from 'lucide-react';
import {useTranslations} from 'use-intl';
import {cn} from '@/lib/utils';
import {Link, useLocation} from 'react-router';
import {ReactNode} from 'react';
import {ReactNode, useMemo} from 'react';
import {useQuery} from '@tanstack/react-query';
import {useBackend} from '@/backend.context';
import {NotificationDotIcon} from '@/components/ui/icons/notification-dot';

interface MenuItem {
path: string;
title: string;
icon: ReactNode;
releaseTag?: string;
hasNotify?: boolean;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit overcomplicated way to do so.

It's could be better to have async callback instead of hasNotify Boolean.

}

type RuntimeMenuOptions = Partial<
Record<MenuItem['title'], Pick<MenuItem, 'hasNotify'>>
>;

const MENURAIL_ITEMS: MenuItem[] = [
{path: '/', title: 'profile', icon: <User />},
{path: '/feed', title: 'feed', icon: <BookUser />},
Expand All @@ -30,9 +38,41 @@ export function MenuRail() {
const t = useTranslations('menu');
const {pathname} = useLocation();

const backend = useBackend();
const feedQuery = useQuery({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we do that request here, we should not repeat it on the tab page as well, I think.

Currently we invoke request 2 times, so user have to wait until feed is loaded even tho it was already loaded for notification.

You can create an issue on that and we will merge PR without fixing it instantly, we just need to remember that.

queryKey: ['feedQueue'],
queryFn: () => backend.getFeedQueue(),
});

const hasFeedNotify = useMemo(
() =>
feedQuery.data?.ok
? feedQuery.data.data.entries.some(item => item.isRequest)
: false,
[feedQuery.data],
);

const runtimeMenuOptions = useMemo<RuntimeMenuOptions>(
() => ({
feed: {
hasNotify: hasFeedNotify,
},
}),
[hasFeedNotify],
);

const menuItems = useMemo(
() =>
MENURAIL_ITEMS.map(item => ({
...item,
hasNotify: runtimeMenuOptions[item.title]?.hasNotify,
})),
[runtimeMenuOptions],
);

return (
<div className="h-full p-1 flex flex-col gap-1.5 lg:p-4 lg:min-w-55">
{MENURAIL_ITEMS.map(item => (
{menuItems.map(item => (
<Link key={item.path} to={item.path}>
<Button
variant="ghost"
Expand All @@ -46,6 +86,9 @@ export function MenuRail() {
<p className="hidden lg:block">
{t(item.title as Parameters<typeof t>[0])}
</p>{' '}
{item.hasNotify && (
<NotificationDotIcon className="hidden size-3 lg:block" />
)}
<Badge hidden={!item.releaseTag} variant="secondary">
{item.releaseTag}
</Badge>
Expand Down
1 change: 1 addition & 0 deletions src/components/ui/icons/index.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 'Ui' folder is reserved for Shadcn components, you shouldn't put it there.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {NotificationDotIcon} from './notification-dot';
14 changes: 14 additions & 0 deletions src/components/ui/icons/notification-dot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';

export function NotificationDotIcon(props: React.ComponentProps<'svg'>) {
return (
<svg
viewBox="0 0 16 16"
fill="none"
aria-hidden="true"
{...props}
>
<circle cx="8" cy="8" r="6" fill="#ef4444" stroke="#000000" />
</svg>
);
}
Loading