implemented "ask ai"

This commit is contained in:
2026-02-05 16:27:28 +00:00
parent cc740265ea
commit 5d9c5eaa93
4 changed files with 69 additions and 33 deletions

View File

@@ -1,12 +1,14 @@
import { AskAI } from "@/components/ask-ai";
import { ProjectListItem } from "@/components/ProjectListItem"; import { ProjectListItem } from "@/components/ProjectListItem";
import { type ProjectEntry, projectList, projects } from "@/projects"; import { type ProjectEntry, projectList, projects } from "@/projects";
import { Downasaur, Home as HomeIcon } from "@nsmr/pixelart-react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Link, Route, Routes, useParams } from "react-router-dom"; import { Link, Route, Routes, useParams } from "react-router-dom";
import { ThemeToggle } from "./components/theme-toggle"; import { ThemeToggle } from "./components/theme-toggle";
const asciiFiles = [ const asciiFiles = [
"cat-sleep.txt", "cat-sleep.txt",
// "polar-bear.txt", "polar-bear.txt",
"penguin-surfboard.txt", "penguin-surfboard.txt",
"cat-shock.txt", "cat-shock.txt",
"exclamation.txt", "exclamation.txt",
@@ -53,10 +55,10 @@ function Home() {
}, [asciiFile]); }, [asciiFile]);
return ( return (
<div className="min-h-dvh flex flex-col items-center gap-8 text-2xl px-6 py-10"> <div className="min-h-dvh flex flex-col items-center gap-2 text-2xl px-6 py-10">
<div className="flex flex-col items-center gap-8"> <div className="flex flex-col items-center gap-8 mb-4">
{asciiArt ? ( {asciiArt ? (
<pre className="leading-1.75 tracking-[-1.75px]"> <pre className="text-[#000000] leading-1.75 tracking-[-1.75px]">
<code className="commitmono text-[11px]">{asciiArt}</code> <code className="commitmono text-[11px]">{asciiArt}</code>
</pre> </pre>
) : null} ) : null}
@@ -73,7 +75,10 @@ function Home() {
/> />
))} ))}
</div> </div>
<ThemeToggle /> <div className="w-full max-w-5xl flex items-center justify-between gap-4">
<AskAI name="me" inline />
<ThemeToggle />
</div>
</div> </div>
); );
} }
@@ -88,15 +93,32 @@ function ProjectRoute() {
function NotFound() { function NotFound() {
return ( return (
<div className="min-h-dvh flex flex-col items-center justify-center gap-4 text-2xl"> <div
<h1 className="text-4xl text-accent text-balance">Not found</h1> className={`w-full h-[100vh] flex flex-col items-center justify-center gap-4`}
<Link className="text-accent underline" to="/"> >
Go home <span className="-ml-14 -mb-7 -rotate-20 text-xl text-accent">?</span>
<Downasaur size={72} className="text-accent" />
<span className="text-7xl">404</span>
<span className="text-2xl">Not Found</span>
<Link to="/">
<HomeIcon className="size-12 hover:text-accent" />
</Link> </Link>
</div> </div>
); );
} }
// function NotFound() {
// return (
// <div className="min-h-dvh flex flex-col items-center justify-center gap-4 text-2xl">
// <Downasaur className="size-24 text-accent" />
// <Link to="/">
// <HomeIcon className="size-12 hover:text-accent" />
// </Link>
// </div>
// );
// }
function parseDate(dateStr: string): Date { function parseDate(dateStr: string): Date {
const lower = dateStr.toLowerCase(); const lower = dateStr.toLowerCase();

View File

@@ -1,22 +1,26 @@
import { getProjectPrompt } from "@/lib/constants";
import type { ProjectMetadata } from "@/projects";
import { Home } from "@nsmr/pixelart-react";
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import type { ProjectMetadata } from "@/projects"; import { AskAI } from "./ask-ai";
type ProjectPageProps = { export function ProjectPage({
metadata,
children,
}: {
metadata: ProjectMetadata; metadata: ProjectMetadata;
children: ReactNode; children: ReactNode;
}; }) {
export function ProjectPage({ metadata, children }: ProjectPageProps) {
const tags = metadata.tags ? [...metadata.tags].sort() : []; const tags = metadata.tags ? [...metadata.tags].sort() : [];
return ( return (
<div className="mx-auto w-full max-w-4xl px-6 py-10 text-md"> <div className="mx-auto w-full max-w-4xl px-6 py-4 text-md border my-8">
<Link <Link
to="/" to="/"
className="inline-flex items-center text-sm text-green-500 hover:underline mb-4" className="inline-flex items-center text-sm hover:text-accent mb-4"
> >
Home <Home />
</Link> </Link>
<div className="flex flex-wrap items-start justify-between gap-6 mb-4"> <div className="flex flex-wrap items-start justify-between gap-6 mb-4">
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
@@ -33,19 +37,27 @@ export function ProjectPage({ metadata, children }: ProjectPageProps) {
<div className="w-24 h-24 mb-2 border rounded" /> <div className="w-24 h-24 mb-2 border rounded" />
)} )}
</div> </div>
<div className="flex flex-col items-end gap-2"> <AskAI
{metadata.url ? ( name={metadata.title}
<a prompt={getProjectPrompt(
href={metadata.url} metadata.title,
target="_blank" metadata.description,
rel="noopener noreferrer" metadata.slug,
className="link-project-page inline-block text-sm" )}
> />
Try {metadata.title}
</a>
) : null}
</div>
</div> </div>
{metadata.url ? (
<div className="flex flex-col mb-2">
<a
href={metadata.url}
target="_blank"
rel="noopener noreferrer"
className="link-project-page inline-block text-accent hover:underline underline-offset-2 text-sm"
>
Try {metadata.title}
</a>
</div>
) : null}
<p className="text-sm mb-2"> <p className="text-sm mb-2">
{metadata.date} {metadata.date}

View File

@@ -1,6 +1,6 @@
import { Moon, Sun } from "@nsmr/pixelart-react";
import { useTheme } from "@/components/theme-provider"; import { useTheme } from "@/components/theme-provider";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Moon, Sun } from "@nsmr/pixelart-react";
export function ThemeToggle() { export function ThemeToggle() {
const { resolvedTheme, setTheme } = useTheme(); const { resolvedTheme, setTheme } = useTheme();
@@ -8,11 +8,12 @@ export function ThemeToggle() {
return ( return (
<Button <Button
variant="outline" variant="dummy"
size="sm" size="icon-sm"
onClick={() => setTheme(isDark ? "light" : "dark")} onClick={() => setTheme(isDark ? "light" : "dark")}
className="hover:fill-accent hover:text-accent"
> >
{isDark ? <Sun /> : <Moon />} {isDark ? <Sun className="size-6" /> : <Moon className="size-6" />}
</Button> </Button>
); );
} }

View File

@@ -19,6 +19,7 @@ const buttonVariants = cva(
ghost: ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline", link: "text-primary underline-offset-4 hover:underline",
dummy: "",
}, },
size: { size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3", default: "h-9 px-4 py-2 has-[>svg]:px-3",