Skip to content

Commit

Permalink
Add announcement
Browse files Browse the repository at this point in the history
  • Loading branch information
nzws committed Jun 6, 2024
1 parent e9a5033 commit d46bfab
Show file tree
Hide file tree
Showing 9 changed files with 523 additions and 1 deletion.
53 changes: 53 additions & 0 deletions apps/web/app/api/announcements/route.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Octokit } from 'octokit';

export const runtime = 'edge';
export const revalidate = 60 * 10;

const token = process.env.DISCUSSION_TOKEN;
const repo = process.env.DISCUSSION_REPOSITORY;
const octokit = new Octokit({
auth: token
});

export async function GET() {
if (!repo || !token) {
return Response.json(
{ error: 'DISCUSSION_REPOSITORY and DISCUSSION_TOKEN must be set' },
{ status: 400 }
);
}

try {
const discussions = await octokit.graphql<{
search: {
nodes: { __typename: string; url: string; title: string; id: string }[];
};
}>(
`
query ($searchQuery: String!) {
search(type: DISCUSSION, query: $searchQuery, first: 5) {
nodes {
__typename
... on Discussion {
url
title
id
}
}
}
}
`,
{
searchQuery: `repo:${repo} is:open label:pinned category:announcements`
}
);

return Response.json(discussions.search.nodes);
} catch (error) {
console.error(error);
return Response.json(
{ error: 'Failed to fetch discussions' },
{ status: 500 }
);
}
}
11 changes: 11 additions & 0 deletions apps/web/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
interface Props {
children: React.ReactNode;
}

export default function RootLayout({ children }: Props) {
return (
<html>
<body>{children}</body>
</html>
);
}
1 change: 1 addition & 0 deletions apps/web/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference types="next/navigation-types/compat/navigation" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
63 changes: 63 additions & 0 deletions apps/web/organisms/navbar/announcements.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Alert, CloseButton, Link } from '@chakra-ui/react';
import { Fragment, MouseEvent, useCallback, useMemo } from 'react';
import { useLocalStorage } from 'react-use';
import { useAnnouncements } from '~/utils/hooks/api/use-announcements';

export const Announcements = () => {
const [reads, setReads] = useLocalStorage<string[]>(
'knzklive-announcement-reads',
[]
);
const announcements = useAnnouncements();
const unreadAnnouncements = useMemo(
() =>
announcements?.filter(
announcement => !reads || !reads.includes(announcement.id)
),
[announcements, reads]
);

const handleRead = useCallback(
(e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
const id = e.currentTarget.dataset.id;
if (!id) {
return;
}

setReads(() => {
if (!reads) {
return [id];
}

return [...reads, id];
});
},
[setReads, reads]
);

return (
<Fragment>
{unreadAnnouncements?.map(announcement => (
<Alert status="info" py={2} px={3} key={announcement.id}>
<Link
href={announcement.url}
target="_blank"
rel="noopener noreferrer"
_hover={{ textDecoration: 'underline' }}
isTruncated
>
{announcement.title}
</Link>

<CloseButton
size="sm"
ml="auto"
onClick={handleRead}
data-id={announcement.id}
/>
</Alert>
))}
</Fragment>
);
};
3 changes: 3 additions & 0 deletions apps/web/organisms/navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { LoginModal } from './login-modal';
import { User } from './user';
import { LiveInfoModal } from '../live/admin/live-info-modal';
import { useRouter } from 'next/router';
import { Announcements } from './announcements';

export const Navbar: FC = () => {
const router = useRouter();
Expand Down Expand Up @@ -86,6 +87,8 @@ export const Navbar: FC = () => {
/>
)}

<Announcements />

<Box as="nav">
<Container py={{ base: 3 }} maxW="full">
<HStack
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"mux-embed": "5.2.1",
"next": "14.2.3",
"nextjs-progressbar": "0.0.16",
"octokit": "4.0.2",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-icons": "5.2.1",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"~/*": ["./*"]
}
},
"include": ["**/*.ts", "**/*.tsx"],
"include": ["**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules", ".next"]
}
20 changes: 20 additions & 0 deletions apps/web/utils/hooks/api/use-announcements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import useSWR from 'swr';

const fetcher = (...args: Parameters<typeof fetch>) =>
fetch(...args).then(res => res.json());

export const useAnnouncements = () => {
const { data } = useSWR<
{
url: string;
title: string;
id: string;
}[]
>('/api/announcements', fetcher, {
revalidateOnFocus: false,
revalidateOnReconnect: false,
revalidateIfStale: false
});

return data;
};
Loading

0 comments on commit d46bfab

Please sign in to comment.