Skip to content

Commit cd04001

Browse files
initial - email client
0 parents  commit cd04001

31 files changed

+17981
-0
lines changed

.eslintrc.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "next/core-web-vitals"
3+
}

.gitignore

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
.yarn/install-state.gz
8+
9+
# testing
10+
/coverage
11+
12+
# next.js
13+
/.next/
14+
/out/
15+
16+
# production
17+
/build
18+
19+
# misc
20+
.DS_Store
21+
*.pem
22+
23+
# debug
24+
npm-debug.log*
25+
yarn-debug.log*
26+
yarn-error.log*
27+
28+
# local env files
29+
.env*.local
30+
31+
# vercel
32+
.vercel
33+
34+
# typescript
35+
*.tsbuildinfo
36+
next-env.d.ts

README.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2+
3+
## Getting Started
4+
5+
First, run the development server:
6+
7+
```bash
8+
npm run dev
9+
# or
10+
yarn dev
11+
# or
12+
pnpm dev
13+
# or
14+
bun dev
15+
```
16+
17+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18+
19+
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20+
21+
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
22+
23+
## Learn More
24+
25+
To learn more about Next.js, take a look at the following resources:
26+
27+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29+
30+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
31+
32+
## Deploy on Vercel
33+
34+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35+
36+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

app/favicon.ico

25.3 KB
Binary file not shown.

app/globals.css

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
5+
@layer base {
6+
:root {
7+
--copilot-kit-primary-color: black;
8+
9+
--background: 0 0% 100%;
10+
--foreground: 0 0% 3.9%;
11+
--card: 0 0% 100%;
12+
--card-foreground: 0 0% 3.9%;
13+
--popover: 0 0% 100%;
14+
--popover-foreground: 0 0% 3.9%;
15+
--primary: 0 0% 9%;
16+
--primary-foreground: 0 0% 98%;
17+
--secondary: 0 0% 96.1%;
18+
--secondary-foreground: 0 0% 9%;
19+
--muted: 0 0% 96.1%;
20+
--muted-foreground: 0 0% 45.1%;
21+
--accent: 0 0% 96.1%;
22+
--accent-foreground: 0 0% 9%;
23+
--destructive: 0 84.2% 60.2%;
24+
--destructive-foreground: 0 0% 98%;
25+
--border: 0 0% 89.8%;
26+
--input: 0 0% 89.8%;
27+
--ring: 0 0% 3.9%;
28+
--radius: 0.5rem;
29+
--chart-1: 12 76% 61%;
30+
--chart-2: 173 58% 39%;
31+
--chart-3: 197 37% 24%;
32+
--chart-4: 43 74% 66%;
33+
--chart-5: 27 87% 67%;
34+
}
35+
36+
.dark {
37+
--background: 0 0% 3.9%;
38+
--foreground: 0 0% 98%;
39+
--card: 0 0% 3.9%;
40+
--card-foreground: 0 0% 98%;
41+
--popover: 0 0% 3.9%;
42+
--popover-foreground: 0 0% 98%;
43+
--primary: 0 0% 98%;
44+
--primary-foreground: 0 0% 9%;
45+
--secondary: 0 0% 14.9%;
46+
--secondary-foreground: 0 0% 98%;
47+
--muted: 0 0% 14.9%;
48+
--muted-foreground: 0 0% 63.9%;
49+
--accent: 0 0% 14.9%;
50+
--accent-foreground: 0 0% 98%;
51+
--destructive: 0 62.8% 30.6%;
52+
--destructive-foreground: 0 0% 98%;
53+
--border: 0 0% 14.9%;
54+
--input: 0 0% 14.9%;
55+
--ring: 0 0% 83.1%;
56+
--chart-1: 220 70% 50%;
57+
--chart-2: 160 60% 45%;
58+
--chart-3: 30 80% 55%;
59+
--chart-4: 280 65% 60%;
60+
--chart-5: 340 75% 55%;
61+
}
62+
}
63+
64+
@layer base {
65+
* {
66+
@apply border-border;
67+
}
68+
body {
69+
@apply bg-background text-foreground;
70+
}
71+
}
72+
73+
.copilotKitDevConsole {
74+
@apply hidden !important;
75+
}
76+

