Skip to content

Commit

Permalink
feat: gradually building token page
Browse files Browse the repository at this point in the history
  • Loading branch information
GuiBibeau committed Nov 18, 2024
1 parent b39286c commit 162a520
Show file tree
Hide file tree
Showing 43 changed files with 38,379 additions and 469 deletions.
2 changes: 1 addition & 1 deletion app/api/search/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export async function POST(request: Request) {
return Response.json({ error: "Query is required" }, { status: 400 });
}

const searchTool = new SearchTool("BraveSearch");
const searchTool = new SearchTool();
const searchResults = await searchTool.search(query);

if (!searchResults) {
Expand Down
6 changes: 5 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Exo_2 } from "next/font/google";
import localFont from "next/font/local";
import "./globals.css";
import { Analytics } from "@vercel/analytics/react";
import { NavBar } from "@/components/NavBar";

const exo2 = Exo_2({
subsets: ["latin"],
Expand Down Expand Up @@ -36,7 +37,10 @@ export default function RootLayout({
<body
className={`${exo2.variable} ${geistSans.variable} ${geistMono.variable} font-sans antialiased bg-white text-black`}
>
{children}
<div className="min-h-screen flex flex-col">
<NavBar />
{children}
</div>
<Analytics />
</body>
</html>
Expand Down
30 changes: 30 additions & 0 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Link from "next/link";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { HomeIcon } from "lucide-react";

export default function NotFound() {
return (
<div className="min-h-screen flex flex-col items-center justify-center p-4">
<Card className="w-full max-w-md">
<CardContent className="pt-6 text-center">
<div className="mb-6">
<h1 className="text-4xl font-bold mb-2">404</h1>
<p className="text-muted-foreground">
Oops! The page you&apos;re looking for doesn&apos;t exist.
</p>
</div>
<Link href="/">
<Button
variant="default"
className="gap-2 bg-black text-white hover:bg-black/70"
>
<HomeIcon className="h-4 w-4" />
Back to Home
</Button>
</Link>
</CardContent>
</Card>
</div>
);
}
10 changes: 3 additions & 7 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { NavBar } from "@/components/NavBar";
import { SearchBar } from "./SearchBar";
import { SearchBar } from "./search-bar";

import { Metadata } from "next";

Expand Down Expand Up @@ -35,11 +34,8 @@ export const metadata: Metadata = {
export default async function Home() {
return (
<div className="min-h-screen flex flex-col relative">
<div className="relative flex flex-col min-h-screen">
<NavBar />
<div className="flex-grow flex flex-col items-center justify-center p-4">
<SearchBar />
</div>
<div className="flex-grow flex flex-col items-center justify-center p-4">
<SearchBar />
</div>
</div>
);
Expand Down
18 changes: 0 additions & 18 deletions app/prototype/page.tsx

This file was deleted.

7 changes: 4 additions & 3 deletions app/SearchBar.tsx → app/search-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Link from "next/link";
import { redirect } from "next/navigation";
import { track } from "@vercel/analytics/server";
import { SearchForm } from "./SearchForm";
import { SearchForm } from "./search-form";
import { createParamFromString } from "@/lib/create-param-from-string";

async function searchAction(formData: FormData) {
"use server";
const query = formData.get("query")?.toString();
if (query?.trim()) {
track("search", { query });
redirect(`/search?q=${encodeURIComponent(query)}`);
redirect(`/search/${createParamFromString(query)}`);
}
}

Expand All @@ -35,7 +36,7 @@ export function SearchBar() {
function SearchPill({ emoji, query }: { emoji: string; query: string }) {
return (
<Link
href={`/search?q=${encodeURIComponent(query)}`}
href={`/prototype/${createParamFromString(query)}`}
className="border hover:bg-gray-100 transition-all duration-300 ease-in-out px-4 py-2 rounded-lg text-sm inline-flex items-center"
>
{emoji} {query}
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions app/search/[query]/@sources/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function SourcesPage() {
return <div>SourcesPage</div>;
}
3 changes: 3 additions & 0 deletions app/search/[query]/@summary/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function SummaryPage() {
return <div>SummaryPage</div>;
}
25 changes: 25 additions & 0 deletions app/search/[query]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createStringFromParam } from "@/lib/create-param-from-string";

export default async function PrototypeLayout({
children,

...props
}: {
children: React.ReactNode;
sources: React.ReactNode;
summary: React.ReactNode;
params: Promise<{ query?: string }>;
}) {
const params = await props.params;
const query = params.query;
const searchPrompt = createStringFromParam(query!);

return (
<main className="flex-grow flex justify-center p-4">
<div className="w-full max-w-4xl space-y-6">
<h1 className="text-3xl font-bold">{searchPrompt}</h1>
{children}
</div>
</main>
);
}
11 changes: 11 additions & 0 deletions app/search/[query]/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { SourcesSkeleton } from "./sources-skeleton";
import { StreamingSummarySkeleton } from "./streaming-summary-skeleton";

export default function Loading() {
return (
<>
<SourcesSkeleton />
<StreamingSummarySkeleton />
</>
);
}
30 changes: 30 additions & 0 deletions app/search/[query]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { createStringFromParam } from "@/lib/create-param-from-string";
import { processSearchResults } from "@/lib/processSearchResults";
import { SearchTool } from "@/lib/SearchTool";
import { Metadata } from "next";
import { Sources } from "./sources";
import { StreamingSummary } from "./streaming-summary";

export const metadata: Metadata = {
title: "Prototype Page",
description: "A basic Next.js prototype page",
};

export default async function PrototypePage(props: {
params: Promise<{ query?: string }>;
}) {
const params = await props.params;
const query = params.query;
const searchPrompt = createStringFromParam(query!);

const searchTool = new SearchTool();
const searchResults = await searchTool.search(searchPrompt!).then();
const processedResults = processSearchResults(searchResults!);

return (
<>
<Sources sources={processedResults.slice(0, 4)} />
<StreamingSummary query={searchPrompt} sources={processedResults} />
</>
);
}
32 changes: 32 additions & 0 deletions app/search/[query]/sources-skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Card, CardContent } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";

export function SourcesSkeleton() {
return (
<div className="w-full space-y-4">
<h2 className="text-2xl font-semibold">Sources</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{Array.from({ length: 4 }).map((_, index) => (
<Card key={index} className="overflow-hidden">
<CardContent className="p-4 h-full flex flex-col justify-between">
<div className="space-y-2">
<div className="flex items-start justify-between">
<Skeleton className="h-5 w-3/4" />
<Skeleton className="h-5 w-5 rounded-sm" />
</div>
<div className="space-y-1">
<Skeleton className="h-3 w-full" />
<Skeleton className="h-3 w-4/5" />
</div>
</div>
<div className="flex items-center justify-between mt-4">
<Skeleton className="h-3 w-24" />
<Skeleton className="h-3 w-16" />
</div>
</CardContent>
</Card>
))}
</div>
</div>
);
}
12 changes: 6 additions & 6 deletions app/search/sources.tsx → app/search/[query]/sources.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function Sources({ sources }: SourcesProps) {
rel="noopener noreferrer"
className="no-underline"
>
<CardContent className="p-4 h-full flex flex-col justify-between">
<CardContent className="p-4 h-full flex flex-col justify-between relative">
<div className="space-y-2">
<div className="flex items-start justify-between">
<h3 className="text-sm font-semibold text-primary line-clamp-1 flex-grow pr-2">
Expand All @@ -54,16 +54,16 @@ export function Sources({ sources }: SourcesProps) {
</p>
</div>
<div className="flex items-center justify-between mt-4 text-xs text-muted-foreground">
<span className="truncate max-w-[calc(100%-4rem)]">
<span className="truncate max-w-[calc(100%-6rem)]">
{result.source}
</span>
<span>{result.date}</span>
<span className="flex items-center gap-2">
{result.date}
<ExternalLinkIcon className="w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</div>
</CardContent>
</a>
<div className="absolute bottom-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity">
<ExternalLinkIcon className="w-4 h-4 text-muted-foreground" />
</div>
</Card>
))}
</div>
Expand Down
26 changes: 26 additions & 0 deletions app/search/[query]/streaming-summary-skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { FileText } from "lucide-react";

export const StreamingSummarySkeleton = () => {
return (
<Card className="w-full mt-10">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg font-semibold">
<FileText className="w-5 h-5" />
Summary
</CardTitle>
</CardHeader>
<CardContent>
<div className="mb-4">
<div className="w-24 h-6 bg-muted animate-pulse rounded-full" />
</div>
<div className="space-y-3">
<div className="h-4 bg-muted animate-pulse rounded" />
<div className="h-4 bg-muted animate-pulse rounded w-[95%]" />
<div className="h-4 bg-muted animate-pulse rounded w-[90%]" />
<div className="h-4 bg-muted animate-pulse rounded w-[85%]" />
</div>
</CardContent>
</Card>
);
};
Loading

0 comments on commit 162a520

Please sign in to comment.