From 6962beb8e2dff8e45eec4b97a2647043c7932230 Mon Sep 17 00:00:00 2001 From: shadcn Date: Fri, 16 Jun 2023 17:06:23 +0400 Subject: [PATCH] feat: implement sharing page --- app/layout.tsx | 4 +- app/share/[id]/page.tsx | 32 +++++++++--- app/sign-in/[[...sign-in]]/page.tsx | 10 +--- app/sign-up/[[...sign-up]]/page.tsx | 10 +--- components/chat-list.tsx | 4 +- components/chat-panel.tsx | 10 +--- components/footer.tsx | 23 +++++++++ components/header.tsx | 78 +++++++++++++++++------------ components/sidebar-item.tsx | 4 +- components/sidebar.tsx | 1 - middleware.ts | 4 +- tailwind.config.js | 2 +- 12 files changed, 113 insertions(+), 69 deletions(-) create mode 100644 components/footer.tsx diff --git a/app/layout.tsx b/app/layout.tsx index 7662f9e..8537650 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -48,7 +48,9 @@ export default function RootLayout({ children }: RootLayoutProps) {
{/* @ts-ignore */}
-
{children}
+
+ {children} +
diff --git a/app/share/[id]/page.tsx b/app/share/[id]/page.tsx index e487cd2..fad1b62 100644 --- a/app/share/[id]/page.tsx +++ b/app/share/[id]/page.tsx @@ -1,10 +1,11 @@ import { type Metadata } from 'next' -import { auth } from '@clerk/nextjs' - -import { Chat } from '@/components/chat' -import { getChat, getSharedChat } from '@/app/actions' import { notFound } from 'next/navigation' +import { formatDate } from '@/lib/utils' +import { getSharedChat } from '@/app/actions' +import { ChatList } from '@/components/chat-list' +import { FooterText } from '@/components/footer' + // export const runtime = 'edge' export const preferredRegion = 'home' @@ -17,8 +18,8 @@ export interface SharePageProps { export async function generateMetadata({ params }: SharePageProps): Promise { - const { user } = await auth() - const chat = await getChat(params.id, user?.id ?? '') + const chat = await getSharedChat(params.id) + return { title: chat?.title.slice(0, 50) ?? 'Chat' } @@ -31,5 +32,22 @@ export default async function SharePage({ params }: SharePageProps) { notFound() } - return + return ( + <> +
+
+
+
+

{chat.title}

+
+ {formatDate(chat.createdAt)} ยท {chat.messages.length} messages +
+
+
+
+ +
+ + + ) } diff --git a/app/sign-in/[[...sign-in]]/page.tsx b/app/sign-in/[[...sign-in]]/page.tsx index e5fc141..1e6c598 100644 --- a/app/sign-in/[[...sign-in]]/page.tsx +++ b/app/sign-in/[[...sign-in]]/page.tsx @@ -4,6 +4,7 @@ import { cn } from '@/lib/utils' import { ExternalLink } from '@/components/external-link' import { buttonVariants } from '@/components/ui/button' import { IconSpinner } from '@/components/ui/icons' +import { FooterText } from '@/components/footer' export default function SignInPage() { return ( @@ -27,14 +28,7 @@ export default function SignInPage() { } }} /> -

- Open source AI chatbot app built with{' '} - Next.js and{' '} - - Vercel KV - - . -

+ diff --git a/app/sign-up/[[...sign-up]]/page.tsx b/app/sign-up/[[...sign-up]]/page.tsx index aaadbcb..f30ecc3 100644 --- a/app/sign-up/[[...sign-up]]/page.tsx +++ b/app/sign-up/[[...sign-up]]/page.tsx @@ -4,6 +4,7 @@ import { cn } from '@/lib/utils' import { buttonVariants } from '@/components/ui/button' import { ExternalLink } from '@/components/external-link' import { IconSpinner } from '@/components/ui/icons' +import { FooterText } from '@/components/footer' export default function Page() { return ( @@ -28,14 +29,7 @@ export default function Page() { } }} /> -

- Open source AI chatbot app built with{' '} - Next.js and{' '} - - Vercel KV - - . -