app/layout.tsx

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { Metadata } from "next";
2+
import { Inter } from "next/font/google";
3+
import "./globals.css";
4+
import { Suspense } from "react";
5+
6+
const inter = Inter({ subsets: ["latin"] });
7+
8+
export const metadata: Metadata = {
9+
title: "CopilotKit Todos",
10+
description: "A simple todo app using CopilotKit",
11+
};
12+
13+
export default function RootLayout({
14+
children,
15+
}: Readonly<{
16+
children: React.ReactNode;
17+
}>) {
18+
return (
19+
<html lang="en">
20+
<body className={inter.className}>
21+
<Suspense>{children}</Suspense>
22+
</body>
23+
</html>
24+
);
25+
}

app/page.tsx

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"use client";
2+
3+
import { EmailThread } from "@/components/EmailThread";
4+
import { ProvideApiKeyDialog } from "@/components/ProvideApiKeyDialog";
5+
import { EmailsProvider } from "@/lib/hooks/use-email";
6+
import { CopilotKit } from "@copilotkit/react-core";
7+
import "@copilotkit/react-ui/styles.css";
8+
import { useSearchParams } from "next/navigation";
9+
10+
export default function Home() {
11+
const searchParams = useSearchParams();
12+
const publicApiKey = searchParams.get("publicApiKey");
13+
14+
return (
15+
<>
16+
<div className="h-screen flex flex-col">
17+
<div className="flex-[0_0_auto]">
18+
<ProvideApiKeyDialog />
19+
</div>
20+
<div className="flex-1">
21+
<CopilotKit publicApiKey={(publicApiKey as string) || "undefined"}>
22+
<EmailsProvider>
23+
<EmailThread />
24+
</EmailsProvider>
25+
</CopilotKit>
26+
</div>
27+
</div>
28+
</>
29+
);
30+
}

components.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "default",
4+
"rsc": true,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "tailwind.config.ts",
8+
"css": "app/globals.css",
9+
"baseColor": "neutral",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils"
16+
}
17+
}

components/EmailThread.tsx

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { Button } from "@/components/ui/button";
2+
import { Textarea } from "@/components/ui/textarea";
3+
import { useEmails } from "@/lib/hooks/use-email";
4+
import { useState } from "react";
5+
6+
export function EmailThread() {
7+
const [input, setInput] = useState("");
8+
const { emails, addEmail } = useEmails();
9+
10+
const handleReply = () => {
11+
console.log(input);
12+
addEmail({
13+
from: "me",
14+
to: "John Doe <[email protected]>",
15+
body: input,
16+
timestamp: new Date().toISOString(),
17+
});
18+
setInput("");
19+
};
20+
21+
return (
22+
<main className="flex h-full flex-col items-center justify-between">
23+
<div className="flex h-full w-full flex-col">
24+
<header className="border-b px-6 py-4">
25+
<h2 className="text-2xl font-semibold">
26+
Email Thread: Project Kickoff Meeting
27+
</h2>
28+
</header>
29+
<div className="flex flex-1">
30+
<div className="flex w-full flex-col border-r bg-muted">
31+
<div className="flex-1 overflow-y-auto p-4">
32+
<div className="space-y-4">
33+
{emails.map((email) => (
34+
<div
35+
key={`${email.from}-${email.timestamp}`}
36+
className="rounded-md border bg-background p-4 space-y-1"
37+
>
38+
<p className="text-sm text-muted-foreground">
39+
{new Date(email.timestamp).toLocaleDateString()}{" "}
40+
{new Date(email.timestamp).toLocaleTimeString([], {
41+
hour: "2-digit",
42+
minute: "2-digit",
43+
hour12: true,
44+
})}
45+
</p>
46+
<div className="flex items-center justify-between">
47+
<div className="space-y-1">
48+
<p className="text-sm font-medium">
49+
<span className="text-muted-foreground">From:</span>{" "}
50+
{email.from}
51+
</p>
52+
<p className="text-sm font-medium">
53+
<span className="text-muted-foreground">To:</span>{" "}
54+
{email.to}
55+
</p>
56+
<p className="text-sm text-muted-foreground">
57+
{email.body}
58+
</p>
59+
</div>
60+
</div>
61+
</div>
62+
))}
63+
64+
<hr className="my-2" />
65+
66+
<div className="mt-4 pt-4 space-y-2 bg-background p-4 rounded-md border">
67+
<Textarea
68+
className="min-h-40"
69+
value={input}
70+
onChange={(e) => setInput(e.target.value)}
71+
placeholder="Write your reply..."
72+
/>
73+
<Button disabled={!input} onClick={handleReply}>
74+
Reply
75+
</Button>
76+
</div>
77+
</div>
78+
</div>
79+
</div>
80+
</div>
81+
</div>
82+
</main>
83+
);
84+
}

0 commit comments

Comments
 (0)