+ diff --git a/components/chat-list.tsx b/components/chat-list.tsx index ef18c87..43a1588 100644 --- a/components/chat-list.tsx +++ b/components/chat-list.tsx @@ -17,7 +17,9 @@ export function ChatList({ messages }: ChatList) { {messages.map((message, index) => (
- {index < messages.length - 1 && } + {index < messages.length - 1 && ( + + )}
))} diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx index a6f01de..b48e346 100644 --- a/components/chat-panel.tsx +++ b/components/chat-panel.tsx @@ -5,6 +5,7 @@ import { ExternalLink } from '@/components/external-link' import { PromptForm } from '@/components/prompt-form' import { ButtonScrollToBottom } from '@/components/button-scroll-to-bottom' import { IconRefresh, IconStop } from '@/components/ui/icons' +import { FooterText } from '@/components/footer' export interface ChatPanelProps extends Pick< @@ -70,14 +71,7 @@ export function ChatPanel({ setInput={setInput} isLoading={isLoading} /> -

- Open source AI chatbot app built with{' '} - Next.js and{' '} - - Vercel KV - - . -

+ diff --git a/components/footer.tsx b/components/footer.tsx new file mode 100644 index 0000000..4b65095 --- /dev/null +++ b/components/footer.tsx @@ -0,0 +1,23 @@ +import React from 'react' + +import { ExternalLink } from '@/components/external-link' +import { cn } from '@/lib/utils' + +export function FooterText({ className, ...props }: React.ComponentProps<'p'>) { + return ( +

+ Open source AI chatbot built with{' '} + Next.js and{' '} + + Vercel KV + + . +

+ ) +} diff --git a/components/header.tsx b/components/header.tsx index 04b7c15..91398d1 100644 --- a/components/header.tsx +++ b/components/header.tsx @@ -1,4 +1,4 @@ -import { Suspense } from 'react' +import { Suspense, use } from 'react' import { cn } from '@/lib/utils' import { buttonVariants } from '@/components/ui/button' @@ -10,6 +10,7 @@ import { SidebarFooter } from '@/components/sidebar-footer' import { ThemeToggle } from '@/components/theme-toggle' import { ClearHistory } from '@/components/clear-history' import { clearChats } from '@/app/actions' +import Link from 'next/link' export async function Header() { const user = await currentUser() @@ -18,38 +19,53 @@ export async function Header() {
{/* @ts-ignore */} - - }> - {/* @ts-ignore */} - - - - - - - + {user?.id ? ( + + }> + {/* @ts-ignore */} + + + + + + + + ) : ( + + + + )}
- *]:dark:text-zinc-600', - userPreview: 'p-4 border-b border-border m-0', - userButtonPopoverActionButton: 'px-1 gap-1', - userButtonPopoverActionButtonText: - 'text-sm tracking-normal dark:text-zinc-400', - userButtonPopoverActionButtonIcon: - 'h-4 w-4 text-muted-foreground' - } - }} - /> + {user?.id ? ( + *]:dark:text-zinc-600', + userPreview: 'p-4 border-b border-border m-0', + userButtonPopoverActionButton: 'px-1 gap-1', + userButtonPopoverActionButtonText: + 'text-sm tracking-normal dark:text-zinc-400', + userButtonPopoverActionButtonIcon: + 'h-4 w-4 text-muted-foreground' + } + }} + /> + ) : ( + + Sign in + + )}
diff --git a/components/sidebar-item.tsx b/components/sidebar-item.tsx index 34d2bea..3e92c0f 100644 --- a/components/sidebar-item.tsx +++ b/components/sidebar-item.tsx @@ -27,7 +27,7 @@ export function SidebarItem({ chat, children }: SidebarItemProps) { return ( <> {chat.title}
- {children} + {isActive && children} ) diff --git a/components/sidebar.tsx b/components/sidebar.tsx index 87e4eff..e842b12 100644 --- a/components/sidebar.tsx +++ b/components/sidebar.tsx @@ -13,7 +13,6 @@ import { import { IconSidebar } from '@/components/ui/icons' export interface SidebarProps { - userId?: string children?: React.ReactNode } diff --git a/middleware.ts b/middleware.ts index 813dafe..217c3cf 100644 --- a/middleware.ts +++ b/middleware.ts @@ -1,7 +1,9 @@ import { authMiddleware } from '@clerk/nextjs' // @see https://clerk.dev -export default authMiddleware() +export default authMiddleware({ + publicRoutes: ['/share/:id'] +}) export const config = { matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'] diff --git a/tailwind.config.js b/tailwind.config.js index f37c844..93289bd 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -87,7 +87,7 @@ module.exports = { }, animation: { 'slide-from-left': - 'slide-from-left 0.4s cubic-bezier(0.82, 0.085, 0.395, 0.895)', + 'slide-from-left 0.3s cubic-bezier(0.82, 0.085, 0.395, 0.895)', 'slide-to-left': 'slide-to-left 0.25s cubic-bezier(0.82, 0.085, 0.395, 0.895)', 'accordion-down': 'accordion-down 0.2s ease-out',